Merge branch 'dev' into cls-301
# Conflicts: # clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/validation/ProfileDocumentValidationConfig.java # clearing-parent/pom.xml # platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InstrumentType.java
This commit is contained in:
commit
e92cb8cc8e
94 changed files with 2928 additions and 512 deletions
|
|
@ -53,7 +53,7 @@ public class BankAccountValidationConfig {
|
|||
Company.class,
|
||||
AccountError.RequiredFieldEmpty,
|
||||
AccountError.CompanyNotFound,
|
||||
company -> WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : AccountError.CompanyNotActive),
|
||||
false),
|
||||
FieldRequiredRule.instance("account",
|
||||
BankAccountNewRequest::getAccount,
|
||||
AccountError.RequiredFieldEmpty,
|
||||
|
|
@ -83,9 +83,6 @@ public class BankAccountValidationConfig {
|
|||
AccountError.RequiredFieldEmpty),
|
||||
FieldRequiredRule.instance("bankName",
|
||||
BankAccountNewRequest::getBankName,
|
||||
AccountError.RequiredFieldEmpty),
|
||||
FieldRequiredRule.instance("destination",
|
||||
BankAccountNewRequest::getDestination,
|
||||
AccountError.RequiredFieldEmpty)
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,24 +48,6 @@ public class BankAccountNewAction implements IAction<BankAccountNewRequest> {
|
|||
@JsonProperty
|
||||
private Long companyId;
|
||||
|
||||
@Override
|
||||
public Collection<EnumMessage> validate() {
|
||||
List<EnumMessage> errors = new ArrayList<>();
|
||||
if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(correspondentAccount)) {
|
||||
errors.add(new EnumMessage(BackEndError.ValidationError, "correspondentAccount"));
|
||||
}
|
||||
if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(correspondentAccountName)) {
|
||||
errors.add(new EnumMessage(BackEndError.ValidationError, "correspondentAccountName"));
|
||||
}
|
||||
if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(taxpayerIdentificationNumber)) {
|
||||
errors.add(new EnumMessage(BackEndError.ValidationError, "taxpayerIdentificationNumber"));
|
||||
}
|
||||
if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(taxRegistrationReasonCode)) {
|
||||
errors.add(new EnumMessage(BackEndError.ValidationError, "taxRegistrationReasonCode"));
|
||||
}
|
||||
return errors.isEmpty() ? Collections.emptyList() : errors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BankAccountNewRequest toRequest() {
|
||||
var req = new BankAccountNewRequest();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ public class MoneyMarketSecurityNewAction implements IAction<MoneyMarketSecurity
|
|||
@ApiModelProperty(value = "Полное наименование инструмента", example = "NAME A")
|
||||
@JsonProperty
|
||||
public String fullName;
|
||||
@ApiModelProperty(value = "Нотация наименования инструмента", example = "NOTE")
|
||||
@JsonProperty
|
||||
public String convention;
|
||||
@ApiModelProperty(value = "Размер лота", example = "21.55")
|
||||
@JsonProperty
|
||||
public BigDecimal lotSize;
|
||||
|
|
@ -84,6 +87,7 @@ public class MoneyMarketSecurityNewAction implements IAction<MoneyMarketSecurity
|
|||
req.setNominalCurrency(this.getNominalCurrency());
|
||||
req.setInstrumentType(this.getInstrumentType());
|
||||
req.setFullName(this.getFullName());
|
||||
req.setConvention(this.getConvention());
|
||||
req.setSecuritySymbol(this.getSecuritySymbol());
|
||||
req.setLotSize(this.getLotSize());
|
||||
req.setShortName(this.getShortName());
|
||||
|
|
@ -128,6 +132,14 @@ public class MoneyMarketSecurityNewAction implements IAction<MoneyMarketSecurity
|
|||
this.fullName = fullName;
|
||||
}
|
||||
|
||||
public String getConvention() {
|
||||
return convention;
|
||||
}
|
||||
|
||||
public void setConvention(String convention) {
|
||||
this.convention = convention;
|
||||
}
|
||||
|
||||
public BigDecimal getLotSize() {
|
||||
return lotSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ public class MoneyMarketSecurityUpdateAction implements IAction<MoneyMarketSecur
|
|||
@ApiModelProperty(value = "Полное наименование инструмента", example = "NAME A")
|
||||
@JsonProperty
|
||||
public String fullName;
|
||||
@ApiModelProperty(value = "Нотация наименования инструмента", example = "NOTE")
|
||||
@JsonProperty
|
||||
public String convention;
|
||||
@ApiModelProperty(value = "Размер лота", example = "21.55")
|
||||
@JsonProperty
|
||||
public BigDecimal lotSize;
|
||||
|
|
@ -86,6 +89,7 @@ public class MoneyMarketSecurityUpdateAction implements IAction<MoneyMarketSecur
|
|||
req.setNominalCurrency(this.getNominalCurrency());
|
||||
req.setInstrumentType(this.getInstrumentType());
|
||||
req.setFullName(this.getFullName());
|
||||
req.setConvention(this.getConvention());
|
||||
req.setSecuritySymbol(this.getSecuritySymbol());
|
||||
req.setLotSize(this.getLotSize());
|
||||
req.setShortName(this.getShortName());
|
||||
|
|
@ -139,6 +143,14 @@ public class MoneyMarketSecurityUpdateAction implements IAction<MoneyMarketSecur
|
|||
this.fullName = fullName;
|
||||
}
|
||||
|
||||
public String getConvention() {
|
||||
return convention;
|
||||
}
|
||||
|
||||
public void setConvention(String convention) {
|
||||
this.convention = convention;
|
||||
}
|
||||
|
||||
public BigDecimal getLotSize() {
|
||||
return lotSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<meta version="3.5.0.6">
|
||||
<meta version="3.5.0.7">
|
||||
<enums>
|
||||
<allowed id="1" code="ALWD" name="Разрешено"/>
|
||||
<allowed id="2" code="DEND" name="Запрещено"/>
|
||||
|
|
@ -152,17 +152,30 @@
|
|||
<registryUnit id="2" code="F" name="Свободные"/>
|
||||
<registryUnit id="3" code="B" name="Заблокированные"/>
|
||||
<registryUnit id="4" code="C" name="Комиссия"/>
|
||||
<registryCode id="1" code="AMPT" name="Денежные средства - на торги"/>
|
||||
<registryCode id="2" code="AMPF" name="Денежные средства - свободные"/>
|
||||
<registryCode id="3" code="AMPB" name="Денежные средства - блокированные"/>
|
||||
<registryCode id="4" code="TMPT" name="Требования по деньгам - клиринговый пул"/>
|
||||
<registryCode id="5" code="OSPT" name="Обязательства по инструментам - клиринговый пул"/>
|
||||
<registryCode id="6" code="OMPT" name="Обязательства по деньгам - клиринговый пул"/>
|
||||
<registryCode id="7" code="TSPT" name="Требования по инструментам - клиринговый пул"/>
|
||||
<registryCode id="8" code="CMPT" name="Требования по деньгам - свои"/>
|
||||
<registryCode id="9" code="LSPT" name="Обязательства по инструментам - свои"/>
|
||||
<registryCode id="10" code="LMPT" name="Обязательства по деньгам - свои"/>
|
||||
<registryCode id="11" code="CSPT" name="Требования по инструментам - свои"/>
|
||||
<registryCode id="1" code="AMAT" name="Денежные средства - на торги"/>
|
||||
<registryCode id="2" code="AMAF" name="Денежные средства - свободные"/>
|
||||
<registryCode id="3" code="AMAB" name="Денежные средства - блокированные"/>
|
||||
<registryCode id="4" code="TMAT" name="Требования по деньгам - клиринговый пул"/>
|
||||
<registryCode id="5" code="OSAT" name="Обязательства по инструментам - клиринговый пул"/>
|
||||
<registryCode id="6" code="OMAT" name="Обязательства по деньгам - клиринговый пул"/>
|
||||
<registryCode id="7" code="TSAT" name="Требования по инструментам - клиринговый пул"/>
|
||||
<registryCode id="8" code="CMAT" name="Требования по деньгам - свои"/>
|
||||
<registryCode id="9" code="LSAT" name="Обязательства по инструментам - свои"/>
|
||||
<registryCode id="10" code="LMAT" name="Обязательства по деньгам - свои"/>
|
||||
<registryCode id="11" code="CSAT" name="Требования по инструментам - свои"/>
|
||||
<registryCode id="12" code="AMBT" name="Денежные средства клиента - на торги"/>
|
||||
<registryCode id="13" code="AMBF" name="Денежные средства клиента - свободные"/>
|
||||
<registryCode id="14" code="AMBB" name="Денежные средства клиента - блокированные"/>
|
||||
<registryCode id="15" code="TMBT" name="Требования по деньгам клиента - клиринговый пул"/>
|
||||
<registryCode id="16" code="OSBT" name="Обязательства по инструментам клиента - клиринговый пул"/>
|
||||
<registryCode id="17" code="OMBT" name="Обязательства по деньгам клиента - клиринговый пул"/>
|
||||
<registryCode id="18" code="TSBT" name="Требования по инструментам клиента - клиринговый пул"/>
|
||||
<registryCode id="19" code="CMBT" name="Требования по деньгам - клиента"/>
|
||||
<registryCode id="20" code="LSBT" name="Обязательства по инструментам - клиента"/>
|
||||
<registryCode id="21" code="LMBT" name="Обязательства по деньгам - клиента"/>
|
||||
<registryCode id="22" code="CSBT" name="Требования по инструментам - клиента"/>
|
||||
<registryCode id="23" code="DMAT" name="Возврат депозита по деньгам - свои"/>
|
||||
<registryCode id="24" code="DMBT" name="Возврат депозита по деньгам - клиента"/>
|
||||
<registryStatus id="1" code="OK" name="Успешно"/>
|
||||
<registryStatus id="2" code="UNCV" name="Не исполнено"/>
|
||||
<registryStatus id="3" code="FAIL" name="Не исполнено контрагентом"/>
|
||||
|
|
@ -538,6 +551,7 @@
|
|||
<market id="78" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UMIC" name="ОФЗИН-Режим непрерывных торгов" exchangeId="1" description="ОФЗИН-Режим непрерывных торгов: Облигации Минфина"/>
|
||||
<market id="79" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DMIC" name="ОФЗИН-Дискретный аукцион" exchangeId="1" description="ОФЗИН-Дискретный аукцион: Облигации Минфина"/>
|
||||
<market id="80" marketType="SCND" section="FOND" settlementCurrency="RUB" code="MMIC" name="ОФЗИН-Торги в режиме выкупа" exchangeId="1" description="ОФЗИН-Торги в режиме выкупа: Облигации Минфина"/>
|
||||
<market id="81" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="MKRS" name="Размещение" exchangeId="1" description="Размещение: МКР"/>
|
||||
</objects>
|
||||
</meta>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
{
|
||||
"version": "3.5.0.27",
|
||||
"version": "3.5.0.28",
|
||||
|
||||
"enums": {
|
||||
|
||||
|
|
@ -1640,11 +1640,11 @@
|
|||
}
|
||||
,
|
||||
{"code": "companySymbol",
|
||||
"field": "id","type": 12,"name": "Тип реквизита","shortname": "Тип реквизита","searchable": true,"sortable": true,"visible": true,"linkKeyCode": "companyId","linkCode": "companySymbol","link": "companySymbols","extends": "companySymbols","ignore": true
|
||||
"field": "id","type": 12,"name": "Тип реквизита","shortname": "Тип реквизита","searchable": true,"sortable": true,"visible": true,"linkKeyCode": "companyId","linkCode": "companySymbol","link": "companySymbols","extends": "companySymbols"
|
||||
}
|
||||
,
|
||||
{"code": "companySymbolValue",
|
||||
"field": "id","type": 2,"length": 255,"name": "Значение реквизита","shortname": "Значение реквизита","searchable": true,"sortable": true,"visible": true,"linkKeyCode": "companyId","linkCode": "companySymbolValue","link": "companySymbols","extends": "companySymbols","ignore": true
|
||||
"field": "id","type": 2,"length": 255,"name": "Значение реквизита","shortname": "Значение реквизита","searchable": true,"sortable": true,"visible": true,"linkKeyCode": "companyId","linkCode": "companySymbolValue","link": "companySymbols","extends": "companySymbols"
|
||||
}
|
||||
,
|
||||
{"code": "workflowStatus",
|
||||
|
|
@ -4741,7 +4741,7 @@
|
|||
,
|
||||
"planner": {
|
||||
|
||||
"name": "Расписание",
|
||||
"name": "Расписание на все даты",
|
||||
|
||||
"destination": "schedule/planners",
|
||||
|
||||
|
|
@ -4996,6 +4996,50 @@
|
|||
}
|
||||
]
|
||||
,"actions":[
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GVER",
|
||||
|
||||
"group": "Общее",
|
||||
|
||||
"name": "Запуск сверки",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GRYT",
|
||||
|
||||
"group": "Общее",
|
||||
|
||||
"name": "Подготовка КС к клиринговому дню",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "LOCM",
|
||||
|
||||
"group": "Обмен с интеграционными модулями",
|
||||
|
||||
"name": "Загрузка участников",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "LOSC",
|
||||
|
||||
"group": "Обмен с интеграционными модулями",
|
||||
|
||||
"name": "Загрузка инструментов",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GALB",
|
||||
|
|
@ -5020,35 +5064,6 @@
|
|||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "SCLR",
|
||||
|
||||
"group": "Клиринг",
|
||||
|
||||
"name": "Запуск клиринговой сессии",
|
||||
|
||||
"confirmation": "section,sessionType",
|
||||
|
||||
"fields": [
|
||||
{"code": "section",
|
||||
"type": 12,"name": "Секция","shortname": "Секция","link": "section","linkCode": "name","linkKeyCode": "code"
|
||||
}
|
||||
,
|
||||
{"code": "sessionType",
|
||||
"type": 12,"name": "Тип клиринговой сессии","shortname": "Тип клиринговой сессии","link": "sessionType","linkCode": "name","linkKeyCode": "code"
|
||||
}
|
||||
,
|
||||
{"code": "companyId",
|
||||
"type": 1,"name": "Наименование инициатора","shortname": "Инициатор","link": "company","linkCode": "shortName","visible": false
|
||||
}
|
||||
,
|
||||
{"code": "securityId",
|
||||
"type": 1,"name": "Наименование инструмента","shortname": "Инструмент","link": "security","linkCode": "shortName","visible": false
|
||||
}
|
||||
]
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GTRD",
|
||||
|
||||
"group": "Обмен с Торговой системой",
|
||||
|
|
@ -5082,108 +5097,38 @@
|
|||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GRRT",
|
||||
"destination": "SCLR",
|
||||
|
||||
"group": "Формирование реестров и отчетности",
|
||||
"group": "Клиринг",
|
||||
|
||||
"name": "Формирование реестра остатков ценных бумаг",
|
||||
"name": "Запуск клиринговой сессии",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
"confirmation": "section,sessionType",
|
||||
|
||||
"destination": "GBRR",
|
||||
|
||||
"group": "Формирование реестров и отчетности",
|
||||
|
||||
"name": "Формирование реестра остатков денежных средств",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "ADLR",
|
||||
|
||||
"group": "Формирование реестров и отчетности",
|
||||
|
||||
"name": "Формирование реестра обязательств, допущенных к клирингу",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "CDLR",
|
||||
|
||||
"group": "Формирование реестров и отчетности",
|
||||
|
||||
"name": "Формирование реестра обязательств, прошедших процедуру контроля обеспечения",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GORR",
|
||||
|
||||
"group": "Формирование реестров и отчетности",
|
||||
|
||||
"name": "Формирование реестра распоряжений, направленных расчетной организации",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GORD",
|
||||
|
||||
"group": "Формирование реестров и отчетности",
|
||||
|
||||
"name": "Формирование реестра распоряжений, направленных расчетному депозитарию",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "EXLR",
|
||||
|
||||
"group": "Формирование реестров и отчетности",
|
||||
|
||||
"name": "Формирование реестра обязательств, исключенных из клирингового пула",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "LBSR",
|
||||
|
||||
"group": "Формирование реестров и отчетности",
|
||||
|
||||
"name": "Формирование реестра учета обязательств",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "ECNR",
|
||||
|
||||
"group": "Формирование реестров и отчетности",
|
||||
|
||||
"name": "Формирование реестра сделок",
|
||||
|
||||
"fields": []
|
||||
"fields": [
|
||||
{"code": "section",
|
||||
"type": 12,"name": "Секция","shortname": "Секция","link": "section","linkCode": "name","linkKeyCode": "code"
|
||||
}
|
||||
,
|
||||
{"code": "sessionType",
|
||||
"type": 12,"name": "Тип клиринговой сессии","shortname": "Тип клиринговой сессии","link": "sessionType","linkCode": "name","linkKeyCode": "code"
|
||||
}
|
||||
,
|
||||
{"code": "companyId",
|
||||
"type": 1,"name": "Наименование инициатора","shortname": "Инициатор","link": "company","linkCode": "shortName","visible": false
|
||||
}
|
||||
,
|
||||
{"code": "securityId",
|
||||
"type": 1,"name": "Наименование инструмента","shortname": "Инструмент","link": "security","linkCode": "shortName","visible": false
|
||||
}
|
||||
]
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GREP",
|
||||
|
||||
"group": "Формирование реестров и отчетности",
|
||||
"group": "Формирование отчетности",
|
||||
|
||||
"name": "Формирование отчетности",
|
||||
|
||||
|
|
@ -5196,44 +5141,99 @@
|
|||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "LOCM",
|
||||
"destination": "GRRT",
|
||||
|
||||
"group": "Обмен с интеграционными модулями",
|
||||
"group": "Формирование реестров",
|
||||
|
||||
"name": "Загрузка участников",
|
||||
"name": "Формирование реестра остатков ценных бумаг",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "LOSC",
|
||||
"destination": "GBRR",
|
||||
|
||||
"group": "Обмен с интеграционными модулями",
|
||||
"group": "Формирование реестров",
|
||||
|
||||
"name": "Загрузка инструментов",
|
||||
"name": "Формирование реестра остатков денежных средств",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GVER",
|
||||
"destination": "ADLR",
|
||||
|
||||
"group": "Общее",
|
||||
"group": "Формирование реестров",
|
||||
|
||||
"name": "Запуск сверки",
|
||||
"name": "Формирование реестра обязательств, допущенных к клирингу",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GRYT",
|
||||
"destination": "CDLR",
|
||||
|
||||
"group": "Общее",
|
||||
"group": "Формирование реестров",
|
||||
|
||||
"name": "Подготовка КС к клиринговому дню",
|
||||
"name": "Формирование реестра обязательств, прошедших процедуру контроля обеспечения",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GORR",
|
||||
|
||||
"group": "Формирование реестров",
|
||||
|
||||
"name": "Формирование реестра распоряжений, направленных расчетной организации",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "GORD",
|
||||
|
||||
"group": "Формирование реестров",
|
||||
|
||||
"name": "Формирование реестра распоряжений, направленных расчетному депозитарию",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "EXLR",
|
||||
|
||||
"group": "Формирование реестров",
|
||||
|
||||
"name": "Формирование реестра обязательств, исключенных из клирингового пула",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "LBSR",
|
||||
|
||||
"group": "Формирование реестров",
|
||||
|
||||
"name": "Формирование реестра учета обязательств",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
,
|
||||
{"method":"post",
|
||||
|
||||
"destination": "ECNR",
|
||||
|
||||
"group": "Формирование реестров",
|
||||
|
||||
"name": "Формирование реестра сделок",
|
||||
|
||||
"fields": []
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--?xml-stylesheet type="text/xsl" href="\..\corp-reports\src\data\meta\meta.server.xslt"?-->
|
||||
<meta version="3.5.0.27">
|
||||
<meta version="3.5.0.28">
|
||||
<!-- _xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _xsi:noNamespaceSchemaLocation="file:///E:/d/projects/meta/from/meta.xsd" -->
|
||||
<!--Здесь словари-->
|
||||
<enums>
|
||||
|
|
@ -367,8 +367,8 @@
|
|||
<tradingCode type="2" length="255" name="Код участника торгов" shortname="Биржевой код" searchable="true" sortable="true" visible="true"/>
|
||||
<clearingCode type="2" length="255" name="Код участника клиринга" shortname="Клиринговый код" searchable="true" sortable="true" visible="true"/>
|
||||
<registrationCode type="2" length="255" name="Регистрационный код участника" shortname="Регистрационный код" searchable="true" sortable="true" visible="true"/>
|
||||
<companySymbol field="id" type="12" name="Тип реквизита" shortname="Тип реквизита" searchable="true" sortable="true" visible="true" linkKeyCode="companyId" linkCode="companySymbol" link="companySymbols" extends="companySymbols" ignore="true"/>
|
||||
<companySymbolValue field="id" type="2" length="255" name="Значение реквизита" shortname="Значение реквизита" searchable="true" sortable="true" visible="true" linkKeyCode="companyId" linkCode="companySymbolValue" link="companySymbols" extends="companySymbols" ignore="true"/>
|
||||
<companySymbol field="id" type="12" name="Тип реквизита" shortname="Тип реквизита" searchable="true" sortable="true" visible="true" linkKeyCode="companyId" linkCode="companySymbol" link="companySymbols" extends="companySymbols"/>
|
||||
<companySymbolValue field="id" type="2" length="255" name="Значение реквизита" shortname="Значение реквизита" searchable="true" sortable="true" visible="true" linkKeyCode="companyId" linkCode="companySymbolValue" link="companySymbols" extends="companySymbols"/>
|
||||
<workflowStatus type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" link="workflowStatus"/>
|
||||
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
|
||||
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/>
|
||||
|
|
@ -1104,7 +1104,7 @@
|
|||
</delete>
|
||||
</actions>
|
||||
</clearingCalendar>
|
||||
<planner name="Расписание" destination="schedule/planners" class="ru.clearing.classes.statics.data.scheduler.Planner" table="planner">
|
||||
<planner name="Расписание на все даты" destination="schedule/planners" class="ru.clearing.classes.statics.data.scheduler.Planner" table="planner">
|
||||
<task type="12" dbname="Код задачи" name="Наименование задачи" shortname="Задача" searchable="false" sortable="false" visible="true" link="task"/>
|
||||
<taskTime type="5" name="Время задачи" shortname="Время задачи" searchable="false" sortable="false" visible="true"/>
|
||||
<clearingDate type="6" name="Дата задачи" shortname="Дата задачи" searchable="false" sortable="false" visible="true"/>
|
||||
|
|
@ -1165,50 +1165,50 @@
|
|||
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/>
|
||||
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/>
|
||||
<actions>
|
||||
<post destination="GVER" group="Общее" name="Запуск сверки">
|
||||
</post>
|
||||
<post destination="GRYT" group="Общее" name="Подготовка КС к клиринговому дню">
|
||||
</post>
|
||||
<post destination="LOCM" group="Обмен с интеграционными модулями" name="Загрузка участников">
|
||||
</post>
|
||||
<post destination="LOSC" group="Обмен с интеграционными модулями" name="Загрузка инструментов">
|
||||
</post>
|
||||
<post destination="GALB" group="Обмен с расчетной организацией" name="Запрос остатков по всем счетам (отправка ДФ-51, ДФ-56 для получения ответа ДФ-01, ДФ-57)">
|
||||
</post>
|
||||
<post destination="OUTV" group="Обмен с расчетной организацией" name="Вывод свободных средств инициаторов В (отправка ДФ-54 для получения ответа ДФ-55)">
|
||||
</post>
|
||||
<post destination="SCLR" group="Клиринг" name="Запуск клиринговой сессии" confirmation="section,sessionType">
|
||||
<section type="12" name="Секция" shortname="Секция" link="section" linkCode="name" linkKeyCode="code"/>
|
||||
<sessionType type="12" name="Тип клиринговой сессии" shortname="Тип клиринговой сессии" link="sessionType" linkCode="name" linkKeyCode="code"/>
|
||||
<companyId type="1" name="Наименование инициатора" shortname="Инициатор" link="company" linkCode="shortName" visible="false"/>
|
||||
<securityId type="1" name="Наименование инструмента" shortname="Инструмент" link="security" linkCode="shortName" visible="false"/>
|
||||
</post>
|
||||
<post destination="GTRD" group="Обмен с Торговой системой" name="Получение сделок из Торговой системы">
|
||||
</post>
|
||||
<post destination="LIMM" group="Обмен с Торговой системой" name="Выгрузка в Торговую систему остатков по деньгам (отправка lim)">
|
||||
</post>
|
||||
<post destination="LIMS" group="Обмен с Торговой системой" name="Выгрузка в Торговую систему остатков по бумагам (отправка lim)">
|
||||
</post>
|
||||
<post destination="GRRT" group="Формирование реестров и отчетности" name="Формирование реестра остатков ценных бумаг">
|
||||
<post destination="SCLR" group="Клиринг" name="Запуск клиринговой сессии" confirmation="section,sessionType">
|
||||
<section type="12" name="Секция" shortname="Секция" link="section" linkCode="name" linkKeyCode="code"/>
|
||||
<sessionType type="12" name="Тип клиринговой сессии" shortname="Тип клиринговой сессии" link="sessionType" linkCode="name" linkKeyCode="code"/>
|
||||
<companyId type="1" name="Наименование инициатора" shortname="Инициатор" link="company" linkCode="shortName" visible="false"/>
|
||||
<securityId type="1" name="Наименование инструмента" shortname="Инструмент" link="security" linkCode="shortName" visible="false"/>
|
||||
</post>
|
||||
<post destination="GBRR" group="Формирование реестров и отчетности" name="Формирование реестра остатков денежных средств">
|
||||
</post>
|
||||
<post destination="ADLR" group="Формирование реестров и отчетности" name="Формирование реестра обязательств, допущенных к клирингу">
|
||||
</post>
|
||||
<post destination="CDLR" group="Формирование реестров и отчетности" name="Формирование реестра обязательств, прошедших процедуру контроля обеспечения">
|
||||
</post>
|
||||
<post destination="GORR" group="Формирование реестров и отчетности" name="Формирование реестра распоряжений, направленных расчетной организации">
|
||||
</post>
|
||||
<post destination="GORD" group="Формирование реестров и отчетности" name="Формирование реестра распоряжений, направленных расчетному депозитарию">
|
||||
</post>
|
||||
<post destination="EXLR" group="Формирование реестров и отчетности" name="Формирование реестра обязательств, исключенных из клирингового пула">
|
||||
</post>
|
||||
<post destination="LBSR" group="Формирование реестров и отчетности" name="Формирование реестра учета обязательств">
|
||||
</post>
|
||||
<post destination="ECNR" group="Формирование реестров и отчетности" name="Формирование реестра сделок">
|
||||
</post>
|
||||
<post destination="GREP" group="Формирование реестров и отчетности" name="Формирование отчетности">
|
||||
<post destination="GREP" group="Формирование отчетности" name="Формирование отчетности">
|
||||
<sessionId type="1" name="Клиринговая сессия" shortname="Сессия" link="session"/>
|
||||
</post>
|
||||
<post destination="LOCM" group="Обмен с интеграционными модулями" name="Загрузка участников">
|
||||
</post>
|
||||
<post destination="LOSC" group="Обмен с интеграционными модулями" name="Загрузка инструментов">
|
||||
<post destination="GRRT" group="Формирование реестров" name="Формирование реестра остатков ценных бумаг">
|
||||
</post>
|
||||
<post destination="GVER" group="Общее" name="Запуск сверки">
|
||||
<post destination="GBRR" group="Формирование реестров" name="Формирование реестра остатков денежных средств">
|
||||
</post>
|
||||
<post destination="GRYT" group="Общее" name="Подготовка КС к клиринговому дню">
|
||||
<post destination="ADLR" group="Формирование реестров" name="Формирование реестра обязательств, допущенных к клирингу">
|
||||
</post>
|
||||
<post destination="CDLR" group="Формирование реестров" name="Формирование реестра обязательств, прошедших процедуру контроля обеспечения">
|
||||
</post>
|
||||
<post destination="GORR" group="Формирование реестров" name="Формирование реестра распоряжений, направленных расчетной организации">
|
||||
</post>
|
||||
<post destination="GORD" group="Формирование реестров" name="Формирование реестра распоряжений, направленных расчетному депозитарию">
|
||||
</post>
|
||||
<post destination="EXLR" group="Формирование реестров" name="Формирование реестра обязательств, исключенных из клирингового пула">
|
||||
</post>
|
||||
<post destination="LBSR" group="Формирование реестров" name="Формирование реестра учета обязательств">
|
||||
</post>
|
||||
<post destination="ECNR" group="Формирование реестров" name="Формирование реестра сделок">
|
||||
</post>
|
||||
</actions>
|
||||
</launcher>
|
||||
|
|
|
|||
|
|
@ -2,22 +2,60 @@ package ru.spcex.clearing.config;
|
|||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import ru.clearing.classes.statics.data.misc.Market;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.platform.enumeration.MarketType;
|
||||
import ru.spcex.platform.enumeration.Section;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Configuration
|
||||
public class MarketCodesBySessionConfig {
|
||||
|
||||
@Bean(name = "marketCodesForBn")
|
||||
public List<String> marketCodesForBn(ImdgProvider imdgProvider) {
|
||||
// Imdg<Market> marketImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Market, Market.class);
|
||||
// Collection<Market> markets = marketImdg.getCollectionObjectsByFieldValues(Map.of(
|
||||
// "section", Section.FOND.getKey(),
|
||||
// "marketType", MarketType.PRMR.getKey()));
|
||||
// return markets.stream().map(Market::getCode).distinct().collect(Collectors.toList());
|
||||
return List.of("BMFC", "SMMC", "AEPC", "WBIC", "KBVC", "WBFC", "BMVC", "ABIC",
|
||||
"AESC", "ABFC", "KBIC", "WBMC", "BMMC", "ABEC", "SMIC", "ABMC", "SMVC", "KBFC", "SKVC", "ABVC", "WEPC",
|
||||
"KBMC", "SMFC", "BKVC", "WBVC", "BMIC", "WESC");
|
||||
public Supplier<List<String>> marketCodesForBn(ImdgProvider imdgProvider) {
|
||||
return new MarketCodesProvider(imdgProvider, Section.FOND, MarketType.PRMR);
|
||||
}
|
||||
|
||||
@Bean(name = "marketCodesForT0")
|
||||
public Supplier<List<String>> marketCodesForT0(ImdgProvider imdgProvider) {
|
||||
return new MarketCodesProvider(imdgProvider, Section.FOND, MarketType.SCND);
|
||||
}
|
||||
|
||||
private static class MarketCodesProvider implements Supplier<List<String>> {
|
||||
private volatile List<String> codes;
|
||||
private final Object lock = new Object();
|
||||
private final ImdgProvider imdgProvider;
|
||||
private final Section section;
|
||||
private final MarketType marketType;
|
||||
|
||||
public MarketCodesProvider(ImdgProvider imdgProvider, Section section, MarketType marketType) {
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.section = section;
|
||||
this.marketType = marketType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> get() {
|
||||
if (codes == null) {
|
||||
synchronized (lock) {
|
||||
if (codes == null) {
|
||||
imdgProvider.waitAvailable();
|
||||
Imdg<Market> marketImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Market, Market.class);
|
||||
Collection<Market> markets = marketImdg.getCollectionObjectsByFieldValues(Map.of(
|
||||
"section", section.getKey(),
|
||||
"marketType", marketType.getKey()));
|
||||
codes = markets.stream().map(Market::getCode).distinct().collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,15 @@ import ru.clearing.classes.statics.data.company.Company;
|
|||
import ru.clearing.classes.statics.data.company.relation.Relation;
|
||||
import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
|
||||
import ru.clearing.classes.statics.data.misc.STrades;
|
||||
import ru.clearing.classes.statics.data.misc.Session;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
|
||||
import ru.clearing.classes.statics.data.sdf.SDf01;
|
||||
import ru.clearing.classes.statics.data.sdf.SDf57;
|
||||
import ru.clearing.classes.statics.data.security.Security;
|
||||
import ru.clearing.platform.dictionary.SectionDictionary;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.service.validation.*;
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
import ru.spcex.platform.enumeration.ClearingCategory;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
|
@ -23,48 +24,42 @@ import ru.spcex.platform.imdg.validation.ImdgValidationContext;
|
|||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
import ru.spcex.platform.utils.validation.ValidatorImpl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Configuration
|
||||
public class ValidationConfig {
|
||||
private final Map<String, Imdg<? extends SpcexObjectBase>> imdgs;
|
||||
private final BiConsumer<ImdgValidationContext<?>, String> addImdg = (context, s)
|
||||
-> context.addImdg(s, getImdg(s));
|
||||
|
||||
Imdg<Relation> imdgRelation;
|
||||
Imdg<Company> imdgCompany;
|
||||
Imdg<Account> imdgAccount;
|
||||
Imdg<AccountBalance> imdgAccountBalance;
|
||||
Imdg<Security> imdgSecurity;
|
||||
Imdg<TradingClearingRegistry> imdgTradingClearingRegistry;
|
||||
Imdg<Session> imdgSession;
|
||||
Imdg<SectionDictionary> imdgSectionDictionary;
|
||||
|
||||
public ValidationConfig(ImdgProvider imdgProvider) {
|
||||
this.imdgs = new HashMap<>();
|
||||
BiConsumer<String, Class<? extends SpcexObjectBase>> addImdg = (s, aClass) -> imdgs.put(s, imdgProvider.getImdg(s, aClass));
|
||||
addImdg.accept(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Company, Company.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Account, Account.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Security, Security.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Company, Company.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* чтобы во всех валидаторах был один экземпляр Imdg
|
||||
*/
|
||||
private Imdg<?> getImdg(String key) {
|
||||
return imdgs.get(key);
|
||||
this.imdgRelation = imdgProvider.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
this.imdgCompany = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
this.imdgAccount = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class);
|
||||
this.imdgAccountBalance = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class);
|
||||
this.imdgSecurity = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class);
|
||||
this.imdgTradingClearingRegistry = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||
this.imdgSession = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
|
||||
this.imdgSectionDictionary = imdgProvider.getImdg(IMDGDistributedNames.Map_SectionDictionary, SectionDictionary.class);
|
||||
}
|
||||
|
||||
@Bean("executionDepositValidator")
|
||||
public BiFunction<ClearingCategory, ExecutionDeposit, IValidator> executionDepositValidator() {
|
||||
public BiFunction<ClearingCategory, ExecutionDeposit, IValidator> executionDepositValidator(ImdgProvider imdgProvider) {
|
||||
return (category, execDeposit) -> {
|
||||
ImdgValidationContext<ExecutionDeposit> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(execDeposit);
|
||||
context.storeObject(ClrngValidationStored.categoryPredefined, category);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_Relation);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_Company);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_Account);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_AccountBalance);
|
||||
context.addImdg(IMDGDistributedNames.Map_Relation, imdgRelation);
|
||||
context.addImdg(IMDGDistributedNames.Map_Company, imdgCompany);
|
||||
context.addImdg(IMDGDistributedNames.Map_Account, imdgAccount);
|
||||
context.addImdg(IMDGDistributedNames.Map_AccountBalance, imdgAccountBalance);
|
||||
return new ValidatorImpl<>(context,
|
||||
ExecutionDepositValidationRule.ClearingIsAllowed,
|
||||
ExecutionDepositValidationRule.AccountIsNotBlocked,
|
||||
|
|
@ -78,9 +73,9 @@ public class ValidationConfig {
|
|||
return sTrades -> {
|
||||
ImdgValidationContext<STrades> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(sTrades);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_Security);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_Company);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_TradingClearingRegistry);
|
||||
context.addImdg(IMDGDistributedNames.Map_Security, imdgSecurity);
|
||||
context.addImdg(IMDGDistributedNames.Map_Company, imdgCompany);
|
||||
context.addImdg(IMDGDistributedNames.Map_TradingClearingRegistry, imdgTradingClearingRegistry);
|
||||
return new ValidatorImpl<>(context,
|
||||
STradesValidationRule.SecurityPresent,
|
||||
STradesValidationRule.CompanyPresent,
|
||||
|
|
@ -94,12 +89,12 @@ public class ValidationConfig {
|
|||
return rgs -> {
|
||||
ImdgValidationContext<Registry> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(rgs);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_Relation);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_Session);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_SectionDictionary);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_Account);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_Company);
|
||||
addImdg.accept(context, IMDGDistributedNames.Map_TradingClearingRegistry);
|
||||
context.addImdg(IMDGDistributedNames.Map_Relation, imdgRelation);
|
||||
context.addImdg(IMDGDistributedNames.Map_Session, imdgSession);
|
||||
context.addImdg(IMDGDistributedNames.Map_SectionDictionary, imdgSectionDictionary);
|
||||
context.addImdg(IMDGDistributedNames.Map_Account, imdgAccount);
|
||||
context.addImdg(IMDGDistributedNames.Map_Company, imdgCompany);
|
||||
context.addImdg(IMDGDistributedNames.Map_TradingClearingRegistry, imdgTradingClearingRegistry);
|
||||
return new ValidatorImpl<>(context,
|
||||
RegistryStep3ValidationRule.ClearingAvailable,
|
||||
RegistryStep3ValidationRule.AccountActive,
|
||||
|
|
@ -112,9 +107,8 @@ public class ValidationConfig {
|
|||
return sDf01 -> {
|
||||
ImdgValidationContext<SDf01> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(sDf01);
|
||||
Consumer<String> addImdg = (s) -> context.addImdg(s, getImdg(s));
|
||||
addImdg.accept(IMDGDistributedNames.Map_Account);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Company);
|
||||
context.addImdg(IMDGDistributedNames.Map_Account, imdgAccount);
|
||||
context.addImdg(IMDGDistributedNames.Map_Company, imdgCompany);
|
||||
return new ValidatorImpl<>(context,
|
||||
Sdf01ValidationRule.CompanyPresent,
|
||||
Sdf01ValidationRule.AccountPresent,
|
||||
|
|
@ -130,9 +124,8 @@ public class ValidationConfig {
|
|||
return sDf57 -> {
|
||||
ImdgValidationContext<SDf57> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(sDf57);
|
||||
Consumer<String> addImdg = (s) -> context.addImdg(s, getImdg(s));
|
||||
addImdg.accept(IMDGDistributedNames.Map_Account);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Company);
|
||||
context.addImdg(IMDGDistributedNames.Map_Account, imdgAccount);
|
||||
context.addImdg(IMDGDistributedNames.Map_Company, imdgCompany);
|
||||
return new ValidatorImpl<>(context,
|
||||
Sdf57ValidationRule.CompanyDebOrCredPresent,
|
||||
Sdf57ValidationRule.AccountDebOrCredPresent,
|
||||
|
|
@ -146,9 +139,8 @@ public class ValidationConfig {
|
|||
return sDf01 -> {
|
||||
ImdgValidationContext<SDf01> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(sDf01);
|
||||
Consumer<String> addImdg = (s) -> context.addImdg(s, getImdg(s));
|
||||
addImdg.accept(IMDGDistributedNames.Map_Account);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Company);
|
||||
context.addImdg(IMDGDistributedNames.Map_Account, imdgAccount);
|
||||
context.addImdg(IMDGDistributedNames.Map_Company, imdgCompany);
|
||||
return new ValidatorImpl<>(context,
|
||||
Sdf01NewValidationRule.CompanyPresent,
|
||||
Sdf01NewValidationRule.AccountType,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
|||
import org.springframework.stereotype.Service;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonIdRequest;
|
||||
import ru.spcex.clearing.service.execution.ExecutionDepositComponent;
|
||||
import ru.spcex.clearing.service.execution.ExecutionFondComponent;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package ru.spcex.clearing.service;
|
||||
|
||||
import org.apache.kafka.clients.consumer.Consumer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
|
|
@ -12,26 +14,31 @@ import ru.spcex.clearing.platform.messaging.domain.cud.utilities.STradesImported
|
|||
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
|
||||
import ru.spcex.clearing.session.stage.PrimaryAuctionB0Session;
|
||||
import ru.spcex.clearing.session.stage.PrimaryAuctionBnSession;
|
||||
import ru.spcex.clearing.session.stage.SecondaryAuctionT0Session;
|
||||
import ru.spcex.platform.enumeration.Task;
|
||||
|
||||
import static ru.spcex.clearing.platform.messaging.domain.Consts.S_TRADES_IMPORTED;
|
||||
|
||||
@Service
|
||||
public class EventsReceiver extends QueueConsumer implements InitializingBean {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final ClearingService clearingService;
|
||||
private final RegistryService registryService;
|
||||
private final PrimaryAuctionBnSession primaryAuctionBnSession;
|
||||
private final SecondaryAuctionT0Session secondaryAuctionT0Session;
|
||||
private final PrimaryAuctionB0Session primaryAuctionB0Session;
|
||||
|
||||
public EventsReceiver(Consumer<String, Object> kafkaQueue,
|
||||
ClearingService clearingService,
|
||||
RegistryService registryService,
|
||||
PrimaryAuctionBnSession primaryAuctionBnSession,
|
||||
SecondaryAuctionT0Session secondaryAuctionT0Session,
|
||||
PrimaryAuctionB0Session primaryAuctionB0Session) {
|
||||
super(kafkaQueue);
|
||||
this.clearingService = clearingService;
|
||||
this.registryService = registryService;
|
||||
this.primaryAuctionBnSession = primaryAuctionBnSession;
|
||||
this.secondaryAuctionT0Session = secondaryAuctionT0Session;
|
||||
this.primaryAuctionB0Session = primaryAuctionB0Session;
|
||||
}
|
||||
|
||||
|
|
@ -61,11 +68,19 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
|
|||
// .forDestination(Task.startOfB0.topic(), callbacks::put);
|
||||
|
||||
|
||||
callback(Object.class)
|
||||
callback(LauncherCommandRequest.class)
|
||||
.setConsumer(primaryAuctionBnSession::runSession)
|
||||
.forDestination(Task.startOfClearing.topic(), callbacks::put);
|
||||
|
||||
callback(LauncherCommandRequest.class)
|
||||
.setConsumer(secondaryAuctionT0Session::runSession)
|
||||
.forDestination(Task.startOfT0.topic(), callbacks::put);
|
||||
|
||||
callback(Object.class)
|
||||
.setConsumer(primaryAuctionBnSession::continueSession)
|
||||
.setConsumer(req -> {
|
||||
primaryAuctionBnSession.continueSession(req);
|
||||
secondaryAuctionT0Session.continueSession(req);
|
||||
})
|
||||
.forDestination(Consts.CONTINUE_SESSION_BN_FIRST_PART, callbacks::put);
|
||||
|
||||
callback(STradesImportedRequest.class)
|
||||
|
|
|
|||
|
|
@ -7,15 +7,19 @@ import ru.clearing.classes.statics.data.payment.PaymentInstruction;
|
|||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.platform.enumeration.CompanySymbol;
|
||||
import ru.spcex.platform.enumeration.InOutDirection;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
|
||||
public class PaymentInstructionBuilder {
|
||||
|
||||
private Registry registry;
|
||||
private ImdgProvider imdgProvider;
|
||||
private Long sessionId;
|
||||
|
||||
public static PaymentInstructionBuilder builder(ImdgProvider imdgProvider, Registry registry) {
|
||||
return new PaymentInstructionBuilder(imdgProvider, registry);
|
||||
|
|
@ -26,6 +30,11 @@ public class PaymentInstructionBuilder {
|
|||
this.registry = registry;
|
||||
}
|
||||
|
||||
public PaymentInstructionBuilder sessionId(Long sessionId) {
|
||||
this.sessionId = sessionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaymentInstruction build() {
|
||||
PaymentInstruction paymentInstruction = new PaymentInstruction();
|
||||
paymentInstruction.setSenderId(registry.getCompanyId());
|
||||
|
|
@ -67,8 +76,20 @@ public class PaymentInstructionBuilder {
|
|||
|
||||
paymentInstruction.setDebitLeg_accountId(registry.getAccountId());
|
||||
|
||||
// Account account = accountImdg.getSingleObjectByID(registry.get());
|
||||
// paymentInstruction.setDebitLeg_account();
|
||||
// Imdg<DepoAccount> depoAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class);
|
||||
account = accountImdg.getSingleObjectByID(paymentInstruction.getDebitLeg_accountId());
|
||||
if (account != null) {
|
||||
paymentInstruction.setDebitLeg_account(account.getAccount());
|
||||
}
|
||||
|
||||
paymentInstruction.setCreditLeg_direction(InOutDirection.out.getKey());
|
||||
paymentInstruction.setDebitLeg_direction(InOutDirection.in.getKey());
|
||||
|
||||
|
||||
paymentInstruction.setTransactionStatus("STLD");
|
||||
paymentInstruction.setCreated(Instant.now());
|
||||
paymentInstruction.setClearingDate(LocalDate.now());
|
||||
|
||||
return paymentInstruction;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package ru.spcex.clearing.service;
|
||||
package ru.spcex.clearing.service.execution;
|
||||
|
||||
import org.apache.kafka.clients.producer.Producer;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -25,7 +25,10 @@ import ru.spcex.clearing.service.validation.ValidationStored;
|
|||
import ru.spcex.platform.enumeration.*;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.utils.enumeration.*;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.enumeration.IEnumId;
|
||||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
import ru.spcex.platform.utils.time.TimeUtil;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ru.spcex.clearing.service;
|
||||
package ru.spcex.clearing.service.execution;
|
||||
|
||||
import org.apache.kafka.clients.producer.Producer;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -96,7 +96,7 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
|
||||
@Override
|
||||
public boolean isNeedToSendCommand() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -171,11 +171,12 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
Registry registry = createRegistryByStatement(stmt, company, account, dsgn);
|
||||
|
||||
Registry registryB = registry.clone();
|
||||
registryB.setId(imdgProvider.getImdgIdGenerator().nextId());
|
||||
registryB.setRegistryUnit(RegistryUnit.B.getKey());
|
||||
registryB.setRegistryCode(RegistryUtil.clearingCode(registryB));
|
||||
registryB.setId(imdgProvider.getImdgIdGenerator().nextId());
|
||||
registryB.setBalance(BigDecimal.ZERO);
|
||||
registryB.setDebit(BigDecimal.ZERO);
|
||||
registryB.setCredit(BigDecimal.ZERO);
|
||||
|
||||
Registry registryF = registry.clone();
|
||||
registryF.setRegistryUnit(RegistryUnit.F.getKey());
|
||||
|
|
@ -291,10 +292,13 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
//Если значение statement.inOutDirection=OUT, то:
|
||||
//= текущее значение registry.balance - statement.amount
|
||||
switch (inOutDirection) {
|
||||
case in -> rgs.setBalance(statement.getAmount());
|
||||
case in -> {
|
||||
rgs.setBalance(statement.getAmount());
|
||||
rgs.setCredit(statement.getAmount());
|
||||
}
|
||||
case out -> {
|
||||
rgs.setBalance(statement.getAmount().negate());
|
||||
rgs.setDebit(statement.getAmount());
|
||||
rgs.setDebit(statement.getAmount().negate());
|
||||
}
|
||||
}
|
||||
rgs.setBalanceDimension(BalanceDimension.MONY.getKey()); //fixme ! смотри описание и ссылка на начало html'ки
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@ public enum RegistryStep3ValidationRule implements IValidationRule<ImdgValidatio
|
|||
return of(ClearingError.ClearingUnavailableForCompany, sectionFind.get());
|
||||
}
|
||||
Imdg<Relation> relationImdg = context.obtainMap(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
Relation relation = relationImdg.getSingleObjectByFieldValues(Map.of("consumerId", validatedObject.getCompanyId()));
|
||||
Imdg<Session> sessionImdg = context.obtainMap(IMDGDistributedNames.Map_Session, Session.class);
|
||||
Session activeSession = sessionImdg.getSingleObjectByID(validatedObject.getSessionId());
|
||||
Relation relation = relationImdg.getSingleObjectByFieldValues(Map.of(
|
||||
"consumerId", validatedObject.getCompanyId(),
|
||||
"service", activeSession.getSection()));
|
||||
if (relation == null || (!ServiceStatus.Active.equalsByKey(relation.getServiceStatus()) && !ServiceStatus.Reopened.equalsByKey(relation.getServiceStatus()))) {
|
||||
return of(ClearingError.ClearingUnavailableForCompany, sectionFind.get(), validatedObject.getCompanyId());
|
||||
}
|
||||
|
|
@ -90,7 +94,7 @@ public enum RegistryStep3ValidationRule implements IValidationRule<ImdgValidatio
|
|||
}
|
||||
Imdg<TradingClearingRegistry> tradingClearingRegistryImdg = context.obtainMap(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||
TradingClearingRegistry tcr = tradingClearingRegistryImdg.getSingleObjectBySQL("id = " + validatedObject.getTradingClearingRegistryId());
|
||||
if (tcr == null || (ServiceStatus.Active.equalsByKey(tcr.getStatus()) || ServiceStatus.Reopened.equalsByKey(tcr.getStatus())))
|
||||
if (tcr == null || !(ServiceStatus.Active.equalsByKey(tcr.getStatus()) || ServiceStatus.Reopened.equalsByKey(tcr.getStatus())))
|
||||
return of(ClearingError.TradingClearingRegistryNotActive, validatedObject.getTradingClearingRegistryId());
|
||||
return empty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,4 +65,10 @@ public class AbstractSession {
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean isRunning() {
|
||||
synchronized (this.currStage) {
|
||||
return this.currStage.get() != null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import org.springframework.stereotype.Service;
|
|||
import ru.clearing.classes.statics.data.execution.ExecutionCommon;
|
||||
import ru.clearing.classes.statics.data.execution.ExecutionFond;
|
||||
import ru.clearing.classes.statics.data.misc.Session;
|
||||
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.session.stage.impl.*;
|
||||
|
|
@ -22,7 +23,9 @@ import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
|||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Service
|
||||
public class PrimaryAuctionBnSession extends AbstractSession implements InitializingBean {
|
||||
|
|
@ -41,7 +44,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
|
|||
private final EndStageNotification endStageNotification;
|
||||
|
||||
private final Imdg<ExecutionFond> executionFondImdg;
|
||||
private final List<String> marketCodes;
|
||||
private final Supplier<List<String>> marketCodes;
|
||||
|
||||
|
||||
public PrimaryAuctionBnSession(
|
||||
|
|
@ -58,7 +61,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
|
|||
EndStageNotification endStageNotification,
|
||||
IMessageResolver messageResolver,
|
||||
InspectionObligations inspectionObligations,
|
||||
@Qualifier("marketCodesForBn") List<String> marketCodes) {
|
||||
@Qualifier("marketCodesForBn") Supplier<List<String>> marketCodes) {
|
||||
super(imdgProvider, messageResolver);
|
||||
this.balanceRevise = balanceRevise;
|
||||
this.dealsPrepare = dealsPrepare;
|
||||
|
|
@ -80,7 +83,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
|
|||
dealsPrepare.searchForExecutions(ExecutionType.ExecutionFond);
|
||||
ImdgPredicateBuilder execFondPb = executionFondImdg.predicateBuilder();
|
||||
dealsPrepare.addExecutionFondCondition(execFondPb.regex("settlementCode", "^B\\d{2}$"));
|
||||
dealsPrepare.addExecutionFondCondition(execFondPb.in("market", marketCodes.toArray(new String[0])));
|
||||
dealsPrepare.addExecutionFondCondition(execFondPb.in("market", marketCodes.get().toArray(new String[0])));
|
||||
}
|
||||
|
||||
public void runSession(BaseRequest<?> req) {
|
||||
|
|
@ -98,14 +101,16 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
|
|||
|
||||
public void continueSession(BaseRequest<?> req) {
|
||||
try {
|
||||
if (!checkStage(TaskType.StartRevise)) {
|
||||
log.error("cannot continue session, current stage is {}", currStage.get());
|
||||
throw new StageException();
|
||||
if (!isRunning()) {
|
||||
return;
|
||||
}
|
||||
if (checkStage(TaskType.StartRevise)) {
|
||||
firstPart(req);
|
||||
} else if (checkStage(TaskType.FormingPaymentInstruction)) {
|
||||
finishPart(req);
|
||||
} else {
|
||||
log.error("cannot continue session, current stage is {}", currStage.get());
|
||||
throw new StageException();
|
||||
}
|
||||
} catch (StageException e) {
|
||||
//already logged
|
||||
|
|
@ -140,13 +145,16 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
|
|||
//stage 6
|
||||
runStage(TaskType.FormingRegistersOnOS, formingRegistersOnOS); //returns Collection<Registry>
|
||||
//stage 7
|
||||
runStage(TaskType.FormingPaymentInstruction, formingPaymentInstruction);
|
||||
StageResult<Collection<PaymentInstruction>> paymentResult = runStage(TaskType.FormingPaymentInstruction, formingPaymentInstruction);
|
||||
if (paymentResult.getStageResult().isEmpty()) {
|
||||
runStage(TaskType.FormingPaymentInstruction, balanceRevise);
|
||||
// finishPart(req);
|
||||
}
|
||||
} catch (StageException e) {
|
||||
//already logged
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void finishPart(BaseRequest<?> req) {
|
||||
try {
|
||||
if (!checkStage(TaskType.FormingPaymentInstruction)) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,204 @@
|
|||
package ru.spcex.clearing.session.stage;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.execution.ExecutionCommon;
|
||||
import ru.clearing.classes.statics.data.execution.ExecutionFond;
|
||||
import ru.clearing.classes.statics.data.misc.Session;
|
||||
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.session.stage.impl.*;
|
||||
import ru.spcex.clearing.session.stage.task.*;
|
||||
import ru.spcex.platform.classes.base.interfaces.ExecutionType;
|
||||
import ru.spcex.platform.enumeration.Section;
|
||||
import ru.spcex.platform.enumeration.SessionStatus;
|
||||
import ru.spcex.platform.enumeration.SessionType;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Service
|
||||
public class SecondaryAuctionT0Session extends AbstractSession implements InitializingBean {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final BalanceRevise balanceRevise;
|
||||
private final DealsPrepare dealsPrepare;
|
||||
private final RequirementsAndObligationCreation requirementsAndObligationCreation;
|
||||
private final ObligationAdmission obligationsAdmission;
|
||||
|
||||
private final InclusionObligations inclusionObligations;
|
||||
private final InspectionObligations inspectionObligations;
|
||||
private final FormingRegistersOnOS formingRegistersOnOS;
|
||||
private final FormingPaymentInstruction formingPaymentInstruction;
|
||||
private final UnlockResources unlockResources;
|
||||
private final FinishingSession finishingSession;
|
||||
private final EndStageNotification endStageNotification;
|
||||
|
||||
private final Imdg<ExecutionFond> executionFondImdg;
|
||||
private final Supplier<List<String>> marketCodes;
|
||||
|
||||
|
||||
public SecondaryAuctionT0Session(
|
||||
ImdgProvider imdgProvider,
|
||||
BalanceRevise balanceRevise,
|
||||
DealsPrepare dealsPrepare,
|
||||
RequirementsAndObligationCreation requirementsAndObligationCreation,
|
||||
ObligationAdmission obligationsAdmission,
|
||||
InclusionObligations inclusionObligations,
|
||||
FormingRegistersOnOS formingRegistersOnOS,
|
||||
FormingPaymentInstruction formingPaymentInstruction,
|
||||
UnlockResources unlockResources,
|
||||
FinishingSession finishingSession,
|
||||
EndStageNotification endStageNotification,
|
||||
IMessageResolver messageResolver,
|
||||
InspectionObligations inspectionObligations,
|
||||
@Qualifier("marketCodesForT0") Supplier<List<String>> marketCodes) {
|
||||
super(imdgProvider, messageResolver);
|
||||
this.balanceRevise = balanceRevise;
|
||||
this.dealsPrepare = dealsPrepare;
|
||||
this.requirementsAndObligationCreation = requirementsAndObligationCreation;
|
||||
this.obligationsAdmission = obligationsAdmission;
|
||||
this.inclusionObligations = inclusionObligations;
|
||||
this.formingRegistersOnOS = formingRegistersOnOS;
|
||||
this.formingPaymentInstruction = formingPaymentInstruction;
|
||||
this.unlockResources = unlockResources;
|
||||
this.finishingSession = finishingSession;
|
||||
this.endStageNotification = endStageNotification;
|
||||
this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class);
|
||||
this.inspectionObligations = inspectionObligations;
|
||||
this.marketCodes = marketCodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
dealsPrepare.searchForExecutions(ExecutionType.ExecutionFond);
|
||||
ImdgPredicateBuilder execFondPb = executionFondImdg.predicateBuilder();
|
||||
dealsPrepare.addExecutionFondCondition(execFondPb.regex("settlementCode", "^T0.*$"));
|
||||
dealsPrepare.addExecutionFondCondition(execFondPb.in("market", marketCodes.get().toArray(new String[0])));
|
||||
}
|
||||
|
||||
public void runSession(BaseRequest<?> req) {
|
||||
if (!startSession()) {
|
||||
return;
|
||||
}
|
||||
StageResult<?> submit = balanceRevise.submit(new Task<>(TaskType.StartRevise, null));
|
||||
if (!submit.success) {
|
||||
log.error("stage {} error={}", balanceRevise.getClass().getSimpleName(), messageResolver.resolve(submit.error));
|
||||
endSession();
|
||||
} else {
|
||||
log.info("stage BalanceRevise success, waiting for a response from kafka");
|
||||
}
|
||||
}
|
||||
|
||||
public void continueSession(BaseRequest<?> req) {
|
||||
try {
|
||||
if (!isRunning()) {
|
||||
return;
|
||||
}
|
||||
if (!checkStage(TaskType.StartRevise)) {
|
||||
log.error("cannot continue session, current stage is {}", currStage.get());
|
||||
throw new StageException();
|
||||
}
|
||||
if (checkStage(TaskType.StartRevise)) {
|
||||
firstPart(req);
|
||||
} else if (checkStage(TaskType.FormingPaymentInstruction)) {
|
||||
finishPart(req);
|
||||
}
|
||||
} catch (StageException e) {
|
||||
//already logged
|
||||
}
|
||||
}
|
||||
|
||||
private void firstPart(BaseRequest<?> req) {
|
||||
try {
|
||||
//stage 1
|
||||
StageResult<List<ExecutionCommon>> dealsPreparationResult;
|
||||
{
|
||||
DealsPreparePayload payload = new DealsPreparePayload();
|
||||
payload.setSessionId(currSession.getId());
|
||||
dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare);
|
||||
}
|
||||
//stage 2
|
||||
runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation);
|
||||
//stage 3
|
||||
runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission);
|
||||
//stage 4
|
||||
{
|
||||
InclusionToPoolPayload inclusionToPoolPayload = new InclusionToPoolPayload();
|
||||
inclusionToPoolPayload.setSessionType(currSession.getSessionType());
|
||||
runStage(TaskType.InclusionToPool, inclusionToPoolPayload, inclusionObligations);
|
||||
}
|
||||
//stage 5
|
||||
{
|
||||
InspectionPoolPayload companyIdPayload = new InspectionPoolPayload();
|
||||
companyIdPayload.setProcessedCompanyId(currSession.getCompanyId());
|
||||
runStage(TaskType.InspectionObligations, companyIdPayload, inspectionObligations);
|
||||
}
|
||||
//stage 6
|
||||
runStage(TaskType.FormingRegistersOnOS, formingRegistersOnOS); //returns Collection<Registry>
|
||||
//stage 7
|
||||
StageResult<Collection<PaymentInstruction>> paymentResult = runStage(TaskType.FormingPaymentInstruction, formingPaymentInstruction);
|
||||
if (paymentResult.getStageResult().isEmpty()) {
|
||||
runStage(TaskType.ContinueRevise, balanceRevise);
|
||||
finishPart(req);
|
||||
}
|
||||
} catch (StageException e) {
|
||||
//already logged
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void finishPart(BaseRequest<?> req) {
|
||||
try {
|
||||
if (!checkStage(TaskType.FormingPaymentInstruction)) {
|
||||
log.error("cannot continue session, current stage is {}", currStage.get());
|
||||
throw new StageException();
|
||||
}
|
||||
//stage 10
|
||||
{
|
||||
FinishingSessionPayload payload = new FinishingSessionPayload();
|
||||
payload.setSessionId(currSession.getId());
|
||||
runStage(TaskType.FinishingSession, payload, finishingSession);
|
||||
}
|
||||
//stage 11
|
||||
{
|
||||
EndStageNotificationPayload payload = new EndStageNotificationPayload();
|
||||
payload.setSection(currSession.getSection());
|
||||
runStage(TaskType.EndStageNotification, payload, endStageNotification);
|
||||
}
|
||||
} catch (StageException e) {
|
||||
//already logged
|
||||
}
|
||||
}
|
||||
|
||||
private boolean startSession() {
|
||||
synchronized (this.currStage) {
|
||||
if (this.currStage.get() != null) {
|
||||
log.info("already running session.id={}", this.currSession.getId());
|
||||
return false;
|
||||
} else {
|
||||
Session newSession = new Session();
|
||||
newSession.setSection(Section.FOND.getKey());
|
||||
newSession.setSessionType(SessionType.TRDT.getKey());
|
||||
newSession.setSessionStatus(SessionStatus.CLRN.getKey());
|
||||
newSession.setClearingDate(LocalDate.now());
|
||||
|
||||
//todo companyId/securityId/userId передается из сообщения очереди
|
||||
sessionImdg.insert(newSession);
|
||||
currSession = newSession;
|
||||
log.info("started new session.id={}", this.currSession.getId());
|
||||
currStage.set(TaskType.StartRevise);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -57,12 +57,10 @@ public class BalanceRevise implements ISessionStage {
|
|||
@Override
|
||||
public StageResult<?> submit(Task<?> task) {
|
||||
switch (task.getTaskType()) {
|
||||
case StartRevise -> {
|
||||
case StartRevise, FormingPaymentInstruction -> {
|
||||
return sendSdfs();
|
||||
}
|
||||
case ContinueRevise -> {
|
||||
//больше не используются, удалить после проверки
|
||||
cashFlow(); //((SdfClearingRequest) task.getData()).getGroupId() if needed //todo убрать это отсюда
|
||||
return revise();
|
||||
}
|
||||
default -> throw new IllegalStateException("unknown task " + task.getTaskType());
|
||||
|
|
@ -91,6 +89,53 @@ public class BalanceRevise implements ISessionStage {
|
|||
return new StageResult<>(null, true);
|
||||
}
|
||||
|
||||
private StageResult<?> revise() {
|
||||
String statementSQL = String.format("inOutSDfType = %s and operationStatus = %s and statementType = %s",
|
||||
InOutSDfType.type1.getKey(), OperationStatus.Pending.getKey(), StatementType.full.getKey());
|
||||
Collection<Statement> stmts = statementImdg.getCollectionObjectsBySQL(statementSQL);
|
||||
for (Statement stmt : stmts) {
|
||||
|
||||
RegistryTradingParams registryAMT = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M,
|
||||
null, RegistryUnit.T);
|
||||
String registrySqlAMT = String.format("%s and account = '%s' and securityId = %d",
|
||||
RegistryCodeSqlBuilder.getInstance(registryAMT).build(),
|
||||
stmt.getAccount(),
|
||||
stmt.getSecurityId()
|
||||
);
|
||||
Registry rgsAMT = registryImdg.getSingleObjectBySQL(registrySqlAMT);
|
||||
rgsAMT.setCheckBalance(stmt.getAmount());
|
||||
rgsAMT.setDiffBalance(safeBD(rgsAMT.getBalance()).subtract(safeBD(rgsAMT.getCheckBalance())));
|
||||
}
|
||||
return new StageResult<>(null, true);
|
||||
}
|
||||
|
||||
private BigDecimal safeBD(BigDecimal value) {
|
||||
return value != null ? value : BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
private void newSDf56(Statement statement) {
|
||||
log.debug("creating sdf56");
|
||||
SDf56 sDf56 = new SDf56();
|
||||
sDf56.setNumber(idGenerator.nextId().toString());
|
||||
Instant now = Instant.now();
|
||||
String startTime = String.valueOf(statement != null ?
|
||||
statement.getCreated().toEpochMilli() : now.minus(1, ChronoUnit.DAYS).toEpochMilli());
|
||||
sDf56.setStart_datetime(startTime);
|
||||
sDf56.setEnd_datetime(String.valueOf(now.toEpochMilli()));
|
||||
sDf56.setAccount("ТБС");
|
||||
sDf56.setDeal("КОДУ");
|
||||
sDf56.setGenerationTime(now);
|
||||
sDf56.setGenerationId(idGenerator.nextId());
|
||||
sDf56Imdg.insert(sDf56);
|
||||
SdfClearingRequest requestForExporter = new SdfClearingRequest();
|
||||
requestForExporter.setGroupId(sDf56.getGenerationId());
|
||||
kafkaSender.sendRequestToQueue(Consts.SDF56_PROCESS, requestForExporter);
|
||||
log.debug("successfully processed, new id {}", sDf56.getId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private StageResult<?> cashFlow() {
|
||||
String statementSQL = String.format("inOutSDfType = %s and operationStatus = %s and statementType = %s",
|
||||
InOutSDfType.type57.getKey(), OperationStatus.Pending.getKey(), StatementType.incr.getKey());
|
||||
|
|
@ -149,48 +194,4 @@ public class BalanceRevise implements ISessionStage {
|
|||
//todoSdf1
|
||||
return new StageResult<>(null, true);
|
||||
}
|
||||
|
||||
private StageResult<?> revise() {
|
||||
String statementSQL = String.format("inOutSDfType = %s and operationStatus = %s and statementType = %s",
|
||||
InOutSDfType.type1.getKey(), OperationStatus.Pending.getKey(), StatementType.full.getKey());
|
||||
Collection<Statement> stmts = statementImdg.getCollectionObjectsBySQL(statementSQL);
|
||||
for (Statement stmt : stmts) {
|
||||
|
||||
RegistryTradingParams registryAMT = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M,
|
||||
null, RegistryUnit.T);
|
||||
String registrySqlAMT = String.format("%s and account = '%s' and securityId = %d",
|
||||
RegistryCodeSqlBuilder.getInstance(registryAMT).build(),
|
||||
stmt.getAccount(),
|
||||
stmt.getSecurityId()
|
||||
);
|
||||
Registry rgsAMT = registryImdg.getSingleObjectBySQL(registrySqlAMT);
|
||||
rgsAMT.setCheckBalance(stmt.getAmount());
|
||||
rgsAMT.setDiffBalance(safeBD(rgsAMT.getBalance()).subtract(safeBD(rgsAMT.getCheckBalance())));
|
||||
}
|
||||
return new StageResult<>(null, true);
|
||||
}
|
||||
|
||||
private BigDecimal safeBD(BigDecimal value) {
|
||||
return value != null ? value : BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
private void newSDf56(Statement statement) {
|
||||
log.debug("creating sdf56");
|
||||
SDf56 sDf56 = new SDf56();
|
||||
sDf56.setNumber(idGenerator.nextId().toString());
|
||||
Instant now = Instant.now();
|
||||
String startTime = String.valueOf(statement != null ?
|
||||
statement.getCreated().toEpochMilli() : now.minus(1, ChronoUnit.DAYS).toEpochMilli());
|
||||
sDf56.setStart_datetime(startTime);
|
||||
sDf56.setEnd_datetime(String.valueOf(now.toEpochMilli()));
|
||||
sDf56.setAccount("ТБС");
|
||||
sDf56.setDeal("КОДУ");
|
||||
sDf56.setGenerationTime(now);
|
||||
sDf56.setGenerationId(idGenerator.nextId());
|
||||
sDf56Imdg.insert(sDf56);
|
||||
SdfClearingRequest requestForExporter = new SdfClearingRequest();
|
||||
requestForExporter.setGroupId(sDf56.getGenerationId());
|
||||
kafkaSender.sendRequestToQueue(Consts.SDF56_PROCESS, requestForExporter);
|
||||
log.debug("successfully processed, new id {}", sDf56.getId());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,18 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.account.Account;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.clearing.classes.statics.data.sdf.SDf03;
|
||||
import ru.clearing.classes.statics.data.sdf.SDf12;
|
||||
import ru.clearing.classes.statics.data.security.Security;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||
import ru.spcex.clearing.service.builder.PaymentInstructionBuilder;
|
||||
import ru.spcex.clearing.session.stage.ISessionStage;
|
||||
import ru.spcex.clearing.session.stage.StageResult;
|
||||
import ru.spcex.clearing.session.stage.Task;
|
||||
|
|
@ -23,6 +31,8 @@ import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
|||
import ru.spcex.platform.utils.enumeration.SimpleMessageResolver;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -35,6 +45,11 @@ public class FormingPaymentInstruction implements ISessionStage {
|
|||
private ImdgId idGenerator;
|
||||
private Imdg<Registry> registryImdg;
|
||||
private Imdg<PaymentInstruction> paymentInstructionImdg;
|
||||
private Imdg<Security> securityImdg;
|
||||
private Imdg<Account> accountImdg;
|
||||
private Imdg<Company> companyImdg;
|
||||
private Imdg<SDf03> sDf03Imdg;
|
||||
private Imdg<SDf12> sDf12Imdg;
|
||||
private KafkaSender kafkaSender;
|
||||
private final IMessageResolver msgResolver = new SimpleMessageResolver();
|
||||
|
||||
|
|
@ -43,6 +58,11 @@ public class FormingPaymentInstruction implements ISessionStage {
|
|||
this.imdgProvider = imdgProvider;
|
||||
this.idGenerator = imdgProvider.getImdgIdGenerator();
|
||||
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
||||
this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class);
|
||||
this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class);
|
||||
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
this.sDf03Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf03, SDf03.class);
|
||||
this.sDf12Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf12, SDf12.class);
|
||||
this.paymentInstructionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class);
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +224,7 @@ public class FormingPaymentInstruction implements ISessionStage {
|
|||
}
|
||||
}
|
||||
|
||||
List<PaymentInstruction> formedPaymentInstructions = new ArrayList<>();
|
||||
for (Registry obligation : obligations) {
|
||||
RegistryTradingParams registryTradingParamsLT = new RegistryTradingParams(RegistryDesignation.L,
|
||||
null, null, RegistryUnit.T);
|
||||
|
|
@ -214,22 +235,120 @@ public class FormingPaymentInstruction implements ISessionStage {
|
|||
|
||||
BigDecimal sumBalance = registries.stream().map(Registry::getBalance).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
PaymentInstruction paymentInstruction = createPaymentInstruction(obligation, sumBalance);
|
||||
formedPaymentInstructions.add(paymentInstruction);
|
||||
paymentInstructionImdg.insert(paymentInstruction);
|
||||
obligation.setPaymentId(paymentInstruction.getId());
|
||||
registryImdg.update(obligation);
|
||||
}
|
||||
|
||||
sendSdfs(formedPaymentInstructions);
|
||||
|
||||
//todo send message to queue for forming sDf03 and sDf12?
|
||||
StageResult<Collection<PaymentInstruction>> stageResult = new StageResult(null, true);
|
||||
stageResult.setStageResult(formedPaymentInstructions);
|
||||
return stageResult;
|
||||
}
|
||||
|
||||
return new StageResult(null, true);
|
||||
private void sendSdfs(List<PaymentInstruction> formedPaymentInstructions) {
|
||||
Long sdf03GroupId = null;
|
||||
Long sdf12GroupId = null;
|
||||
for (PaymentInstruction paymentInstruction : formedPaymentInstructions) {
|
||||
Security security = securityImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_securityId());
|
||||
Account account = accountImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_accountId());
|
||||
if (InstrumentType.CRNC.equalsByKey(security.getInstrumentType()) &&
|
||||
List.of(AccountType.Corr, AccountType.Clrn).contains(IEnumKey.getEnumByKey(AccountType.class, account.getAccountType()))) {
|
||||
sdf03GroupId = sdf03GroupId != null ? sdf12GroupId : imdgProvider.getImdgIdGenerator().nextId();
|
||||
newSDf03(paymentInstruction, sdf03GroupId);
|
||||
} else if (!InstrumentType.CRNC.equalsByKey(security.getInstrumentType()) &&
|
||||
AccountType.Depo.equalsByKey(account.getAccountType())) {
|
||||
sdf12GroupId = sdf12GroupId != null ? sdf12GroupId : imdgProvider.getImdgIdGenerator().nextId();
|
||||
newSDf12(paymentInstruction, sdf12GroupId);
|
||||
}
|
||||
}
|
||||
|
||||
if (sdf03GroupId != null) {
|
||||
ExportToFileRequest exportToFileRequest = new ExportToFileRequest();
|
||||
exportToFileRequest.setNameOfTable("DF-03");
|
||||
exportToFileRequest.setSdfGroupId(sdf03GroupId);
|
||||
kafkaSender.sendRequestToQueue(Consts.EXPORT_PROCESS, exportToFileRequest);
|
||||
}
|
||||
|
||||
if (sdf12GroupId != null) {
|
||||
ExportToFileRequest exportToFileRequest = new ExportToFileRequest();
|
||||
exportToFileRequest.setNameOfTable("DF-12");
|
||||
exportToFileRequest.setSdfGroupId(sdf12GroupId);
|
||||
kafkaSender.sendRequestToQueue(Consts.EXPORT_PROCESS, exportToFileRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private PaymentInstruction createPaymentInstruction(Registry registry, BigDecimal balance) {
|
||||
PaymentInstruction paymentInstruction = new PaymentInstruction();
|
||||
paymentInstruction.setSenderId(registry.getCompanyId());
|
||||
paymentInstruction.setAddresseeId(registry.getCounterPartyId());
|
||||
//todo add builder for paymentInstruction
|
||||
return paymentInstruction;
|
||||
PaymentInstructionBuilder paymentInstructionBuilder = PaymentInstructionBuilder.builder(imdgProvider, registry);
|
||||
return paymentInstructionBuilder.build();
|
||||
}
|
||||
|
||||
private void newSDf03(PaymentInstruction paymentInstruction, Long sdf03GroupId) {
|
||||
log.debug("creating sdf03");
|
||||
SDf03 sDf03 = new SDf03();
|
||||
sDf03.setId(idGenerator.nextId());
|
||||
sDf03.setSeg_type("S");
|
||||
sDf03.setDoc_type("002");
|
||||
String strId = paymentInstruction.getId().toString();
|
||||
String strIdCut = strId.length() > 16 ? strId.substring(strId.length() - 16) : strId;
|
||||
sDf03.setDocnm_ref(strIdCut);
|
||||
sDf03.setC_acc_deb(paymentInstruction.getDebitLeg_account());
|
||||
|
||||
String senderSbankName = "";
|
||||
if (paymentInstruction.getSenderId().equals(1L)) {
|
||||
senderSbankName = paymentInstruction.getPayeeBankName();
|
||||
} else {
|
||||
Company company = companyImdg.getSingleObjectByID(paymentInstruction.getSenderId());
|
||||
if (company != null) {
|
||||
senderSbankName = company.getShortName();
|
||||
}
|
||||
}
|
||||
sDf03.setSbanknam1(senderSbankName);
|
||||
sDf03.setSbanknam2(senderSbankName);
|
||||
sDf03.setSbanknam3(senderSbankName);
|
||||
sDf03.setSbanknam4(senderSbankName);
|
||||
sDf03.setSbanknam5(senderSbankName);
|
||||
|
||||
sDf03.setC_acc_cred(paymentInstruction.getCreditLeg_account());
|
||||
|
||||
String addresseeSbankName = "";
|
||||
if (paymentInstruction.getAddresseeId().equals(1L)) {
|
||||
addresseeSbankName = paymentInstruction.getAddresseeBankName();
|
||||
} else {
|
||||
Company company = companyImdg.getSingleObjectByID(paymentInstruction.getAddresseeId());
|
||||
if (company != null) {
|
||||
addresseeSbankName = company.getShortName();
|
||||
}
|
||||
}
|
||||
sDf03.setRbanknam1(addresseeSbankName);
|
||||
sDf03.setRbanknam2(addresseeSbankName);
|
||||
sDf03.setRbanknam3(addresseeSbankName);
|
||||
sDf03.setRbanknam4(addresseeSbankName);
|
||||
sDf03.setRbanknam5(addresseeSbankName);
|
||||
|
||||
// sDf03.setPay_date();//
|
||||
sDf03.setPay_val("RUR");
|
||||
sDf03.setSum_deb(paymentInstruction.getDebitLeg_amount() != null ? paymentInstruction.getDebitLeg_amount().toString() : "");
|
||||
sDf03.setSpecif_1(paymentInstruction.getPaymentPurpose());
|
||||
sDf03.setGenerationTime(Instant.now());
|
||||
sDf03.setGenerationId(sdf03GroupId);
|
||||
sDf03.setPaymentInstructionId(paymentInstruction.getId());
|
||||
sDf03Imdg.insert(sDf03);
|
||||
log.debug("successfully processed, new id {}", sDf03.getId());
|
||||
}
|
||||
|
||||
private void newSDf12(PaymentInstruction paymentInstruction, Long sdf12GroupId) {
|
||||
log.debug("creating sdf12");
|
||||
SDf12 sDf12 = new SDf12();
|
||||
sDf12.setId(idGenerator.nextId());
|
||||
sDf12.setOutDocument(sDf12.getId().toString());
|
||||
// sDf12.setQuantity();
|
||||
sDf12.setGenerationTime(Instant.now());
|
||||
sDf12.setGenerationId(sdf12GroupId);
|
||||
sDf12Imdg.insert(sDf12);
|
||||
}
|
||||
|
||||
// private String defineCompanyName(Function function, )
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@ package ru.spcex.clearing.session.stage.impl;
|
|||
|
||||
import ru.clearing.classes.statics.data.account.Account;
|
||||
import ru.clearing.classes.statics.data.account.ClearingAccount;
|
||||
import ru.clearing.classes.statics.data.account.DepoAccount;
|
||||
import ru.clearing.classes.statics.data.account.InformationAccount;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.execution.ExecutionCommon;
|
||||
import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
|
||||
import ru.clearing.classes.statics.data.execution.ExecutionFond;
|
||||
import ru.clearing.classes.statics.data.misc.Currency;
|
||||
import ru.clearing.classes.statics.data.misc.Market;
|
||||
import ru.clearing.classes.statics.data.misc.Session;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
|
|
@ -20,6 +23,7 @@ import ru.spcex.platform.imdg.api.ImdgProvider;
|
|||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Map;
|
||||
|
||||
public class RegistryBuilder {
|
||||
private Imdg<Company> companyImdg;
|
||||
|
|
@ -28,6 +32,9 @@ public class RegistryBuilder {
|
|||
private Imdg<Market> marketImdg;
|
||||
private Imdg<Session> sessionImdg;
|
||||
private Imdg<ClearingAccount> clearingAccountImdg;
|
||||
private Imdg<InformationAccount> informationAccountImdg;
|
||||
private Imdg<DepoAccount> depoAccountImdg;
|
||||
private Imdg<Currency> currencyImdg;
|
||||
private ExecutionCommon exec;
|
||||
private RegistryDesignation regDsgn;
|
||||
|
||||
|
|
@ -45,6 +52,9 @@ public class RegistryBuilder {
|
|||
this.marketImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Market, Market.class);
|
||||
this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
|
||||
this.clearingAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class);
|
||||
this.depoAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class);
|
||||
this.informationAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_InformationAccount, InformationAccount.class);
|
||||
this.currencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -69,32 +79,56 @@ public class RegistryBuilder {
|
|||
reg.setShortName(company.getShortName());
|
||||
reg.setFullName(company.getFullName());
|
||||
TradingClearingRegistry tcr = searchTradingClearingRegistry();
|
||||
ClearingAccount accountForStatement = null;
|
||||
String capacityByAccount = null;
|
||||
boolean isMoney = false;
|
||||
Account account = null;
|
||||
if ((regDsgn.equals(RegistryDesignation.O) && side.isBuy()) || (regDsgn.equals(RegistryDesignation.T) && side.isSell())) {
|
||||
isMoney = true;
|
||||
reg.setAccountId(tcr.getMoneyAccountId());
|
||||
account = accountImdg.getSingleObjectByID(tcr.getMoneyAccountId());
|
||||
reg.setRegistryInstrumentType(RegistryInstrumentType.M.getKey());
|
||||
reg.setBalanceDimension(BalanceDimension.MONY.getKey()); //fixme add second leg code branch
|
||||
accountForStatement = clearingAccountImdg.getSingleObjectByID(tcr.getMoneyAccountId());
|
||||
Currency currency = currencyImdg.getSingleObjectByFieldValues(Map.of("currencyCode", exec.getSettlementCurrency()));
|
||||
reg.setSecurityId(currency.getId());
|
||||
reg.setSecuritySymbol(currency.getCurrencyCode());
|
||||
if (AccountType.Clrn.equalsByKey(account.getAccountType())) {
|
||||
ClearingAccount clearingAccount = clearingAccountImdg.getSingleObjectByID(tcr.getMoneyAccountId());
|
||||
if (clearingAccount != null) {
|
||||
capacityByAccount = clearingAccount.getClearingAccountType();
|
||||
}
|
||||
} else if (AccountType.Info.equalsByKey(account.getAccountType())){
|
||||
InformationAccount informationAccount = informationAccountImdg.getSingleObjectByID(tcr.getMoneyAccountId());
|
||||
if (informationAccount != null) {
|
||||
capacityByAccount = "A"; //todo сделать enum
|
||||
}
|
||||
}
|
||||
} else if ((regDsgn.equals(RegistryDesignation.T) && side.isBuy()) || (regDsgn.equals(RegistryDesignation.O) && side.isSell())) {
|
||||
isMoney = false;
|
||||
reg.setAccountId(tcr.getDepoAccountId());
|
||||
account = accountImdg.getSingleObjectByID(tcr.getDepoAccountId());
|
||||
reg.setRegistryInstrumentType(RegistryInstrumentType.S.getKey());
|
||||
reg.setBalanceDimension(BalanceDimension.PICS.getKey()); //fixme add second leg code branch
|
||||
accountForStatement = clearingAccountImdg.getSingleObjectByID(tcr.getDepoAccountId());
|
||||
reg.setSecurityId(exec.getSecurityId());
|
||||
reg.setSecuritySymbol(exec.getSecuritySymbol());
|
||||
DepoAccount depoAccount = depoAccountImdg.getSingleObjectByID(tcr.getDepoAccountId());
|
||||
if (depoAccount != null) {
|
||||
capacityByAccount = depoAccount.getDepoAccountType();
|
||||
}
|
||||
}
|
||||
|
||||
if (account != null) {
|
||||
reg.setAccountType(account.getAccountType());
|
||||
reg.setAccount(account.getAccount());
|
||||
}
|
||||
Account account = accountImdg.getSingleObjectByID(reg.getAccountId());
|
||||
reg.setAccountType(account.getAccountType());
|
||||
reg.setAccount(account.getAccount());
|
||||
reg.setRegistryDesignation(regDsgn.getKey());
|
||||
if (accountForStatement != null) {
|
||||
reg.setRegistryCapacity(accountForStatement.getClearingAccountType());
|
||||
if (capacityByAccount != null) {
|
||||
reg.setRegistryCapacity(capacityByAccount);
|
||||
}
|
||||
reg.setRegistryUnit(RegistryUnit.T.getKey());
|
||||
reg.setRegistryCode(RegistryUtil.clearingCode(reg));
|
||||
reg.setTradingClearingRegistryId(exec.getTradingClearingRegistryId());
|
||||
reg.setTradingClearingRegistry(tcr.getCode());
|
||||
reg.setRegistryStatus(RegistryStatus.PROC.getKey());
|
||||
reg.setSecurityId(exec.getSecurityId());
|
||||
reg.setSecuritySymbol(exec.getSecuritySymbol());
|
||||
switch (exec.type()) {
|
||||
case ExecutionDeposit -> {
|
||||
ExecutionDeposit execDep = (ExecutionDeposit) this.exec;
|
||||
|
|
@ -112,7 +146,13 @@ public class RegistryBuilder {
|
|||
}
|
||||
case ExecutionFond -> {
|
||||
ExecutionFond execFond = (ExecutionFond) this.exec;
|
||||
reg.setBalance(execFond.getSettlementAmount());
|
||||
if (isMoney) {
|
||||
//todo ОКРУГЛЕНИЕ(fixedIncomeSecurity.nominalValue * quantity * price/100) + ОКРУГЛЕНИЕ (executionFond.interestAmount)
|
||||
reg.setBalance(execFond.getSettlementAmount());
|
||||
} else {
|
||||
reg.setBalance(execFond.getQuantity());
|
||||
}
|
||||
|
||||
reg.setSettlementDate(execFond.getSettlementDate());
|
||||
reg.setSettlementCode(execFond.getSettlementCode());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,4 +39,9 @@
|
|||
<appender-ref ref="FILE"/>
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
|
||||
<logger name="ru.spcex.clearing.service.execution" level="warn" additivity="false">
|
||||
<appender-ref ref="FILE"/>
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
</configuration>
|
||||
|
|
@ -13,6 +13,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
|||
import ru.spcex.clearing.config.*;
|
||||
import ru.spcex.clearing.service.builder.LiabilitiesClaimsAssetsCreator;
|
||||
import ru.spcex.clearing.service.builder.LiabilitiesClaimsMoneyCreator;
|
||||
import ru.spcex.clearing.service.execution.ExecutionDepositComponent;
|
||||
import ru.spcex.clearing.service.order.ExecutionDepositSorter;
|
||||
import ru.spcex.clearing.service.order.PaymentInstructionSorter;
|
||||
import ru.spcex.clearing.utils.TestUtils;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package ru.spcex.clearing.service;
|
||||
package ru.spcex.clearing.service.execution;
|
||||
|
||||
import org.apache.kafka.clients.consumer.MockConsumer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
|
@ -11,6 +11,8 @@ import ru.clearing.classes.statics.data.misc.STrades;
|
|||
import ru.clearing.classes.statics.data.security.Security;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest;
|
||||
import ru.spcex.clearing.service.AbstractClearingTest;
|
||||
import ru.spcex.clearing.service.EventsReceiver;
|
||||
import ru.spcex.platform.enumeration.Task;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ public class IMDGMessageResolver implements IMessageResolver {
|
|||
try {
|
||||
ErrorCodeDictionary errorDictionary = errorCodeDictionaryIMDG.getSingleObjectByID(errMsg.getSubject().getId());
|
||||
if (errorDictionary == null) {
|
||||
log.warn("ERROR_CODE_DICTIONARY not found fo id={}", errMsg.getSubject().getId());
|
||||
log.warn("ERROR_CODE_DICTIONARY not found for id={}", errMsg.getSubject().getId());
|
||||
return simplFormatter.get();
|
||||
}
|
||||
String textTemplate = errorDictionary.getName();
|
||||
|
|
|
|||
|
|
@ -14,60 +14,61 @@ import java.util.function.Function;
|
|||
* @param <R> Класс проверяемого объекта
|
||||
*/
|
||||
public record EndDtAfterStartDtRule<R>(
|
||||
String endDtFieldName,
|
||||
String startDtFieldName,
|
||||
Function<R, LocalDate> getterEndDt,
|
||||
String endDtFieldName,
|
||||
Function<R, LocalDate> getterStartDt,
|
||||
Function<R, LocalDate> getterEndDt,
|
||||
IErrorEnumId errorEmptyRequiredValue,
|
||||
IErrorEnumId errorEndDtAfterStartDt,
|
||||
boolean required
|
||||
) implements IValidationRule<ImdgValidationContext<R>> {
|
||||
|
||||
/**
|
||||
* @param endDtFieldName Название поля класса, содержащий EndDt
|
||||
* @param startDtFieldName Название поля класса, содержащий StartDt
|
||||
* @param getterEndDt Метод получения проверяемой EndDt
|
||||
* @param endDtFieldName Название поля класса, содержащий EndDt
|
||||
* @param getterStartDt Метод получения проверяемой StartDt
|
||||
* @param getterEndDt Метод получения проверяемой EndDt
|
||||
* @param errorEmptyRequiredValue Ошибка, которая будет возвращена, если одна из дат пустая
|
||||
* @param errorEndDtAfterStartDt Ошибка, которая будет возвращена, если EndDt > StartDt
|
||||
* @param required Флаг обязательности поля
|
||||
* @param <R> Класс проверяемого объекта
|
||||
*/
|
||||
public static <R> EndDtAfterStartDtRule<R> instance(String endDtFieldName,
|
||||
String startDtFieldName,
|
||||
Function<R, LocalDate> getterEndDt,
|
||||
public static <R> EndDtAfterStartDtRule<R> instance(String startDtFieldName,
|
||||
String endDtFieldName,
|
||||
Function<R, LocalDate> getterStartDt,
|
||||
Function<R, LocalDate> getterEndDt,
|
||||
IErrorEnumId errorEmptyRequiredValue,
|
||||
IErrorEnumId errorEndDtAfterStartDt,
|
||||
boolean required) {
|
||||
return new EndDtAfterStartDtRule<>(endDtFieldName,
|
||||
startDtFieldName,
|
||||
getterEndDt,
|
||||
return new EndDtAfterStartDtRule<>(startDtFieldName,
|
||||
endDtFieldName,
|
||||
getterStartDt,
|
||||
getterEndDt,
|
||||
errorEmptyRequiredValue,
|
||||
errorEndDtAfterStartDt,
|
||||
required);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param endDtFieldName Название поля класса, содержащий EndDt
|
||||
* @param startDtFieldName Название поля класса, содержащий StartDt
|
||||
* @param getterEndDt Метод получения проверяемой EndDt
|
||||
* @param endDtFieldName Название поля класса, содержащий EndDt
|
||||
* @param getterStartDt Метод получения проверяемой StartDt
|
||||
* @param getterEndDt Метод получения проверяемой EndDt
|
||||
* @param errorEmptyRequiredValue Ошибка, которая будет возвращена, если одна из дат пустая
|
||||
* @param errorEndDtAfterStartDt Ошибка, которая будет возвращена, если EndDt > StartDt
|
||||
* @param errorEndDtAfterStartDt Ошибка, которая будет возвращена, если StartDt > EndDt
|
||||
* @param <R> Класс проверяемого объекта
|
||||
*/
|
||||
public static <R> EndDtAfterStartDtRule<R> instance(String endDtFieldName,
|
||||
public static <R> EndDtAfterStartDtRule<R> instance(
|
||||
String startDtFieldName,
|
||||
Function<R, LocalDate> getterEndDt,
|
||||
String endDtFieldName,
|
||||
Function<R, LocalDate> getterStartDt,
|
||||
Function<R, LocalDate> getterEndDt,
|
||||
IErrorEnumId errorEmptyRequiredValue,
|
||||
IErrorEnumId errorEndDtAfterStartDt) {
|
||||
return new EndDtAfterStartDtRule<>(endDtFieldName,
|
||||
startDtFieldName,
|
||||
getterEndDt,
|
||||
return new EndDtAfterStartDtRule<>(startDtFieldName,
|
||||
endDtFieldName,
|
||||
getterStartDt,
|
||||
getterEndDt,
|
||||
errorEmptyRequiredValue,
|
||||
errorEndDtAfterStartDt,
|
||||
true);
|
||||
|
|
@ -76,8 +77,8 @@ public record EndDtAfterStartDtRule<R>(
|
|||
@Override
|
||||
public Optional<EnumMessage> validate(ImdgValidationContext<R> context) {
|
||||
R validatedObject = context.getValidatedObject();
|
||||
LocalDate endDt = getterEndDt.apply(validatedObject);
|
||||
LocalDate startDt = getterStartDt.apply(validatedObject);
|
||||
LocalDate endDt = getterEndDt.apply(validatedObject);
|
||||
if (endDt == null) return required ? of(errorEmptyRequiredValue, endDtFieldName) : Optional.empty();
|
||||
if (startDt == null) return required ? of(errorEmptyRequiredValue, startDtFieldName) : Optional.empty();
|
||||
if (startDt.isAfter(endDt)) return of(errorEndDtAfterStartDt, startDtFieldName, endDtFieldName);
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
|||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.company.ProfileDocumentNewRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.company.ProfileDocumentUpdateRequest;
|
||||
import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule;
|
||||
import ru.spcex.clearing.validation.common.rules.EndDtAfterStartDtRule;
|
||||
import ru.spcex.clearing.validation.common.rules.FieldRequiredRule;
|
||||
import ru.spcex.clearing.validation.common.rules.IdPresentRule;
|
||||
import ru.spcex.clearing.validation.common.rules.*;
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
|
|
@ -59,6 +56,9 @@ public class ProfileDocumentValidationConfig {
|
|||
FieldRequiredRule.instance("issuer",
|
||||
ProfileDocumentNewRequest::getIssuer,
|
||||
CompanyErrors.RequiredFieldEmpty),
|
||||
FieldRequiredRule.instance("name",
|
||||
ProfileDocumentNewRequest::getName,
|
||||
CompanyErrors.RequiredFieldEmpty),
|
||||
FieldRequiredRule.instance("number",
|
||||
ProfileDocumentNewRequest::getNumber,
|
||||
CompanyErrors.RequiredFieldEmpty),
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
|
|||
import ru.spcex.clearing.util.security.UserRoleVerification;
|
||||
import ru.spcex.clearing.validation.common.ValidationHelper;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgId;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.api.ImdgTransaction;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Service
|
||||
|
|
@ -34,6 +34,7 @@ public class ClearingMemberCategoryService extends QueueConsumer implements Init
|
|||
private final Imdg<ClearingMemberCategory> clearingMemberCategoryMap;
|
||||
private final Imdg<Company> companyMap;
|
||||
private final ImdgProvider imdgProvider;
|
||||
private final ImdgId idSequence;
|
||||
|
||||
private final Function<ClearingMemberCategoryNewRequest, IValidator> clearingMemberCategoryNewRequestValidator;
|
||||
private final Function<ClearingMemberCategoryUpdateRequest, IValidator> clearingMemberCategoryUpdateRequestValidator;
|
||||
|
|
@ -56,6 +57,7 @@ public class ClearingMemberCategoryService extends QueueConsumer implements Init
|
|||
this.clearingMemberCategoryMap = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
|
||||
this.companyMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.idSequence = imdgProvider.getImdgIdGenerator();
|
||||
this.clearingMemberCategoryNewRequestValidator = clearingMemberCategoryNewRequestValidator;
|
||||
this.clearingMemberCategoryUpdateRequestValidator = clearingMemberCategoryUpdateRequestValidator;
|
||||
this.clearingMemberCategoryDeleteRequestValidator = clearingMemberCategoryDeleteRequestValidator;
|
||||
|
|
@ -88,6 +90,7 @@ public class ClearingMemberCategoryService extends QueueConsumer implements Init
|
|||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
ClearingMemberCategoryNewRequest req = userRequest.getRequestPayload();
|
||||
ClearingMemberCategory newCategory = new ClearingMemberCategory();
|
||||
newCategory.setId(idSequence.nextId());
|
||||
newCategory.setCompanyId(req.getCompanyId());
|
||||
newCategory.setClearingMemberCategory(req.getClearingMemberCategory());
|
||||
|
||||
|
|
@ -96,7 +99,7 @@ public class ClearingMemberCategoryService extends QueueConsumer implements Init
|
|||
transaction.beginTransaction();
|
||||
boolean txOk = false;
|
||||
try {
|
||||
companyService.relationService.createNewRelation(transaction, req.getCompanyId());
|
||||
companyService.relationService.createNewRelation(transaction, req.getCompanyId(), newCategory);
|
||||
Imdg<ClearingMemberCategory> txClearingMemberCategoryMap = transaction.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
|
||||
txClearingMemberCategoryMap.insert(newCategory);
|
||||
txOk = true;
|
||||
|
|
|
|||
|
|
@ -141,10 +141,6 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
|
|||
companyMap.insert(company);
|
||||
log.debug("company-new request processed, BaseRequest.id = {}, company.id={}",
|
||||
companyNewRequestBaseRequest.getId(), company.getId());
|
||||
relationService.createNewRelation(transaction, company.getId());
|
||||
if (!(WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()))) { // Block
|
||||
relationService.onChangeWorkflowStatus(transaction, company, null, company.getWorkflowStatus());
|
||||
}
|
||||
txOk = true;
|
||||
} finally {
|
||||
if (txOk)
|
||||
|
|
|
|||
|
|
@ -280,16 +280,15 @@ public class RelationService extends QueueConsumer implements InitializingBean {
|
|||
|
||||
// --- internal API ---
|
||||
|
||||
protected void createNewRelation(ImdgTransaction transaction, Long companyId) {
|
||||
protected void createNewRelation(ImdgTransaction transaction, Long companyId, ClearingMemberCategory clearingMemberCategory) {
|
||||
Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
Relation relation = new Relation();
|
||||
Company company = transaction.getImdg(IMDGDistributedNames.Map_Company, Company.class).getSingleObjectByFieldValues(Map.of("id", companyId));
|
||||
ClearingMemberCategory clearingMemberCategory = transaction.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class).getSingleObjectByFieldValues(Map.of("companyId", companyId));
|
||||
|
||||
WorkflowStatus workflowStatus = getEnumByKey(WorkflowStatus.class, company.getWorkflowStatus());
|
||||
String serviceStatus = null;
|
||||
if (clearingMemberCategory == null) {
|
||||
log.debug("clearingMemberCategory not found for companyId={}", companyId);
|
||||
log.warn("clearingMemberCategory not set for companyId={}", companyId);
|
||||
} else {
|
||||
ClearingCategory clearingCategory = getEnumByKey(ClearingCategory.class, clearingMemberCategory.getClearingMemberCategory());
|
||||
switch (Objects.requireNonNull(clearingCategory)) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- DB version: 3.5.0.26
|
||||
-- DATA version: 3.5.0.6
|
||||
-- DB version: 3.5.0.28
|
||||
-- DATA version: 3.5.0.7
|
||||
/* Dictionaries */
|
||||
|
||||
INSERT INTO ALLOWED_DICTIONARY(ID, CODE, NAME) values (1, 'ALWD', 'Разрешено') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
|
@ -302,27 +302,53 @@ INSERT INTO REGISTRY_UNIT_DICTIONARY(ID, CODE, NAME) values (3, 'B', 'Забло
|
|||
|
||||
INSERT INTO REGISTRY_UNIT_DICTIONARY(ID, CODE, NAME) values (4, 'C', 'Комиссия') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (1, 'AMPT', 'Денежные средства - на торги') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (1, 'AMAT', 'Денежные средства - на торги') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (2, 'AMPF', 'Денежные средства - свободные') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (2, 'AMAF', 'Денежные средства - свободные') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (3, 'AMPB', 'Денежные средства - блокированные') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (3, 'AMAB', 'Денежные средства - блокированные') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (4, 'TMPT', 'Требования по деньгам - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (4, 'TMAT', 'Требования по деньгам - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (5, 'OSPT', 'Обязательства по инструментам - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (5, 'OSAT', 'Обязательства по инструментам - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (6, 'OMPT', 'Обязательства по деньгам - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (6, 'OMAT', 'Обязательства по деньгам - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (7, 'TSPT', 'Требования по инструментам - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (7, 'TSAT', 'Требования по инструментам - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (8, 'CMPT', 'Требования по деньгам - свои') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (8, 'CMAT', 'Требования по деньгам - свои') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (9, 'LSPT', 'Обязательства по инструментам - свои') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (9, 'LSAT', 'Обязательства по инструментам - свои') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (10, 'LMPT', 'Обязательства по деньгам - свои') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (10, 'LMAT', 'Обязательства по деньгам - свои') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (11, 'CSPT', 'Требования по инструментам - свои') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (11, 'CSAT', 'Требования по инструментам - свои') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (12, 'AMBT', 'Денежные средства клиента - на торги') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (13, 'AMBF', 'Денежные средства клиента - свободные') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (14, 'AMBB', 'Денежные средства клиента - блокированные') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (15, 'TMBT', 'Требования по деньгам клиента - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (16, 'OSBT', 'Обязательства по инструментам клиента - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (17, 'OMBT', 'Обязательства по деньгам клиента - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (18, 'TSBT', 'Требования по инструментам клиента - клиринговый пул') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (19, 'CMBT', 'Требования по деньгам - клиента') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (20, 'LSBT', 'Обязательства по инструментам - клиента') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (21, 'LMBT', 'Обязательства по деньгам - клиента') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (22, 'CSBT', 'Требования по инструментам - клиента') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (23, 'DMAT', 'Возврат депозита по деньгам - свои') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_CODE_DICTIONARY(ID, CODE, NAME) values (24, 'DMBT', 'Возврат депозита по деньгам - клиента') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO REGISTRY_STATUS_DICTIONARY(ID, CODE, NAME) values (1, 'OK', 'Успешно') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
|
|
@ -1011,3 +1037,5 @@ INSERT INTO MARKET(ID, MARKET_TYPE, SECTION, SETTLEMENT_CURRENCY, CODE, NAME, EX
|
|||
INSERT INTO MARKET(ID, MARKET_TYPE, SECTION, SETTLEMENT_CURRENCY, CODE, NAME, EXCHANGE_ID, DESCRIPTION) values (79, 'SCND', 'FOND', 'RUB', 'DMIC', 'ОФЗИН-Дискретный аукцион', 1, 'ОФЗИН-Дискретный аукцион: Облигации Минфина') ON CONFLICT (ID) DO UPDATE SET MARKET_TYPE = EXCLUDED.MARKET_TYPE, SECTION = EXCLUDED.SECTION, SETTLEMENT_CURRENCY = EXCLUDED.SETTLEMENT_CURRENCY, CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME, EXCHANGE_ID = EXCLUDED.EXCHANGE_ID, DESCRIPTION = EXCLUDED.DESCRIPTION;
|
||||
|
||||
INSERT INTO MARKET(ID, MARKET_TYPE, SECTION, SETTLEMENT_CURRENCY, CODE, NAME, EXCHANGE_ID, DESCRIPTION) values (80, 'SCND', 'FOND', 'RUB', 'MMIC', 'ОФЗИН-Торги в режиме выкупа', 1, 'ОФЗИН-Торги в режиме выкупа: Облигации Минфина') ON CONFLICT (ID) DO UPDATE SET MARKET_TYPE = EXCLUDED.MARKET_TYPE, SECTION = EXCLUDED.SECTION, SETTLEMENT_CURRENCY = EXCLUDED.SETTLEMENT_CURRENCY, CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME, EXCHANGE_ID = EXCLUDED.EXCHANGE_ID, DESCRIPTION = EXCLUDED.DESCRIPTION;
|
||||
|
||||
INSERT INTO MARKET(ID, MARKET_TYPE, SECTION, SETTLEMENT_CURRENCY, CODE, NAME, EXCHANGE_ID, DESCRIPTION) values (81, 'PRMR', 'MKR', 'RUB', 'MKRS', 'Размещение', 1, 'Размещение: МКР') ON CONFLICT (ID) DO UPDATE SET MARKET_TYPE = EXCLUDED.MARKET_TYPE, SECTION = EXCLUDED.SECTION, SETTLEMENT_CURRENCY = EXCLUDED.SETTLEMENT_CURRENCY, CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME, EXCHANGE_ID = EXCLUDED.EXCHANGE_ID, DESCRIPTION = EXCLUDED.DESCRIPTION;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
<module>trade-importer</module>
|
||||
<module>lim-exporter</module>
|
||||
<module>swt-exporter</module>
|
||||
<module>swt-importer</module>
|
||||
<module>gateway-api</module>
|
||||
</modules>
|
||||
|
||||
|
|
|
|||
|
|
@ -135,9 +135,9 @@ public class ValidationConfig {
|
|||
},
|
||||
ReportError.WrongFieldValue,
|
||||
ReportError.RequiredFieldEmpty),
|
||||
EndDtAfterStartDtRule.instance("endDate", "startDate",
|
||||
ReportRequestWithPeriod::getEndDate,
|
||||
EndDtAfterStartDtRule.instance("startDate", "endDate",
|
||||
ReportRequestWithPeriod::getStartDate,
|
||||
ReportRequestWithPeriod::getEndDate,
|
||||
ReportError.RequiredFieldEmpty,
|
||||
ReportError.WrongFieldValue)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -104,6 +104,10 @@ public abstract class LiabilitiesClaimsReportBuilder<P> extends CSVReportBuilder
|
|||
execution.getTradingClearingRegistryId()
|
||||
);
|
||||
|
||||
if (registry == null) {
|
||||
log.warn("registry not found for companyId={}", execution.getCompanyId());
|
||||
}
|
||||
|
||||
String id = String.valueOf(execution.getId());
|
||||
String docDate = dateFormatter.format(nowDate);
|
||||
String docTime = timeFormatter.format(nowTime);
|
||||
|
|
@ -114,7 +118,7 @@ public abstract class LiabilitiesClaimsReportBuilder<P> extends CSVReportBuilder
|
|||
String sessionId = String.valueOf(execution.getSessionId());
|
||||
String clearingDate = dateFormatter.format(execution.getClearingDate());
|
||||
String clearingTime = dateFormatter.format(execution.getClearingDate());
|
||||
String trdAccId = registry.getTradingClearingRegistry();
|
||||
String trdAccId = registry == null? null : registry.getTradingClearingRegistry();
|
||||
String account = String.valueOf(tradingClearingRegistry.getMoneyAccountId());
|
||||
String depoAccount = String.valueOf(tradingClearingRegistry.getDepoAccountId());
|
||||
String currency = execution.getSettlementCurrency();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import java.time.ZoneId;
|
|||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
|
||||
@Deprecated
|
||||
public abstract class AbstractReportCollector<T extends AbstractReport> {
|
||||
public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy");
|
||||
public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import java.time.Instant;
|
|||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
|
||||
@Deprecated
|
||||
public abstract class ReportWithPeriodCollector<T extends AbstractReport> extends AbstractReportCollector<T> {
|
||||
/**
|
||||
* Подготовка отчета на период startDate..endDate
|
||||
|
|
|
|||
|
|
@ -4,12 +4,22 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.misc.Session;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportRequestWithPeriod;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportRequestWithSessionId;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportRequestWithSessionIdList;
|
||||
import ru.spcex.clearing.reports.config.ReportBuildersConfig;
|
||||
import ru.spcex.clearing.reports.config.element.ReportsServiceSettings;
|
||||
import ru.spcex.clearing.reports.reports.AbstractReport;
|
||||
import ru.spcex.clearing.reports.reports.ReportId;
|
||||
import ru.spcex.clearing.reports.reports.*;
|
||||
import ru.spcex.clearing.reports.services.builders.XMLReportBuilder;
|
||||
import ru.spcex.platform.enumeration.ReportType;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
|
|
@ -17,9 +27,7 @@ import ru.spcex.platform.utils.log.ExceptionUtils;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Исполняет создание отчётов.
|
||||
|
|
@ -35,17 +43,42 @@ public class ReportsServiceCommand implements InitializingBean {
|
|||
|
||||
protected ReportsServiceSettings settings;
|
||||
protected ImdgProvider imdg;
|
||||
|
||||
@Deprecated
|
||||
protected List<ReportWithPeriodCollector> allPeriodReports; // Spring services
|
||||
@Deprecated
|
||||
protected List<SimpleReportCollector> allSimpleReports;
|
||||
@Deprecated
|
||||
private final Map<ReportId, AbstractReportCollector> collectorForReportById;
|
||||
|
||||
// new format report:
|
||||
ReportService newReportService; // by ReportBuildersConfig
|
||||
Map<ReportType, List<CSVReportBuilder<EmptyParams>>> reportBuildersWithoutParams;
|
||||
Map<ReportType, List<CSVReportBuilder<SessionIdParam>>> reportBuildersWithSessionIdParam;
|
||||
Map<ReportType, List<CSVReportBuilder<SessionIdListParams>>> reportBuildersWithSessionIdListParam;
|
||||
Map<ReportType, List<CSVReportBuilder<PeriodParams>>> reportBuildersWithPeriodParams;
|
||||
|
||||
|
||||
@Autowired
|
||||
public ReportsServiceCommand(ImdgProvider imdg, List<ReportWithPeriodCollector> allPeriodReports,
|
||||
public ReportsServiceCommand(ImdgProvider imdg,
|
||||
List<ReportWithPeriodCollector> allPeriodReports,
|
||||
List<SimpleReportCollector> allSimpleReports,
|
||||
@Qualifier("reportBuildersWithoutParams") Map<ReportType, List<CSVReportBuilder<EmptyParams>>> reportBuildersWithoutParams,
|
||||
@Qualifier("reportBuildersWithSessionIdParam") Map<ReportType, List<CSVReportBuilder<SessionIdParam>>> reportBuildersWithSessionIdParam,
|
||||
@Qualifier("reportBuildersWithSessionIdListParam") Map<ReportType, List<CSVReportBuilder<SessionIdListParams>>> reportBuildersWithSessionIdListParam,
|
||||
@Qualifier("reportBuildersWithPeriodParams") Map<ReportType, List<CSVReportBuilder<PeriodParams>>> reportBuildersWithPeriodParams,
|
||||
|
||||
ReportService reportService,
|
||||
ReportsServiceSettings settings) {
|
||||
this.imdg = imdg;
|
||||
this.settings = settings;
|
||||
|
||||
this.newReportService = reportService;
|
||||
this.reportBuildersWithoutParams = reportBuildersWithoutParams;
|
||||
this.reportBuildersWithSessionIdParam = reportBuildersWithSessionIdParam;
|
||||
this.reportBuildersWithSessionIdListParam = reportBuildersWithSessionIdListParam;
|
||||
this.reportBuildersWithPeriodParams = reportBuildersWithPeriodParams;
|
||||
|
||||
this.allSimpleReports = allSimpleReports;
|
||||
this.allPeriodReports = allPeriodReports; // allReports = context.getBeansOfType(ReportDataCollector.class);
|
||||
this.collectorForReportById = new HashMap<>();
|
||||
|
|
@ -73,6 +106,75 @@ public class ReportsServiceCommand implements InitializingBean {
|
|||
}
|
||||
|
||||
public void generateReportAll(@Nullable String reportGroup, LocalDate startDate, LocalDate endDate) throws IOException {
|
||||
// new reports:
|
||||
{
|
||||
HashSet<ReportType> reported=new HashSet<>();
|
||||
for (ReportType rType : reportBuildersWithoutParams.keySet()) {
|
||||
if (reported.contains(rType)) continue;
|
||||
reported.add(rType);
|
||||
log.info("Make report {}", rType);
|
||||
try {
|
||||
BaseRequest<ReportRequest> request = new BaseRequest<>();
|
||||
request.setRequestPayload(new ReportRequest());
|
||||
request.getRequestPayload().setReportId(rType.getKey());
|
||||
newReportService.createReport(request);
|
||||
} catch (Exception e) {
|
||||
log.error("Error make report {}: {}", rType, ExceptionUtils.getStackTrace(e));
|
||||
}
|
||||
}
|
||||
Imdg<Session> sessionImdg = imdg.getImdg(IMDGDistributedNames.Map_Session, Session.class);
|
||||
Long sessionId = sessionImdg.aggregateLongMax("id", sessionImdg.predicateBuilder().greatEqual("id", 0L)); // max, always true
|
||||
log.info("For all report sessionId={}", sessionId);
|
||||
for (ReportType rType : reportBuildersWithSessionIdParam.keySet()) {
|
||||
if (reported.contains(rType)) continue;
|
||||
reported.add(rType);
|
||||
log.info("Make report {}, session {}", rType, sessionId);
|
||||
try {
|
||||
BaseRequest<ReportRequestWithSessionId> request = new BaseRequest<>();
|
||||
request.setRequestPayload(new ReportRequestWithSessionId());
|
||||
request.getRequestPayload().setReportId(rType.getKey());
|
||||
request.getRequestPayload().setSessionId(sessionId);
|
||||
newReportService.createReportForSessionId(request);
|
||||
} catch (Exception e) {
|
||||
log.error("Error make report {}: {}", rType, ExceptionUtils.getStackTrace(e));
|
||||
}
|
||||
}
|
||||
for (ReportType rType : reportBuildersWithSessionIdListParam.keySet()) {
|
||||
if (reported.contains(rType)) continue;
|
||||
reported.add(rType);
|
||||
log.info("Make report {}, sessions {}", rType, sessionId);
|
||||
try {
|
||||
BaseRequest<ReportRequestWithSessionIdList> request = new BaseRequest<>();
|
||||
request.setRequestPayload(new ReportRequestWithSessionIdList());
|
||||
request.getRequestPayload().setReportId(rType.getKey());
|
||||
request.getRequestPayload().setSessionIdList(Arrays.asList(sessionId));
|
||||
newReportService.createReportForSessionIdList(request);
|
||||
} catch (Exception e) {
|
||||
log.error("Error make report {}: {}", rType, ExceptionUtils.getStackTrace(e));
|
||||
}
|
||||
}
|
||||
for (ReportType rType : reportBuildersWithPeriodParams.keySet()) {
|
||||
if (reported.contains(rType)) continue;
|
||||
reported.add(rType);
|
||||
LocalDate d1=LocalDate.now().minusDays(1);
|
||||
LocalDate d2=LocalDate.now().minusDays(1);
|
||||
log.info("Make report {} period {} - {}", rType, d1, d2);
|
||||
try {
|
||||
BaseRequest<ReportRequestWithPeriod> request = new BaseRequest<>();
|
||||
request.setRequestPayload(new ReportRequestWithPeriod());
|
||||
request.getRequestPayload().setReportId(rType.getKey());
|
||||
request.getRequestPayload().setStartDate(d1);
|
||||
request.getRequestPayload().setStartDate(d2);
|
||||
newReportService.createReportForPeriod(request);
|
||||
} catch (Exception e) {
|
||||
log.error("Error make report {}: {}", rType, ExceptionUtils.getStackTrace(e));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log.info(" Old format report...");
|
||||
// deprecated code:
|
||||
for (ReportWithPeriodCollector<?> reportDataCollector : allPeriodReports) {
|
||||
if (reportGroup == null || QUEUE_RUN_REPORT_COMMAND.equals(reportGroup)) {
|
||||
try {
|
||||
|
|
@ -124,7 +226,7 @@ public class ReportsServiceCommand implements InitializingBean {
|
|||
XMLReportBuilder reportBuilder = new XMLReportBuilder(reportDataCollector.getReportClass(), outPath);
|
||||
AbstractReport report = reportDataCollector.collectReportWithPeriod(startDate, endDate);
|
||||
if (report == null) {
|
||||
throw new NullPointerException("reportDataCollector "+ reportDataCollector +" return null");
|
||||
throw new NullPointerException("reportDataCollector " + reportDataCollector + " return null");
|
||||
}
|
||||
File reportFile = reportBuilder.createReport(report);
|
||||
if (reportFile != null) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package ru.spcex.clearing.reports.services;
|
|||
|
||||
import ru.spcex.clearing.reports.reports.AbstractReport;
|
||||
|
||||
@Deprecated
|
||||
public abstract class SimpleReportCollector<T extends AbstractReport> extends AbstractReportCollector<T> {
|
||||
/**
|
||||
* Подготовка отчета (без входных параметров)
|
||||
|
|
|
|||
|
|
@ -100,12 +100,12 @@ public class EquitySecurityService extends QueueConsumer implements Initializing
|
|||
try {
|
||||
transaction.beginTransaction();
|
||||
Imdg<EquitySecurity> equityImdg = transaction.getImdg(IMDGDistributedNames.Map_EquitySecurity, EquitySecurity.class);
|
||||
Imdg<Listing> listingMap = transaction.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
|
||||
// Imdg<Listing> listingMap = transaction.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
|
||||
//одним скопом выполняем реквест
|
||||
equityImdg.insert(equity);
|
||||
Listing listing = ListingBuilder.builder()
|
||||
.append(equity).append(req).build();
|
||||
listingMap.insert(listing);
|
||||
// Listing listing = ListingBuilder.builder()
|
||||
// .append(equity).append(req).build();
|
||||
// listingMap.insert(listing);
|
||||
//и сохраняем обновленный
|
||||
// reqInfoMap.insert(reqInfo);
|
||||
transaction.commitTransaction();
|
||||
|
|
@ -144,13 +144,13 @@ public class EquitySecurityService extends QueueConsumer implements Initializing
|
|||
equity.setInstrumentType(req.getInstrumentType());
|
||||
|
||||
equitySecurityImdg.update(equity);
|
||||
Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", equity.getId()));
|
||||
if (listing == null) {
|
||||
log.error("MoneyMarketSecurityUpdateRequest id {} couldn't find listing with securityId {}", req.getId(), equity.getId());
|
||||
return null;
|
||||
}
|
||||
listing = updateListingByEquity(equity, listing);
|
||||
listingImdg.update(listing);
|
||||
// Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", equity.getId()));
|
||||
// if (listing == null) {
|
||||
// log.error("MoneyMarketSecurityUpdateRequest id {} couldn't find listing with securityId {}", req.getId(), equity.getId());
|
||||
// return null;
|
||||
// }
|
||||
// listing = updateListingByEquity(equity, listing);
|
||||
// listingImdg.update(listing);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -170,14 +170,14 @@ public class EquitySecurityService extends QueueConsumer implements Initializing
|
|||
equity.setUpdated(updateTime);
|
||||
equitySecurityImdg.update(equity);
|
||||
|
||||
Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", equity.getId()));
|
||||
if (listing == null) {
|
||||
log.error("CommonDeleteRequest id {} couldn't find listing with securityId {}", req.getId(), equity.getId());
|
||||
return null;
|
||||
}
|
||||
listing.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey());
|
||||
listing.setUpdated(updateTime);
|
||||
listingImdg.update(listing);
|
||||
// Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", equity.getId()));
|
||||
// if (listing == null) {
|
||||
// log.error("CommonDeleteRequest id {} couldn't find listing with securityId {}", req.getId(), equity.getId());
|
||||
// return null;
|
||||
// }
|
||||
// listing.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey());
|
||||
// listing.setUpdated(updateTime);
|
||||
// listingImdg.update(listing);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,12 +104,12 @@ public class FixedIncomeSecurityService extends QueueConsumer implements Initial
|
|||
try {
|
||||
transaction.beginTransaction();
|
||||
Imdg<FixedIncomeSecurity> fixedIncomeImdg = transaction.getImdg(IMDGDistributedNames.Map_FixedIncomeSecurity, FixedIncomeSecurity.class);
|
||||
Imdg<Listing> listingMap = transaction.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
|
||||
// Imdg<Listing> listingMap = transaction.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
|
||||
//одним скопом выполняем реквест
|
||||
fixedIncomeImdg.insert(fixedIncome);
|
||||
Listing listing = ListingBuilder.builder()
|
||||
.append(fixedIncome).append(req).build();
|
||||
listingMap.insert(listing);
|
||||
// Listing listing = ListingBuilder.builder()
|
||||
// .append(fixedIncome).append(req).build();
|
||||
// listingMap.insert(listing);
|
||||
//и сохраняем обновленный
|
||||
// reqInfoMap.insert(reqInfo);
|
||||
transaction.commitTransaction();
|
||||
|
|
@ -154,13 +154,13 @@ public class FixedIncomeSecurityService extends QueueConsumer implements Initial
|
|||
fixedIncome.setSecurityId(fixedIncome.getId());
|
||||
|
||||
fixedIncomeSecurityImdg.update(fixedIncome);
|
||||
Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", fixedIncome.getId()));
|
||||
if (listing == null) {
|
||||
log.error("updateFixedIncome id {} couldn't find listing with securityId {}", req.getId(), fixedIncome.getId());
|
||||
return null;
|
||||
}
|
||||
listing = updateListingByFixedIncome(fixedIncome, listing);
|
||||
listingImdg.update(listing);
|
||||
// Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", fixedIncome.getId()));
|
||||
// if (listing == null) {
|
||||
// log.error("updateFixedIncome id {} couldn't find listing with securityId {}", req.getId(), fixedIncome.getId());
|
||||
// return null;
|
||||
// }
|
||||
// listing = updateListingByFixedIncome(fixedIncome, listing);
|
||||
// listingImdg.update(listing);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -180,14 +180,14 @@ public class FixedIncomeSecurityService extends QueueConsumer implements Initial
|
|||
equity.setUpdated(updateTime);
|
||||
fixedIncomeSecurityImdg.update(equity);
|
||||
|
||||
Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", equity.getId()));
|
||||
if (listing == null) {
|
||||
log.error("CommonDeleteRequest id {} couldn't find listing with securityId {}", req.getId(), equity.getId());
|
||||
return null;
|
||||
}
|
||||
listing.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey());
|
||||
listing.setUpdated(updateTime);
|
||||
listingImdg.update(listing);
|
||||
// Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", equity.getId()));
|
||||
// if (listing == null) {
|
||||
// log.error("CommonDeleteRequest id {} couldn't find listing with securityId {}", req.getId(), equity.getId());
|
||||
// return null;
|
||||
// }
|
||||
// listing.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey());
|
||||
// listing.setUpdated(updateTime);
|
||||
// listingImdg.update(listing);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,199 @@
|
|||
package ru.spcex.clearing.securities.service.cud;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.kafka.clients.consumer.Consumer;
|
||||
import org.apache.kafka.clients.producer.Producer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.instrument.issue.EquitySecurity;
|
||||
import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity;
|
||||
import ru.clearing.classes.statics.data.misc.Listing;
|
||||
import ru.clearing.classes.statics.data.security.MoneyMarketSecurity;
|
||||
import ru.clearing.classes.statics.data.security.Security;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.ListingNewRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.ListingUpdateRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
|
||||
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
|
||||
import ru.spcex.clearing.securities.validation.ValidationProvider;
|
||||
import ru.spcex.clearing.util.security.UserRoleVerification;
|
||||
import ru.spcex.clearing.validation.common.ValidationHelper;
|
||||
import ru.spcex.platform.enumeration.UserRole;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgId;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.api.ImdgTransaction;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Service
|
||||
public class ListingService extends QueueConsumer implements InitializingBean {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final Imdg<FixedIncomeSecurity> fixedIncomeSecurityImdg;
|
||||
private final Imdg<MoneyMarketSecurity> moneyMarketSecurityImdg;
|
||||
private final Imdg<EquitySecurity> equitySecurity;
|
||||
|
||||
private final Imdg<Listing> listingImdg;
|
||||
private final ImdgProvider imdgProvider;
|
||||
private final ImdgId idGenerator;
|
||||
private final ValidationProvider validation;
|
||||
private final UserRoleVerification userRoleVerification;
|
||||
private final ValidationHelper validationHelper;
|
||||
|
||||
@Autowired
|
||||
public ListingService(Consumer<String, Object> kafkaQueue,
|
||||
Producer<String, Object> kafkaProducer,
|
||||
ImdgProvider imdgProvider,
|
||||
ValidationProvider validation,
|
||||
UserRoleVerification userRoleVerification,
|
||||
ValidationHelper validationHelper) {
|
||||
super(kafkaQueue, kafkaProducer);
|
||||
this.validation = validation;
|
||||
this.fixedIncomeSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_FixedIncomeSecurity, FixedIncomeSecurity.class);
|
||||
this.moneyMarketSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, MoneyMarketSecurity.class);
|
||||
this.equitySecurity = imdgProvider.getImdg(IMDGDistributedNames.Map_EquitySecurity, EquitySecurity.class);
|
||||
this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.idGenerator = imdgProvider.getImdgIdGenerator();
|
||||
this.userRoleVerification = userRoleVerification.setRoleForVerification(UserRole.Admin);
|
||||
this.validationHelper = validationHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
callback(ListingNewRequest.class)
|
||||
.setFunction(this::newListing)
|
||||
.forDestination(Consts.LISTING_NEW, callbacks::put);
|
||||
callback(ListingUpdateRequest.class)
|
||||
.setFunction(this::updateListing)
|
||||
.forDestination(Consts.LISTING_UPDATE, callbacks::put);
|
||||
callback(CommonDeleteRequest.class)
|
||||
.setFunction(this::deleteListing)
|
||||
.forDestination(Consts.LISTING_DELETE, callbacks::put);
|
||||
imdgProvider.waitAvailable();
|
||||
init();
|
||||
}
|
||||
|
||||
protected Security selectSecurityById(Long securityId) {
|
||||
Security security = fixedIncomeSecurityImdg.getSingleObjectByID(securityId);
|
||||
if (security != null) return security;
|
||||
security = moneyMarketSecurityImdg.getSingleObjectByID(securityId);
|
||||
if (security != null) return security;
|
||||
security = equitySecurity.getSingleObjectByID(securityId);
|
||||
if (security != null) return security;
|
||||
|
||||
return security;
|
||||
}
|
||||
|
||||
private RequestInfoUpdate newListing(BaseRequest<ListingNewRequest> userRequest) {
|
||||
ImdgTransaction transaction = imdgProvider.newTransaction();
|
||||
ListingNewRequest req = userRequest.getRequestPayload();
|
||||
|
||||
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
// RequestInfoUpdate requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, validation.listingNewValidator());
|
||||
// if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
/*
|
||||
todo
|
||||
3. Проверяем значения полученных параметров:
|
||||
3.1. Необходимо выполнить ряд проверок, стандартных для всех методов (проверка на обязательность параметров исключена).
|
||||
3.2. Проверить, что в таблице security есть инструмент, для которого нужно добавить листинг по security.id = securityId из очереди. Если такой записи нет, вернуть ошибку (1011) «Инструмент %s не найден».
|
||||
3.3. Проверить, что в таблице security тип инструмента instrumentType ≠ RATE (см. справочник instrumentType). Если тип инструмента другой, вернуть ошибку (1021) «Информиция об инструментах Денежного рынка на режимах добавляется автоматически».
|
||||
3.4. Проверить, что в таблице market есть режим, с которым нужно добавить листинг по market.code = market из очереди. Если такой записи нет, вернуть ошибку (1020) «Режим %s не найден».
|
||||
3.5. Проверить, что еще нет такой же записи в таблице listing по ключу securityId И market И со статусом listing.workflowStatus=ACTV (см. справочник workflowStatus). Если запись существует, вернуть ошибку (1017) «Инструмент на режиме %s уже существует».
|
||||
*/
|
||||
|
||||
log.debug("newListing received");
|
||||
|
||||
Security security = selectSecurityById(req.getSecurityId());
|
||||
if (security == null) {
|
||||
log.error("Security not found {}", req.getSecurityId());
|
||||
//return validationHelper.getMessageResolver()
|
||||
//todo error!
|
||||
}
|
||||
|
||||
Listing listing = new Listing();
|
||||
listing.setId(idGenerator.nextId());
|
||||
listing.setCreated(Instant.now());
|
||||
listing.setUpdated(listing.getCreated());
|
||||
listing.setSecurityId(req.getSecurityId());
|
||||
listing.setMarket(req.getMarket());
|
||||
listing.setLotSize(req.getLotSize());
|
||||
listing.setSymbolCode(security.getSecuritySymbol()); // listing.setSymbolCode(req.getSymbolCode());
|
||||
listing.setSymbolName(security.getFullName()); // req.getSymbolName
|
||||
listing.setTradingCurrency(req.getTradingCurrency());
|
||||
if (StringUtils.isEmpty(req.getWorkflowStatus())) {
|
||||
listing.setWorkflowStatus(WorkflowStatus.Active.getKey());
|
||||
} else {
|
||||
listing.setWorkflowStatus(req.getWorkflowStatus());
|
||||
}
|
||||
|
||||
listingImdg.insert(listing);
|
||||
log.debug("successfully processed, request id {}, new object id {}", userRequest.getId(), listing.getId());
|
||||
return null; // default success
|
||||
}
|
||||
|
||||
private RequestInfoUpdate updateListing(BaseRequest<ListingUpdateRequest> userRequest) {
|
||||
ListingUpdateRequest req = userRequest.getRequestPayload();
|
||||
log.debug("updateListing received id = {}", req.getId());
|
||||
|
||||
|
||||
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
// RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
|
||||
// if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
Listing listing = listingImdg.getSingleObjectByID(req.getId());
|
||||
|
||||
Security security = selectSecurityById(req.getSecurityId());
|
||||
if (security == null) {
|
||||
log.error("Security not found {}", req.getSecurityId());
|
||||
//return validationHelper.getMessageResolver()
|
||||
//todo error!
|
||||
}
|
||||
if (listing == null) {
|
||||
log.error("listing not found {}", req.getId());
|
||||
//return validationHelper.getMessageResolver()
|
||||
//todo error!
|
||||
}
|
||||
|
||||
listing.setUpdated(Instant.now());
|
||||
listing.setLotSize(req.getLotSize());
|
||||
//if (req.getSymbolCode()!=null) listing.setSymbolCode(req.getSymbolCode());
|
||||
//if (req.getSymbolName!=null) listing.setSymbolName(req.getSymbolName);
|
||||
listing.setTradingCurrency(req.getTradingCurrency());
|
||||
if (StringUtils.isNotEmpty(req.getWorkflowStatus())) {
|
||||
listing.setWorkflowStatus(req.getWorkflowStatus());
|
||||
}
|
||||
|
||||
listingImdg.update(listing);
|
||||
return null;
|
||||
}
|
||||
|
||||
private RequestInfoUpdate deleteListing(BaseRequest<CommonDeleteRequest> userRequest) {
|
||||
CommonDeleteRequest req = userRequest.getRequestPayload();
|
||||
log.debug("CommonDeleteRequest received id = {}", req.getId());
|
||||
|
||||
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
// requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, validation.listingDeleteValidator());
|
||||
// if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
Instant updateTime = Instant.now();
|
||||
Listing listing = listingImdg.getSingleObjectByID(req.getId());
|
||||
listing.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey());
|
||||
listing.setUpdated(updateTime);
|
||||
|
||||
listingImdg.update(listing);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -138,11 +138,9 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial
|
|||
Imdg<Listing> listingMap = transaction.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
|
||||
//одним скопом выполняем реквест
|
||||
moneyMarketSecurityMap.insert(mms);
|
||||
Listing listing = ListingBuilder.builder()
|
||||
.append(mms).append(req).build();
|
||||
listingMap.insert(listing);
|
||||
//и сохраняем обновленный
|
||||
// reqInfoMap.insert(reqInfo);
|
||||
// Listing listing = ListingBuilder.builder()
|
||||
// .append(mms).append(req).build();
|
||||
// listingMap.insert(listing);
|
||||
transaction.commitTransaction();
|
||||
} catch (Throwable e) {
|
||||
transaction.rollbackTransaction();
|
||||
|
|
@ -193,13 +191,13 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial
|
|||
mms.setWorkflowStatus(req.getWorkflowStatus());
|
||||
|
||||
moneyMarketSecurityMap.update(mms);
|
||||
Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", mms.getId()));
|
||||
if (listing == null) {
|
||||
log.error("MoneyMarketSecurityUpdateRequest id {} couldn't find listing with securityId {}", req.getId(), mms.getId());
|
||||
return null;
|
||||
}
|
||||
listing = updateListingByMms(mms, listing);
|
||||
listingImdg.update(listing);
|
||||
// Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", mms.getId()));
|
||||
// if (listing == null) {
|
||||
// log.error("MoneyMarketSecurityUpdateRequest id {} couldn't find listing with securityId {}", req.getId(), mms.getId());
|
||||
// return null;
|
||||
// }
|
||||
// listing = updateListingByMms(mms, listing);
|
||||
// listingImdg.update(listing);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -227,14 +225,14 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial
|
|||
mms.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey());
|
||||
mms.setUpdated(updateTime);
|
||||
moneyMarketSecurityMap.update(mms);
|
||||
Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", mms.getId()));
|
||||
if (listing == null) {
|
||||
log.error("CommonDeleteRequest id {} couldn't find listing with securityId {}", req.getId(), mms.getId());
|
||||
return null;
|
||||
}
|
||||
listing.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey());
|
||||
listing.setUpdated(updateTime);
|
||||
listingImdg.update(listing);
|
||||
// Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", mms.getId()));
|
||||
// if (listing == null) {
|
||||
// log.error("CommonDeleteRequest id {} couldn't find listing with securityId {}", req.getId(), mms.getId());
|
||||
// return null;
|
||||
// }
|
||||
// listing.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey());
|
||||
// listing.setUpdated(updateTime);
|
||||
// listingImdg.update(listing);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,14 +64,15 @@ public class ValidationProvider {
|
|||
MoneyMarketSecurityNewRequest::getStartDate,
|
||||
MoneyMarketSecurityNewRequest::getEndDate,
|
||||
SecuritiesError.RequiredFieldIsEmpty,
|
||||
SecuritiesError.WrongFieldValue),
|
||||
SecuritiesError.WrongFieldValue,
|
||||
false),
|
||||
new NotPresentBySecuritySymbolAndWorkflowStatusActv(IMDGDistributedNames.Map_MoneyMarketSecurity, SecuritiesError.InstrumentAlreadyExists, MoneyMarketSecurityNewRequest.class),
|
||||
new IsValidInstrumentTypeFromRequest(SecuritiesError.RequiredFieldIsEmpty, "RATE"),
|
||||
MmsNewValidationRule.RequiredFieldIsNotEmpty,
|
||||
new HaveValidCompanyId<>(MoneyMarketSecurityNewRequest::getIssuerId, "issuerId"),
|
||||
new HaveValidCompanyId<>(MoneyMarketSecurityNewRequest::getIssuerId, "issuerId", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_InstrumentTypeDictionary, MoneyMarketSecurityNewRequest::getInstrumentType, "instrumentType"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, MoneyMarketSecurityNewRequest::getWorkflowStatus, "workflowStatus"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_TermTypeDictionary, MoneyMarketSecurityNewRequest::getTermType, "termType"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, MoneyMarketSecurityNewRequest::getWorkflowStatus, "workflowStatus", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_TermTypeDictionary, MoneyMarketSecurityNewRequest::getTermType, "termType", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_CurrencyCodeDictionary, MoneyMarketSecurityNewRequest::getNominalCurrency, "nominalCurrency")
|
||||
);
|
||||
};
|
||||
|
|
@ -92,15 +93,15 @@ public class ValidationProvider {
|
|||
MoneyMarketSecurityUpdateRequest::getStartDate,
|
||||
MoneyMarketSecurityUpdateRequest::getEndDate,
|
||||
SecuritiesError.RequiredFieldIsEmpty,
|
||||
SecuritiesError.WrongFieldValue),
|
||||
SecuritiesError.WrongFieldValue,
|
||||
false),
|
||||
new PresentById(IMDGDistributedNames.Map_MoneyMarketSecurity, SecuritiesError.InstrumentNotFound, true),
|
||||
new IsValidInstrumentTypeById(SecuritiesError.InstrumentNotFound, "RATE"),
|
||||
new WorkflowStatusActv(),
|
||||
new HaveValidCompanyId<>(MoneyMarketSecurityUpdateRequest::getIssuerId, "issuerId"),
|
||||
new HaveValidCompanyId<>(MoneyMarketSecurityUpdateRequest::getIssuerId, "issuerId", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_InstrumentTypeDictionary, MoneyMarketSecurityUpdateRequest::getInstrumentType, "instrumentType"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, MoneyMarketSecurityUpdateRequest::getWorkflowStatus, "workflowStatus"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_TermTypeDictionary, MoneyMarketSecurityUpdateRequest::getTermType, "termType"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_CurrencyCodeDictionary, MoneyMarketSecurityUpdateRequest::getNominalCurrency, "nominalCurrency")
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, MoneyMarketSecurityUpdateRequest::getWorkflowStatus, "workflowStatus", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_TermTypeDictionary, MoneyMarketSecurityUpdateRequest::getTermType, "termType", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_CurrencyCodeDictionary, MoneyMarketSecurityUpdateRequest::getNominalCurrency, "nominalCurrency", false)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
@ -131,10 +132,10 @@ public class ValidationProvider {
|
|||
new NotPresentBySecuritySymbolAndWorkflowStatusActv(IMDGDistributedNames.Map_EquitySecurity, SecuritiesError.InstrumentAlreadyExists, EquitySecurityNewRequest.class),
|
||||
new IsValidInstrumentTypeFromRequest(SecuritiesError.RequiredFieldIsEmpty, "EQTY"),
|
||||
EquityNewValidationRule.RequiredFieldIsNotEmpty,
|
||||
new HaveValidCompanyId<>(EquitySecurityNewRequest::getIssuerId, "issuerId"),
|
||||
new HaveValidCompanyId<>(EquitySecurityNewRequest::getIssuerId, "issuerId", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_InstrumentTypeDictionary, EquitySecurityNewRequest::getInstrumentType, "instrumentType"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, EquitySecurityNewRequest::getWorkflowStatus, "workflowStatus"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_ShareTypeDictionary, EquitySecurityNewRequest::getShareType, "shareType"));
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, EquitySecurityNewRequest::getWorkflowStatus, "workflowStatus", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_ShareTypeDictionary, EquitySecurityNewRequest::getShareType, "shareType", false));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -150,11 +151,10 @@ public class ValidationProvider {
|
|||
return new ValidatorImpl<>(context,
|
||||
new PresentById(IMDGDistributedNames.Map_EquitySecurity, SecuritiesError.InstrumentNotFound, true),
|
||||
new IsValidInstrumentTypeById(SecuritiesError.InstrumentNotFound, "EQTY"),
|
||||
new WorkflowStatusActv(),
|
||||
new HaveValidCompanyId<>(EquitySecurityUpdateRequest::getIssuerId, "issuerId"),
|
||||
new HaveValidCompanyId<>(EquitySecurityUpdateRequest::getIssuerId, "issuerId", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_InstrumentTypeDictionary, EquitySecurityUpdateRequest::getInstrumentType, "instrumentType"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, EquitySecurityUpdateRequest::getWorkflowStatus, "workflowStatus"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_ShareTypeDictionary, EquitySecurityUpdateRequest::getShareType, "shareType"));
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, EquitySecurityUpdateRequest::getWorkflowStatus, "workflowStatus", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_ShareTypeDictionary, EquitySecurityUpdateRequest::getShareType, "shareType", false));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -185,11 +185,11 @@ public class ValidationProvider {
|
|||
new NotPresentBySecuritySymbolAndWorkflowStatusActv(IMDGDistributedNames.Map_FixedIncomeSecurity, SecuritiesError.InstrumentAlreadyExists, FixedIncomeSecurityNewRequest.class),
|
||||
new IsValidInstrumentTypeFromRequest(SecuritiesError.RequiredFieldIsEmpty, "BOND"),
|
||||
FixedIncomeNewValidationRule.RequiredFieldIsNotEmpty,
|
||||
new HaveValidCompanyId<>(FixedIncomeSecurityNewRequest::getIssuerId, "issuerId"),
|
||||
new HaveValidCompanyId<>(FixedIncomeSecurityNewRequest::getIssuerId, "issuerId", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_InstrumentTypeDictionary, FixedIncomeSecurityNewRequest::getInstrumentType, "instrumentType"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, FixedIncomeSecurityNewRequest::getWorkflowStatus, "workflowStatus"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_BondTypeDictionary, FixedIncomeSecurityNewRequest::getBondType, "bondType"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_CurrencyCodeDictionary, FixedIncomeSecurityNewRequest::getNominalCurrency, "nominalCurrency")
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, FixedIncomeSecurityNewRequest::getWorkflowStatus, "workflowStatus", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_BondTypeDictionary, FixedIncomeSecurityNewRequest::getBondType, "bondType", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_CurrencyCodeDictionary, FixedIncomeSecurityNewRequest::getNominalCurrency, "nominalCurrency", false)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
@ -208,12 +208,11 @@ public class ValidationProvider {
|
|||
return new ValidatorImpl<>(context,
|
||||
new PresentById(IMDGDistributedNames.Map_FixedIncomeSecurity, SecuritiesError.InstrumentNotFound, true),
|
||||
new IsValidInstrumentTypeById(SecuritiesError.InstrumentNotFound, "BOND"),
|
||||
new WorkflowStatusActv(),
|
||||
new HaveValidCompanyId<>(FixedIncomeSecurityUpdateRequest::getIssuerId, "issuerId"),
|
||||
new HaveValidCompanyId<>(FixedIncomeSecurityUpdateRequest::getIssuerId, "issuerId", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_InstrumentTypeDictionary, FixedIncomeSecurityUpdateRequest::getInstrumentType, "instrumentType"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, FixedIncomeSecurityUpdateRequest::getWorkflowStatus, "workflowStatus"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_BondTypeDictionary, FixedIncomeSecurityUpdateRequest::getBondType, "bondType"),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_CurrencyCodeDictionary, FixedIncomeSecurityUpdateRequest::getNominalCurrency, "nominalCurrency")
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_WorkflowStatusDictionary, FixedIncomeSecurityUpdateRequest::getWorkflowStatus, "workflowStatus", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_BondTypeDictionary, FixedIncomeSecurityUpdateRequest::getBondType, "bondType", false),
|
||||
new HaveValidCodeByDictionary<>(IMDGDistributedNames.Map_CurrencyCodeDictionary, FixedIncomeSecurityUpdateRequest::getNominalCurrency, "nominalCurrency", false)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ public enum EquityNewValidationRule implements IValidationRule<ImdgValidationCon
|
|||
if (!StringUtils.hasText(action.getShortName())){
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, "shortName");
|
||||
}
|
||||
if (action.getLotSize() == null) {
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, "lotSize");
|
||||
}
|
||||
return empty();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ public enum FixedIncomeNewValidationRule implements IValidationRule<ImdgValidati
|
|||
if (!StringUtils.hasText(action.getShortName())){
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, "shortName");
|
||||
}
|
||||
if (action.getLotSize() == null) {
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, "lotSize");
|
||||
}
|
||||
return empty();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,21 +12,33 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Deprecated // use common validator
|
||||
public class HaveValidCodeByDictionary<R> implements IValidationRule<ImdgValidationContext<R>> {
|
||||
String mapName;
|
||||
String errArg;
|
||||
Function<R, String> codeGetter;
|
||||
boolean required;
|
||||
public HaveValidCodeByDictionary(String mapName, Function<R, String> codeGetter, String errArg, boolean required) {
|
||||
this.mapName = mapName;
|
||||
this.codeGetter = codeGetter;
|
||||
this.errArg = errArg;
|
||||
this.required = required;
|
||||
}
|
||||
public HaveValidCodeByDictionary(String mapName, Function<R, String> codeGetter, String errArg) {
|
||||
this.mapName = mapName;
|
||||
this.codeGetter = codeGetter;
|
||||
this.errArg = errArg;
|
||||
this.required = true;
|
||||
}
|
||||
@Override
|
||||
public Optional<EnumMessage> validate(ImdgValidationContext<R> context) {
|
||||
R validatedObject = context.getValidatedObject();
|
||||
String code = codeGetter.apply(validatedObject);
|
||||
if(!StringUtils.hasText(code)) {
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, errArg);
|
||||
if (required)
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, errArg);
|
||||
else
|
||||
return empty();
|
||||
}
|
||||
Imdg<SpcexObjectBase> imdgDictionary = context.obtainMap(mapName, SpcexObjectBase.class);
|
||||
SpcexObjectBase dictionary = imdgDictionary.getSingleObjectByFieldValues(Map.of(
|
||||
|
|
|
|||
|
|
@ -11,19 +11,30 @@ import ru.spcex.platform.utils.validation.IValidationRule;
|
|||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Deprecated // use common validator
|
||||
public class HaveValidCompanyId<R> implements IValidationRule<ImdgValidationContext<R>> {
|
||||
Function<R, Long> idGetter;
|
||||
String errArg;
|
||||
boolean required;
|
||||
public HaveValidCompanyId(Function<R, Long> idGetter, String errArg, boolean required) {
|
||||
this.idGetter = idGetter;
|
||||
this.errArg = errArg;
|
||||
this.required=required;
|
||||
}
|
||||
public HaveValidCompanyId(Function<R, Long> idGetter, String errArg) {
|
||||
this.idGetter = idGetter;
|
||||
this.errArg = errArg;
|
||||
this.required=true;
|
||||
}
|
||||
@Override
|
||||
public Optional<EnumMessage> validate(ImdgValidationContext<R> context) {
|
||||
R validatedObject = context.getValidatedObject();
|
||||
Long id = idGetter.apply(validatedObject);
|
||||
if(id == null) {
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, errArg);
|
||||
if (required)
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, errArg);
|
||||
else
|
||||
return empty();
|
||||
}
|
||||
Imdg<SpcexObjectBase> imdgDictionary = context.obtainMap(IMDGDistributedNames.Map_Company, SpcexObjectBase.class);
|
||||
SpcexObjectBase dictionary = imdgDictionary.getSingleObjectByID(id);
|
||||
|
|
|
|||
|
|
@ -17,18 +17,6 @@ public enum MmsNewValidationRule implements IValidationRule<ImdgValidationContex
|
|||
if (!StringUtils.hasText(action.getShortName())){
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, "shortName");
|
||||
}
|
||||
if (action.getLotSize() == null) {
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, "lotSize");
|
||||
}
|
||||
if (action.getNominalValue() == null) {
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, "nominalValue");
|
||||
}
|
||||
if (!StringUtils.hasText(action.getNominalCurrency())) {
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, "nominalCurrency");
|
||||
}
|
||||
if (!StringUtils.hasText(action.getTermType())) {
|
||||
return of(SecuritiesError.RequiredFieldIsEmpty, "termType");
|
||||
}
|
||||
return empty();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
103
clearing-parent/swt-importer/pom.xml
Normal file
103
clearing-parent/swt-importer/pom.xml
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>clearing-parent</artifactId>
|
||||
<groupId>ru.spcex.clearing</groupId>
|
||||
<version>SPCEX-1.0.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>swt-importer</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring boot -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JDBC -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>c3p0</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DBF files -->
|
||||
<dependency>
|
||||
<groupId>com.github.albfernandez</groupId>
|
||||
<artifactId>javadbf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.platform</groupId>
|
||||
<artifactId>platform-imdg-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.platform</groupId>
|
||||
<artifactId>platform-imdg-api-hazelcast-impl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.clearing</groupId>
|
||||
<artifactId>classes</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.platform</groupId>
|
||||
<artifactId>platform-messaging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.platform</groupId>
|
||||
<artifactId>platform-enum</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<excludes>
|
||||
<exclude>application.properties</exclude>
|
||||
</excludes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package ru.spcex.clearing.swt.importer;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SWTImporterApplication {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder(SWTImporterApplication.class);
|
||||
builder.run(args);
|
||||
} catch (Exception e) {
|
||||
LoggerFactory.getLogger(SWTImporterApplication.class).error("SWT-Loader start failed: {} -> {}", e.getClass().getSimpleName(), e.getMessage());
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package ru.spcex.clearing.swt.importer.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.swt.importer.config.settings.ImportSWTServiceSettings;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
|
||||
|
||||
@Configuration
|
||||
public class ImporterImdgConfig {
|
||||
private static ThreadPoolTaskExecutor createThreadPoolTaskExecutor(int maxPoolSz, boolean waitForCompletion) {
|
||||
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
|
||||
if (maxPoolSz > 2) {
|
||||
pool.setKeepAliveSeconds(60);
|
||||
pool.setAllowCoreThreadTimeOut(true);
|
||||
}
|
||||
pool.setCorePoolSize(maxPoolSz);
|
||||
pool.setWaitForTasksToCompleteOnShutdown(waitForCompletion);
|
||||
return pool;
|
||||
}
|
||||
|
||||
@Bean(name = "taskExecutorHazelcastClientInitializer")
|
||||
public ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer() {
|
||||
return createThreadPoolTaskExecutor(1, true);
|
||||
}
|
||||
|
||||
@Bean(name = "taskExecutorIdGeneratorAwaiter")
|
||||
public ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter() {
|
||||
return createThreadPoolTaskExecutor(1, false);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@Bean
|
||||
public HazelcastService imdgProvider(
|
||||
@Qualifier("taskExecutorHazelcastClientInitializer") ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer,
|
||||
@Qualifier("taskExecutorIdGeneratorAwaiter") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter,
|
||||
ImportSWTServiceSettings settings
|
||||
) {
|
||||
return new HazelcastService(taskExecutorHazelcastClientInitializer,
|
||||
taskExecutorIdGeneratorAwaiter,
|
||||
settings.getHazelcast());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package ru.spcex.clearing.swt.importer.config;
|
||||
|
||||
import org.apache.kafka.clients.consumer.Consumer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.kafka.core.KafkaTemplate;
|
||||
import org.springframework.kafka.core.ProducerFactory;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.config.KafkaConsumerFactory;
|
||||
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.swt.importer.config.settings.ImportSWTServiceSettings;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgId;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Configuration
|
||||
public class KafkaConfig {
|
||||
|
||||
@Bean
|
||||
public ProducerFactory<String, Object> pf(ImportSWTServiceSettings settings) {
|
||||
KafkaProducerSettings kafkaSettings = settings.getKafkaProducer();
|
||||
return KafkaProducerFactory.producerFactory(kafkaSettings);
|
||||
}
|
||||
|
||||
@Bean("kafkaTemplate")
|
||||
public KafkaTemplate<String, Object> kafkaTemplate(ProducerFactory<String, Object> pf) {
|
||||
return new KafkaTemplate<>(pf);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@Bean
|
||||
public Supplier<KafkaSender> kafkaSender(KafkaTemplate<String, Object> kafkaTemplate,
|
||||
ImdgProvider imdgProvider) {
|
||||
ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator();
|
||||
return () -> KafkaSender
|
||||
.setup()
|
||||
.setKafkaTemplate(kafkaTemplate)
|
||||
.idGenerator(imdgIdGenerator::nextId)
|
||||
.imdgProvider(s -> {
|
||||
Imdg<RequestInfo> imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class);
|
||||
return imdg::insert;
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Bean
|
||||
public Consumer<String, Object> createConsumer(ImportSWTServiceSettings settings) {
|
||||
return KafkaConsumerFactory.consumer(settings.getKafkaConsumer());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package ru.spcex.clearing.swt.importer.config;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import ru.spcex.clearing.swt.importer.config.settings.ImportSWTServiceSettings;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.tables.AbstractTable;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.tables.SDf08Table;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.tables.SDf10Table;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.tables.SDf13Table;
|
||||
import ru.spcex.clearing.swt.importer.logic.stages.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@ComponentScan(basePackages = {"ru.spcex.clearing.swt.importer"})
|
||||
public class SWTImporterConfig {
|
||||
private final ImportSWTServiceSettings settings;
|
||||
private final ApplicationContext context;
|
||||
|
||||
|
||||
public SWTImporterConfig(ImportSWTServiceSettings settings, ApplicationContext context) {
|
||||
this.settings = settings;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Bean("pipeline")
|
||||
public List<Stage> pipeline() {
|
||||
List<Stage> pipeline = new LinkedList<>();
|
||||
pipeline.add(context.getBean(LoadFileFromDisk.class));
|
||||
pipeline.add(context.getBean(ValidateFields.class));
|
||||
pipeline.add(context.getBean(ImportToDB.class));
|
||||
pipeline.add(context.getBean(ChangeDirOfFileStage.class));
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
@Bean("executor")
|
||||
public ThreadPoolTaskExecutor executor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setMaxPoolSize(settings.getCommon().getThreadsCount());
|
||||
executor.setCorePoolSize(settings.getCommon().getThreadsCount());
|
||||
executor.setThreadNamePrefix("swt-importer-thread-");
|
||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||
executor.setAwaitTerminationSeconds(300);
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
|
||||
@Bean("mapOfTable")
|
||||
public Map<ETable, AbstractTable> getMapOfTables() {
|
||||
Map<ETable, AbstractTable> map = new HashMap<>();
|
||||
map.put(ETable.S_DF_08, new SDf08Table());
|
||||
map.put(ETable.S_DF_10, new SDf10Table());
|
||||
map.put(ETable.S_DF_13, new SDf13Table());
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package ru.spcex.clearing.swt.importer.config.settings;
|
||||
|
||||
public class Common {
|
||||
|
||||
private String encodingSource;
|
||||
private int insertBatchSize;
|
||||
private int threadsCount;
|
||||
|
||||
public String getEncodingSource() {
|
||||
return encodingSource;
|
||||
}
|
||||
|
||||
public void setEncodingSource(String encodingSource) {
|
||||
this.encodingSource = encodingSource;
|
||||
}
|
||||
|
||||
public int getInsertBatchSize() {
|
||||
return insertBatchSize;
|
||||
}
|
||||
|
||||
public void setInsertBatchSize(int insertBatchSize) {
|
||||
this.insertBatchSize = insertBatchSize;
|
||||
}
|
||||
|
||||
public int getThreadsCount() {
|
||||
return threadsCount;
|
||||
}
|
||||
|
||||
public void setThreadsCount(int threadsCount) {
|
||||
this.threadsCount = threadsCount;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package ru.spcex.clearing.swt.importer.config.settings;
|
||||
|
||||
public class Cron {
|
||||
|
||||
private String checkSrcDirCron;
|
||||
|
||||
public String getCheckSrcDirCron() {
|
||||
return checkSrcDirCron;
|
||||
}
|
||||
|
||||
public void setCheckSrcDirCron(String checkSrcDirCron) {
|
||||
this.checkSrcDirCron = checkSrcDirCron;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package ru.spcex.clearing.swt.importer.config.settings;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.spcex.clearing.platform.messaging.config.element.KafkaConsumerSettings;
|
||||
import ru.spcex.clearing.platform.messaging.config.element.KafkaProducerSettings;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams;
|
||||
|
||||
@Component
|
||||
@PropertySource("file:${spring.config.location}/application.properties")
|
||||
@ConfigurationProperties("import-swt-service")
|
||||
public class ImportSWTServiceSettings {
|
||||
private HazelcastClientParams hazelcast;
|
||||
private KafkaProducerSettings kafkaProducer;
|
||||
private KafkaConsumerSettings kafkaConsumer;
|
||||
private Common common;
|
||||
private Store store;
|
||||
private Cron cron;
|
||||
|
||||
public HazelcastClientParams getHazelcast() {
|
||||
return hazelcast;
|
||||
}
|
||||
|
||||
public void setHazelcast(HazelcastClientParams hazelcast) {
|
||||
this.hazelcast = hazelcast;
|
||||
}
|
||||
|
||||
public KafkaProducerSettings getKafkaProducer() {
|
||||
return kafkaProducer;
|
||||
}
|
||||
|
||||
public void setKafkaProducer(KafkaProducerSettings kafkaProducer) {
|
||||
this.kafkaProducer = kafkaProducer;
|
||||
}
|
||||
|
||||
public KafkaConsumerSettings getKafkaConsumer() {
|
||||
return kafkaConsumer;
|
||||
}
|
||||
|
||||
public void setKafkaConsumer(KafkaConsumerSettings kafkaConsumer) {
|
||||
this.kafkaConsumer = kafkaConsumer;
|
||||
}
|
||||
|
||||
public Common getCommon() {
|
||||
return common;
|
||||
}
|
||||
|
||||
public void setCommon(Common common) {
|
||||
this.common = common;
|
||||
}
|
||||
|
||||
public Store getStore() {
|
||||
return store;
|
||||
}
|
||||
|
||||
public void setStore(Store store) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
public Cron getCron() {
|
||||
return cron;
|
||||
}
|
||||
|
||||
public void setCron(Cron cron) {
|
||||
this.cron = cron;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package ru.spcex.clearing.swt.importer.config.settings;
|
||||
|
||||
public class Store {
|
||||
|
||||
private String srcDir;
|
||||
private String outDir;
|
||||
private String outDirError;
|
||||
private boolean deleteSrcFiles = true;
|
||||
|
||||
public String getSrcDir() {
|
||||
return srcDir;
|
||||
}
|
||||
|
||||
public void setSrcDir(String srcDir) {
|
||||
this.srcDir = srcDir;
|
||||
}
|
||||
|
||||
public String getOutDir() {
|
||||
return outDir;
|
||||
}
|
||||
|
||||
public void setOutDir(String outDir) {
|
||||
this.outDir = outDir;
|
||||
}
|
||||
|
||||
public boolean isDeleteSrcFiles() {
|
||||
return deleteSrcFiles;
|
||||
}
|
||||
|
||||
public void setDeleteSrcFiles(boolean deleteSrcFiles) {
|
||||
this.deleteSrcFiles = deleteSrcFiles;
|
||||
}
|
||||
|
||||
public String getOutDirError() {
|
||||
return outDirError;
|
||||
}
|
||||
|
||||
public void setOutDirError(String outDirError) {
|
||||
this.outDirError = outDirError;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package ru.spcex.clearing.swt.importer.controller;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import ru.spcex.clearing.swt.importer.services.SWTImporterService;
|
||||
|
||||
@Controller("/")
|
||||
public class ImporterController implements InitializingBean {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final SWTImporterService importerService;
|
||||
|
||||
public ImporterController(@Qualifier("swtImporterService") SWTImporterService importerService) {
|
||||
this.importerService = importerService;
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, path = "/import", produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
@ResponseBody
|
||||
public String checkFolder() {
|
||||
log.info("Call check method for importer controller");
|
||||
importerService.run();
|
||||
return "dbf import complete, see log";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
log.info("controller started");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package ru.spcex.clearing.swt.importer.controller;
|
||||
|
||||
import org.apache.kafka.clients.consumer.Consumer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
import ru.spcex.clearing.swt.importer.services.SWTImporterService;
|
||||
import ru.spcex.platform.enumeration.Task;
|
||||
|
||||
@Service
|
||||
public class LauncherCommandReceiver extends QueueConsumer implements InitializingBean {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final SWTImporterService importer;
|
||||
|
||||
@Autowired
|
||||
public LauncherCommandReceiver(Consumer<String, Object> kafkaQueue,
|
||||
SWTImporterService importer) {
|
||||
super(kafkaQueue);
|
||||
this.importer = importer;
|
||||
}
|
||||
|
||||
/**
|
||||
* В реальности не используется
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
callback(LauncherCommandRequest.class)
|
||||
.setConsumer(action -> importer.run(ETable.S_DF_08))
|
||||
.forDestination(Task.createOrderConfirm.topic(), callbacks::put); // CORC
|
||||
callback(LauncherCommandRequest.class)
|
||||
.setConsumer(action -> importer.run(ETable.S_DF_10))
|
||||
.forDestination(Task.accrualOfBalance.topic(), callbacks::put); // GBAL
|
||||
callback(LauncherCommandRequest.class)
|
||||
.setConsumer(action -> importer.run(ETable.S_DF_13))
|
||||
.forDestination(Task.getBalance.topic(), callbacks::put); // GBLD
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package ru.spcex.clearing.swt.importer.exceptions;
|
||||
|
||||
public class ConfigException extends RuntimeException {
|
||||
public ConfigException(String msg) { super(msg); }
|
||||
public ConfigException(String msg, Throwable cause) { super(msg, cause); }
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package ru.spcex.clearing.swt.importer.logic;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.ResultContainer;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.StageResult;
|
||||
import ru.spcex.clearing.swt.importer.logic.stages.Stage;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component("processor")
|
||||
public class Processor {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final List<Stage> pipeline;
|
||||
|
||||
public Processor(@Qualifier("pipeline") List<Stage> pipeline) {
|
||||
this.pipeline = pipeline;
|
||||
}
|
||||
|
||||
public void process(ResultContainer task) {
|
||||
log.info("uuid {}. Task started", task.getUuid());
|
||||
long startMills = System.currentTimeMillis();
|
||||
for (Stage currStage : pipeline) {
|
||||
if (statusIsFinal(task.getLastStageStatus()) && currStage.skipCompleted()) {
|
||||
continue;
|
||||
}
|
||||
log.info("uuid {}. Stage: {}", task.getUuid(), currStage.getClass().getSimpleName());
|
||||
task.setLastStageStatus(currStage.process(task));
|
||||
log.info("uuid {}. Stage {} finished with status {}", task.getUuid(), currStage.getClass().getSimpleName(), task.getLastStageStatus());
|
||||
}
|
||||
long endMills = System.currentTimeMillis();
|
||||
log.info("uuid {}. Task completed, result: {}, time working: {} ms",
|
||||
task.getUuid(),
|
||||
task,
|
||||
endMills - startMills);
|
||||
}
|
||||
|
||||
private boolean statusIsFinal(StageResult previousStageStatus) {
|
||||
return Arrays.asList(StageResult.ERROR, StageResult.COMPLETE).contains(previousStageStatus);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data;
|
||||
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ColumnType;
|
||||
|
||||
public class ColumnStructureSWT {
|
||||
private String name;
|
||||
private ColumnType type;
|
||||
private int length;
|
||||
private int decimalDigits;
|
||||
private String comment;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public ColumnType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(ColumnType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setLength(int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public int getDecimalDigits() {
|
||||
return decimalDigits;
|
||||
}
|
||||
|
||||
public void setDecimalDigits(int decimalDigits) {
|
||||
this.decimalDigits = decimalDigits;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public void setComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data;
|
||||
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DBStructureSWT {
|
||||
private Map<ETable, TableStructureSWT> tables = new EnumMap<>(ETable.class);
|
||||
|
||||
public Map<ETable, TableStructureSWT> getTables() {
|
||||
return tables;
|
||||
}
|
||||
|
||||
public void setTables(Map<ETable, TableStructureSWT> tables) {
|
||||
this.tables = tables;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data;
|
||||
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.StageResult;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Контейнер для передачи результата между стадиями
|
||||
*/
|
||||
public class ResultContainer {
|
||||
private UUID uuid;
|
||||
private ETable swtTable;
|
||||
private File swtFile;
|
||||
private StageResult lastStageStatus;
|
||||
|
||||
private byte[] swtSource;
|
||||
|
||||
protected ResultContainer() {
|
||||
}
|
||||
|
||||
public static ResultContainer createNewTask(ETable swtTable, File swtFile) {
|
||||
ResultContainer container = new ResultContainer();
|
||||
container.swtTable = swtTable;
|
||||
container.swtFile = swtFile;
|
||||
container.uuid = UUID.randomUUID();
|
||||
return container;
|
||||
}
|
||||
|
||||
public ETable getSwtTable() {
|
||||
return swtTable;
|
||||
}
|
||||
|
||||
public void setSwtTable(ETable swtTable) {
|
||||
this.swtTable = swtTable;
|
||||
}
|
||||
|
||||
public byte[] getSwtSource() {
|
||||
return swtSource;
|
||||
}
|
||||
|
||||
public void setSwtSource(byte[] swtSource) {
|
||||
this.swtSource = swtSource;
|
||||
}
|
||||
|
||||
public File getSwtFile() {
|
||||
return swtFile;
|
||||
}
|
||||
|
||||
public void setSwtFile(File swtFile) {
|
||||
this.swtFile = swtFile;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public StageResult getLastStageStatus() {
|
||||
return lastStageStatus;
|
||||
}
|
||||
|
||||
public void setLastStageStatus(StageResult lastStageRes) {
|
||||
this.lastStageStatus = lastStageRes;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class TableStructureSWT {
|
||||
private Map<String, ColumnStructureSWT> columns = new HashMap<>();
|
||||
|
||||
public Map<String, ColumnStructureSWT> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public void setColumns(Map<String, ColumnStructureSWT> columns) {
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
public ColumnStructureSWT getIgnoreCase(String columnName) {
|
||||
for (Map.Entry<String, ColumnStructureSWT> entry : columns.entrySet()) {
|
||||
String currColumnName = entry.getKey();
|
||||
if (currColumnName.equalsIgnoreCase(columnName)) return entry.getValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data.enums;
|
||||
|
||||
import com.linuxense.javadbf.DBFDataType;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* Типы данных в таблицах.
|
||||
* Ставит в соответствие типы PostGRE и DBF
|
||||
*/
|
||||
public enum ColumnType {
|
||||
VARCHAR(DBFDataType.CHARACTER, Types.VARCHAR),
|
||||
CHARACTER(DBFDataType.CHARACTER, Types.CHAR),
|
||||
NUMERIC(DBFDataType.NUMERIC, Types.NUMERIC),
|
||||
DATE(DBFDataType.DATE, Types.DATE);
|
||||
|
||||
private final DBFDataType dbfType;
|
||||
private final int sqlType;
|
||||
|
||||
ColumnType(DBFDataType dbfType, int postgreSqlType) {
|
||||
this.dbfType = dbfType;
|
||||
this.sqlType = postgreSqlType;
|
||||
}
|
||||
|
||||
public DBFDataType getDbfType() {
|
||||
return dbfType;
|
||||
}
|
||||
|
||||
public int getSqlType() {
|
||||
return sqlType;
|
||||
}
|
||||
|
||||
public static ColumnType getForSQLType(int sqlType) {
|
||||
for (ColumnType columnType : values()) {
|
||||
if (columnType.sqlType == sqlType) return columnType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ColumnType getForDBFType(DBFDataType dbfType) {
|
||||
for (ColumnType columnType : values()) {
|
||||
if (columnType.dbfType == dbfType) return columnType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data.enums;
|
||||
|
||||
public enum ETable {
|
||||
S_DF_08("DF-08"),
|
||||
S_DF_10("DF-10"),
|
||||
S_DF_13("DF-13");
|
||||
//S_DF20("DF-20");
|
||||
|
||||
private final String prefix;
|
||||
|
||||
ETable(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public static ETable getTableForFilename(String filename) {
|
||||
for (ETable table : ETable.values()) {
|
||||
if (table.fileForThisTable(filename)) return table;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ETable tableForName(String name) {
|
||||
for (ETable table : values()) {
|
||||
if (name.equalsIgnoreCase(table.name()))
|
||||
return table;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean fileForThisTable(String filename) {
|
||||
return filename != null && filename.contains(prefix);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data.enums;
|
||||
|
||||
public enum StageResult {
|
||||
OK,
|
||||
ERROR,
|
||||
COMPLETE
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data.tables;
|
||||
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgHazelcast;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
|
||||
|
||||
public abstract class AbstractTable<T extends SpcexObjectBase> {
|
||||
private final String prefix;
|
||||
private final Class<T> clazz;
|
||||
private final String nameOfMap;
|
||||
protected HazelcastService hazelcastService;
|
||||
protected ImdgHazelcast<T> map;
|
||||
protected String filename;
|
||||
protected Long fileId;
|
||||
|
||||
protected AbstractTable(String prefix, Class<T> clazz, String nameOfMap) {
|
||||
this.prefix = prefix;
|
||||
this.clazz = clazz;
|
||||
this.nameOfMap = nameOfMap;
|
||||
}
|
||||
|
||||
public void setFileId(Long fileId) {
|
||||
this.fileId = fileId;
|
||||
}
|
||||
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public void setHazelcastService(HazelcastService hazelcastService) {
|
||||
this.hazelcastService = hazelcastService;
|
||||
}
|
||||
|
||||
public abstract T getEntity(String[] entity);
|
||||
|
||||
public void injectEntity(T obj) {
|
||||
if (map == null) {
|
||||
bootMap();
|
||||
}
|
||||
map.insert(obj);
|
||||
}
|
||||
|
||||
private void bootMap() {
|
||||
map = (ImdgHazelcast<T>) hazelcastService.getImdg(nameOfMap, clazz);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data.tables;
|
||||
|
||||
import ru.clearing.classes.statics.data.sdf.SDf08;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class SDf08Table extends AbstractTable<SDf08> {
|
||||
|
||||
private static final String PREFIX = ETable.S_DF_08.name();
|
||||
private static final Class<SDf08> CLAZZ = SDf08.class;
|
||||
private static final String NAME_OF_HZ_MAP = IMDGDistributedNames.Map_SDf08;
|
||||
|
||||
public SDf08Table() {
|
||||
super(PREFIX, CLAZZ, NAME_OF_HZ_MAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SDf08 getEntity(String[] entity) {
|
||||
SDf08 result = new SDf08();
|
||||
result.setDepoCode(entity[0]);
|
||||
result.setQuantity(entity[1]);
|
||||
result.setSecurityCode(entity[2]);
|
||||
result.setClientName(entity[5]);
|
||||
result.setFileName(filename);
|
||||
result.setGenerationTime(Instant.now());
|
||||
result.setGenerationId(fileId);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data.tables;
|
||||
|
||||
import ru.clearing.classes.statics.data.sdf.SDf10;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class SDf10Table extends AbstractTable<SDf10> {
|
||||
|
||||
private static final String PREFIX = ETable.S_DF_10.name();
|
||||
private static final Class<SDf10> CLAZZ = SDf10.class;
|
||||
private static final String NAME_OF_HZ_MAP = IMDGDistributedNames.Map_SDf10;
|
||||
|
||||
public SDf10Table() {
|
||||
super(PREFIX, CLAZZ, NAME_OF_HZ_MAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SDf10 getEntity(String[] entity) {
|
||||
SDf10 result = new SDf10();
|
||||
result.setDepoCode(entity[0]);
|
||||
result.setQuantity(entity[1]);
|
||||
result.setSecurityCode(entity[2]);
|
||||
result.setClientName(entity[5]);
|
||||
result.setFileName(filename);
|
||||
result.setGenerationTime(Instant.now());
|
||||
result.setGenerationId(fileId);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.data.tables;
|
||||
|
||||
import ru.clearing.classes.statics.data.sdf.SDf13;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class SDf13Table extends AbstractTable<SDf13> {
|
||||
|
||||
private static final String PREFIX = ETable.S_DF_13.name();
|
||||
private static final Class<SDf13> CLAZZ = SDf13.class;
|
||||
private static final String NAME_OF_HZ_MAP = IMDGDistributedNames.Map_SDf13;
|
||||
|
||||
public SDf13Table() {
|
||||
super(PREFIX, CLAZZ, NAME_OF_HZ_MAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SDf13 getEntity(String[] entity) {
|
||||
SDf13 result = new SDf13();
|
||||
result.setFileName(filename);
|
||||
result.setGenerationTime(Instant.now());
|
||||
result.setGenerationId(fileId);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.stages;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.spcex.clearing.swt.importer.config.settings.ImportSWTServiceSettings;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.ResultContainer;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.StageResult;
|
||||
import ru.spcex.platform.utils.time.TimeUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||
|
||||
|
||||
@Component
|
||||
public class ChangeDirOfFileStage extends Stage {
|
||||
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy.MM.dd HH.mm.ss");
|
||||
private final ImportSWTServiceSettings settings;
|
||||
|
||||
@Autowired
|
||||
public ChangeDirOfFileStage(ImportSWTServiceSettings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipCompleted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StageResult process(ResultContainer resultContainer) {
|
||||
File srcDir = new File(settings.getStore().getSrcDir());
|
||||
File outDir;
|
||||
if (resultContainer.getLastStageStatus().equals(StageResult.ERROR)) {
|
||||
outDir = new File(settings.getStore().getOutDirError());
|
||||
|
||||
} else {
|
||||
outDir = new File(settings.getStore().getOutDir());
|
||||
}
|
||||
File dbfFile = resultContainer.getSwtFile();
|
||||
|
||||
if (!srcDir.exists()) {
|
||||
log.error("SettlementHouse_DocIn does not exists!");
|
||||
return StageResult.ERROR;
|
||||
}
|
||||
if (!outDir.exists()) {
|
||||
log.warn("ouput directory {} does not exists! Trying to made new!", outDir.getAbsolutePath());
|
||||
if (outDir.mkdir()) {
|
||||
log.error("Made dir {} successfully!", outDir.getName());
|
||||
} else {
|
||||
log.error("SettlementHouse_DocIn does not exists!");
|
||||
return StageResult.ERROR;
|
||||
}
|
||||
}
|
||||
if (!dbfFile.exists()) {
|
||||
log.error("SWT file to save does not exists!");
|
||||
return StageResult.ERROR;
|
||||
}
|
||||
String newNameOfFile = TimeUtil.formatInstant(Instant.now(), FORMATTER) + '_' + dbfFile.getName();
|
||||
|
||||
try {
|
||||
Files.move(dbfFile.toPath(), outDir.toPath().resolve(newNameOfFile), REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
log.error("Could not move file {}", e.getMessage());
|
||||
return StageResult.ERROR;
|
||||
}
|
||||
|
||||
if (resultContainer.getLastStageStatus().equals(StageResult.ERROR)) {
|
||||
return StageResult.ERROR;
|
||||
} else {
|
||||
return StageResult.COMPLETE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.stages;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.spcex.clearing.swt.importer.config.settings.ImportSWTServiceSettings;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.ResultContainer;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.StageResult;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.tables.AbstractTable;
|
||||
import ru.spcex.clearing.swt.importer.util.SWTReader;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Заливка проверенных данных в базу
|
||||
*/
|
||||
@Component
|
||||
public class ImportToDB extends Stage {
|
||||
private final ImportSWTServiceSettings settings;
|
||||
private final HazelcastService hazelcastService;
|
||||
private final Map<ETable, AbstractTable> mappingEnumTableObjectTable;
|
||||
private final SWTImportKafkaMessenger kafkaMessenger;
|
||||
|
||||
public ImportToDB(ImportSWTServiceSettings settings,
|
||||
HazelcastService hazelcastService,
|
||||
@Qualifier("mapOfTable") Map<ETable, AbstractTable> mappingEnumTableObjectTable,
|
||||
SWTImportKafkaMessenger kafkaMessenger) {
|
||||
this.settings = settings;
|
||||
this.hazelcastService = hazelcastService;
|
||||
this.mappingEnumTableObjectTable = mappingEnumTableObjectTable;
|
||||
this.kafkaMessenger = kafkaMessenger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StageResult process(ResultContainer resultContainer) {
|
||||
ETable currTable = resultContainer.getSwtTable();
|
||||
byte[] source = resultContainer.getSwtSource();
|
||||
Charset sourceCharset = Charset.forName(settings.getCommon().getEncodingSource());
|
||||
|
||||
|
||||
|
||||
try (InputStream is = new ByteArrayInputStream(source);
|
||||
SWTReader swtReader = new SWTReader(is, sourceCharset)) {
|
||||
AbstractTable table = mappingEnumTableObjectTable.get(currTable);
|
||||
table.setHazelcastService(hazelcastService);
|
||||
table.setFilename(resultContainer.getSwtFile().getName());
|
||||
Long fileId = hazelcastService.getImdgIdGenerator().nextId();
|
||||
table.setFileId(fileId);
|
||||
int counter = 0;
|
||||
while (swtReader.hasNextRecord()) {
|
||||
counter++;
|
||||
String[] entity = swtReader.nextRecord();
|
||||
if (entity == null) {
|
||||
log.warn("record index {} null", counter);
|
||||
continue;
|
||||
}
|
||||
table.injectEntity(table.getEntity(entity));
|
||||
}
|
||||
kafkaMessenger.notifySystemIfNeeded(currTable, fileId);
|
||||
} catch (IOException exception) {
|
||||
log.warn(exception.getMessage());
|
||||
return StageResult.ERROR;
|
||||
} catch (Throwable e) {
|
||||
log.error(ExceptionUtils.getStackTrace(e));
|
||||
return StageResult.ERROR;
|
||||
}
|
||||
|
||||
|
||||
return StageResult.OK;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.stages;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.spcex.clearing.swt.importer.config.settings.ImportSWTServiceSettings;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.ResultContainer;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.StageResult;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
public class LoadFileFromDisk extends Stage {
|
||||
private final ImportSWTServiceSettings settings;
|
||||
|
||||
public LoadFileFromDisk(ImportSWTServiceSettings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StageResult process(ResultContainer resultContainer) {
|
||||
Objects.requireNonNull(resultContainer.getSwtFile());
|
||||
UUID taskUuid = resultContainer.getUuid();
|
||||
|
||||
File swtFile = resultContainer.getSwtFile();
|
||||
byte[] fileBytes;
|
||||
try {
|
||||
log.debug("uuid {}. Read all bytes from source file {}", taskUuid, resultContainer.getSwtFile().getName());
|
||||
fileBytes = Files.readAllBytes(Paths.get(swtFile.getAbsolutePath()));
|
||||
if (fileBytes.length == 0) throw new IOException("Empty file");
|
||||
if (settings.getStore().isDeleteSrcFiles()) Files.delete(swtFile.toPath());
|
||||
} catch (IOException e) {
|
||||
log.error(String.format("uuid %s. Can't read file %s", taskUuid, resultContainer.getSwtFile().getName()), e);
|
||||
return StageResult.ERROR;
|
||||
}
|
||||
log.debug("uuid {}. Read all bytes from source file complete", taskUuid);
|
||||
resultContainer.setSwtSource(fileBytes);
|
||||
return StageResult.OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.stages;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
import ru.spcex.platform.enumeration.SdfTable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Component
|
||||
public class SWTImportKafkaMessenger implements InitializingBean {
|
||||
private final Supplier<KafkaSender> kafka;
|
||||
private final Map<ETable, Consumer<Long>> messengers;
|
||||
|
||||
public SWTImportKafkaMessenger(Supplier<KafkaSender> kafka) {
|
||||
this.kafka = kafka;
|
||||
this.messengers = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
messengers.put(ETable.S_DF_08, groupId -> messageBalance(groupId, SdfTable.SDF_08));
|
||||
messengers.put(ETable.S_DF_10, groupId -> messageBalance(groupId, SdfTable.SDF_10));
|
||||
messengers.put(ETable.S_DF_13, groupId -> messageBalance(groupId, SdfTable.SDF_13));
|
||||
}
|
||||
|
||||
/**
|
||||
* отправляет в кафку сообщение, при необходимости
|
||||
* (обрабатывается, например, в balance-service, clearing-service)
|
||||
*/
|
||||
public void notifySystemIfNeeded(ETable table, Long groupId) {
|
||||
Consumer<Long> messenger = messengers.get(table);
|
||||
if (messenger != null) {
|
||||
messenger.accept(groupId);
|
||||
}
|
||||
}
|
||||
|
||||
private void messageBalance(Long groupId, SdfTable table) {
|
||||
StatementRequest statementRequest = new StatementRequest();
|
||||
statementRequest.setGroupId(groupId);
|
||||
statementRequest.setTable(table);
|
||||
kafka.get().sendRequestToQueue(Consts.STATEMENT_PROCESS, statementRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.stages;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.ResultContainer;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.StageResult;
|
||||
|
||||
public abstract class Stage {
|
||||
protected Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
public abstract StageResult process(ResultContainer resultContainer);
|
||||
|
||||
public boolean skipCompleted() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package ru.spcex.clearing.swt.importer.logic.stages;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.spcex.clearing.swt.importer.config.settings.ImportSWTServiceSettings;
|
||||
import ru.spcex.clearing.swt.importer.exceptions.ConfigException;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.ResultContainer;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.StageResult;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Фильтрация источника на предмет соответствия полей
|
||||
*/
|
||||
@Component
|
||||
public class ValidateFields extends Stage implements InitializingBean {
|
||||
private final ImportSWTServiceSettings settings;
|
||||
private Charset swtCharset;
|
||||
|
||||
public ValidateFields(ImportSWTServiceSettings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StageResult process(ResultContainer resultContainer) {
|
||||
return StageResult.OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Проверяет кодировку из настройки swt.encoding-source
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
initSWTCharset();
|
||||
}
|
||||
|
||||
private void initSWTCharset() {
|
||||
try {
|
||||
swtCharset = Charset.forName(settings.getCommon().getEncodingSource());
|
||||
} catch (Exception e) {
|
||||
throw new ConfigException("Unknown encoding from properties: " + settings.getCommon().getEncodingSource(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package ru.spcex.clearing.swt.importer.services;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.spcex.clearing.swt.importer.config.settings.ImportSWTServiceSettings;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
@Service("fileChecker")
|
||||
public class FileChecker {
|
||||
private final ImportSWTServiceSettings settings;
|
||||
|
||||
public FileChecker(ImportSWTServiceSettings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public Map<ETable, List<File>> checkNewFiles() {
|
||||
return checkNewFiles(null);
|
||||
}
|
||||
|
||||
public Map<ETable, List<File>> checkNewFiles(ETable specificTable) {
|
||||
Map<ETable, List<File>> newFiles = new EnumMap<>(ETable.class);
|
||||
|
||||
String srcDir = settings.getStore().getSrcDir();
|
||||
List<File> swtFiles = lsSWT(srcDir);
|
||||
if (swtFiles.isEmpty()) return newFiles;
|
||||
|
||||
for (File swtFile : swtFiles) {
|
||||
if (swtFile.isDirectory()) continue;
|
||||
|
||||
ETable currTable = ETable.getTableForFilename(swtFile.getName());
|
||||
if (currTable == null) continue;
|
||||
if (specificTable != null && !specificTable.equals(currTable)) continue;
|
||||
List<File> currList = newFiles.computeIfAbsent(currTable, list -> new LinkedList<>());
|
||||
currList.add(swtFile);
|
||||
}
|
||||
return newFiles;
|
||||
}
|
||||
|
||||
private List<File> lsSWT(String swtDirPath) {
|
||||
File swtDir = new File(swtDirPath);
|
||||
File[] swtFiles = swtDir.listFiles((dir, name) -> {
|
||||
String offsetName = name.substring(0, 9);
|
||||
return offsetName.equalsIgnoreCase("RDC_KS_DF");
|
||||
});
|
||||
|
||||
List<File> resultFiles = new LinkedList<>();
|
||||
if (swtFiles != null && swtFiles.length >= 1) {
|
||||
resultFiles.addAll(Arrays.asList(swtFiles));
|
||||
}
|
||||
|
||||
return resultFiles;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package ru.spcex.clearing.swt.importer.services;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.spcex.clearing.swt.importer.logic.Processor;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.ResultContainer;
|
||||
import ru.spcex.clearing.swt.importer.logic.data.enums.ETable;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Service("swtImporterService")
|
||||
@EnableScheduling
|
||||
public class SWTImporterService {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final FileChecker fileChecker;
|
||||
private final ThreadPoolTaskExecutor executorService;
|
||||
private final Processor processor;
|
||||
private final Set<Path> filesCurrentlyInProcess;
|
||||
|
||||
public SWTImporterService(@Qualifier("fileChecker") FileChecker messageListener,
|
||||
@Qualifier("executor") ThreadPoolTaskExecutor executorService,
|
||||
@Qualifier("processor") Processor processor) {
|
||||
this.fileChecker = messageListener;
|
||||
this.executorService = executorService;
|
||||
this.processor = processor;
|
||||
this.filesCurrentlyInProcess = new HashSet<>();
|
||||
}
|
||||
|
||||
private static String forLogging(Map<ETable, List<File>> files) {
|
||||
return files
|
||||
.entrySet()
|
||||
.stream()
|
||||
.flatMap((Function<Map.Entry<ETable, List<File>>, Stream<String>>) entry -> {
|
||||
List<String> r = new LinkedList<>();
|
||||
for (File file : entry.getValue()) {
|
||||
r.add(entry.getKey().name() + " " + file.toPath());
|
||||
}
|
||||
return r.stream();
|
||||
})
|
||||
.collect(Collectors.joining(";", "[", "]"));
|
||||
}
|
||||
|
||||
private static String forLoggingSizeOnly(Map<ETable, List<File>> files) {
|
||||
return files
|
||||
.entrySet()
|
||||
.stream()
|
||||
.map(entry -> entry.getKey().name() + " " + entry.getValue().size())
|
||||
.collect(Collectors.joining(";", "[", "]"));
|
||||
}
|
||||
|
||||
@Scheduled(cron = "${import-swt-service.scheduler.check-src-dir-cron}")
|
||||
public void run() {
|
||||
run(null);
|
||||
}
|
||||
|
||||
public void run(ETable specificTable) {
|
||||
if (specificTable == null) {
|
||||
log.trace("adding import task");
|
||||
} else {
|
||||
log.info("adding import task {}", specificTable);
|
||||
}
|
||||
executorService.execute(() -> {
|
||||
Map<ETable, List<File>> newFiles = null;
|
||||
try {
|
||||
log.trace("checking new files... {}", specificTable != null ? specificTable.name() : "");
|
||||
newFiles = getFiles(specificTable);
|
||||
if (newFiles.size() > 0 && log.isDebugEnabled()) {
|
||||
log.debug("following files will be processed {}", forLogging(newFiles));
|
||||
} else if (newFiles.size() > 0) {
|
||||
log.info("following files will be processed {}", forLoggingSizeOnly(newFiles));
|
||||
} else {
|
||||
log.trace("no files were found");
|
||||
}
|
||||
for (Map.Entry<ETable, List<File>> newFilesEntry : newFiles.entrySet()) {
|
||||
ETable currTable = newFilesEntry.getKey();
|
||||
List<File> fileList = newFilesEntry.getValue();
|
||||
for (File swtFile : fileList) {
|
||||
processor.process(ResultContainer.createNewTask(currTable, swtFile));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (newFiles != null && newFiles.size() > 0) {
|
||||
cleanFiles(newFiles);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private synchronized Map<ETable, List<File>> getFiles(ETable specificTable) {
|
||||
Map<ETable, List<File>> newFiles = fileChecker.checkNewFiles(specificTable);
|
||||
Map<ETable, List<File>> newFilesFiltered = newFiles.entrySet()
|
||||
.stream()
|
||||
.map(entry ->
|
||||
new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue()
|
||||
.stream()
|
||||
.filter(file -> !filesCurrentlyInProcess.contains(file.toPath()))
|
||||
.collect(Collectors.toList())))
|
||||
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
|
||||
newFilesFiltered.forEach((table, files)
|
||||
-> files.forEach(file -> filesCurrentlyInProcess.add(file.toPath())));
|
||||
return newFilesFiltered;
|
||||
}
|
||||
|
||||
private synchronized void cleanFiles(Map<ETable, List<File>> filesFromTask) {
|
||||
filesFromTask.forEach((table, files)
|
||||
-> files.forEach(file -> filesCurrentlyInProcess.remove(file.toPath())));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package ru.spcex.clearing.swt.importer.util;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class SWTReader implements Closeable {
|
||||
protected InputStream inputStream;
|
||||
protected Scanner scanner;
|
||||
|
||||
public SWTReader(InputStream inputStream, Charset charset) {
|
||||
this.inputStream = inputStream;
|
||||
this.scanner = new Scanner(inputStream, charset);
|
||||
}
|
||||
|
||||
public String[] nextRecord() {
|
||||
String line = scanner.nextLine();
|
||||
String[] separetedLine = line.split(":");
|
||||
if (separetedLine.length < 5) {
|
||||
return null;
|
||||
}
|
||||
return separetedLine;
|
||||
}
|
||||
|
||||
public boolean hasNextRecord() {
|
||||
return scanner.hasNextLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
server.port=8080
|
||||
server.servlet.context-path=/importer-swt
|
||||
spring.main.web-application-type=servlet
|
||||
|
||||
import-swt-service.scheduler.check-src-dir-cron=* * * * 1 ?
|
||||
|
||||
import-swt-service.store.delete-src-files=false
|
||||
import-swt-service.store.src-dir=/opt/clearing/file/importer/
|
||||
import-swt-service.store.out-dir=/opt/clearing/file/importer/loaded/
|
||||
import-swt-service.store.out-dir-error=/opt/clearing/file/importer/error/
|
||||
|
||||
import-swt-service.common.encoding-source=cp866
|
||||
import-swt-service.common.insert-batch-size=100
|
||||
import-swt-service.common.threads-count=10
|
||||
|
||||
import-swt-service.hazelcast.cluster-members=10.200.200.181:5701
|
||||
import-swt-service.hazelcast.login=dev
|
||||
import-swt-service.hazelcast.password=dev-pass
|
||||
|
||||
|
||||
import-swt-service.kafka-producer.bootstrap-servers=localhost:9092
|
||||
import-swt-service.kafka-producer.acks=all
|
||||
import-swt-service.kafka-producer.retries=0
|
||||
import-swt-service.kafka-producer.batch-size=16384
|
||||
import-swt-service.kafka-producer.linger-ms=1
|
||||
import-swt-service.kafka-producer.buffer-memory=33554432
|
||||
|
||||
import-swt-service.kafka-consumer.bootstrap-servers=localhost:9092
|
||||
import-swt-service.kafka-consumer.group-id=dev-group-clearing-service
|
||||
import-swt-service.kafka-consumer.enable-auto-commit=false
|
||||
import-swt-service.kafka-consumer.session-timeout-ms=30000
|
||||
import-swt-service.kafka-consumer.auto-offset-reset=latest
|
||||
import-swt-service.kafka-consumer.linger-ms=1
|
||||
import-swt-service.kafka-consumer.buffer-memory=33554432
|
||||
37
clearing-parent/swt-importer/src/main/resources/logback.xml
Normal file
37
clearing-parent/swt-importer/src/main/resources/logback.xml
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<configuration>
|
||||
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<charset>UTF-8</charset>
|
||||
<pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>./logs/swt-importer.log</file>
|
||||
<encoder>
|
||||
<charset>UTF-8</charset>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
|
||||
<fileNamePattern>
|
||||
../logs/swt-importer.%i.log
|
||||
</fileNamePattern>
|
||||
<minIndex>1</minIndex>
|
||||
<maxIndex>10</maxIndex>
|
||||
</rollingPolicy>
|
||||
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
|
||||
<maxFileSize>500MB</maxFileSize>
|
||||
</triggeringPolicy>
|
||||
</appender>
|
||||
|
||||
<root level="warn">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<appender-ref ref="FILE"/>
|
||||
</root>
|
||||
|
||||
<logger name="ru.spcex" level="debug" additivity="false">
|
||||
<appender-ref ref="FILE"/>
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
</configuration>
|
||||
|
|
@ -6,6 +6,7 @@ public enum InstrumentType implements IEnumKey {
|
|||
BOND("BOND"), // Долевые ценные бумаги (акции)
|
||||
EQTY("EQTY"), // Долговые ценные бумаги (облигации)
|
||||
RATE("RATE"), // Инструмент Денежного рынка
|
||||
CRNC ("CRNC")
|
||||
;
|
||||
|
||||
private final String key;
|
||||
|
|
|
|||
|
|
@ -3,9 +3,14 @@ package ru.spcex.platform.enumeration;
|
|||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
|
||||
public enum SdfTable implements IEnumKey {
|
||||
SDF_01("SDF_01"), SDF_04("SDF_04"), SDF_08("SDF_08"),
|
||||
SDF_13("SDF_13"), SDF_57("SDF_57"), SDF_09("SDF_09"),
|
||||
SDF_16("SDF_16");
|
||||
SDF_01("SDF_01"),
|
||||
SDF_04("SDF_04"),
|
||||
SDF_08("SDF_08"),
|
||||
SDF_09("SDF_09"),
|
||||
SDF_10("SDF_10"),
|
||||
SDF_13("SDF_13"),
|
||||
SDF_16("SDF_16"),
|
||||
SDF_57("SDF_57");
|
||||
|
||||
SdfTable(String key) {
|
||||
this.key = key;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration;
|
|||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
|
||||
public enum SessionType implements IEnumKey {
|
||||
IPOB("IPOB"), IPO0("IPO0"), IPOT("IPOT"),
|
||||
IPOB("IPOB"), IPO0("IPO0"), IPOT("IPOT"), TRDT("TRDT"),
|
||||
;
|
||||
|
||||
SessionType(String key) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ public enum Task implements IEnumKey {
|
|||
@Deprecated /* todo GBLD удаляется по CLS-267, CLS-275 */ getBalance("GBLD"),// Поступление средств
|
||||
startOfClearing("SCLR"),// Запуск клиринговой сессии
|
||||
startOfB0("IPO0"),// Запуск клиринговой сессии
|
||||
startOfT0("TRDT"),// Запуск клиринговой сессии
|
||||
startOfPreClearing("SPRC"),// Запуск преклиринга
|
||||
startPostClearing("SPOC"),// Запуск постклиринга
|
||||
createOrder("CORD"),
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ public class MoneyMarketSecurityNewRequest implements WithStartDt, WithEndDt, Wi
|
|||
@JsonProperty
|
||||
public String fullName;
|
||||
@JsonProperty
|
||||
public String convention;
|
||||
@JsonProperty
|
||||
public String shortNameEng;
|
||||
@JsonProperty
|
||||
public String fullNameEng;
|
||||
|
|
@ -99,6 +101,14 @@ public class MoneyMarketSecurityNewRequest implements WithStartDt, WithEndDt, Wi
|
|||
this.fullName = fullName;
|
||||
}
|
||||
|
||||
public String getConvention() {
|
||||
return convention;
|
||||
}
|
||||
|
||||
public void setConvention(String convention) {
|
||||
this.convention = convention;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return shortName;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ public class MoneyMarketSecurityUpdateRequest implements WithId, WithStartDt, Wi
|
|||
@JsonProperty
|
||||
public String fullName;
|
||||
@JsonProperty
|
||||
public String convention;
|
||||
@JsonProperty
|
||||
public String shortNameEng;
|
||||
@JsonProperty
|
||||
public String fullNameEng;
|
||||
|
|
@ -101,6 +103,14 @@ public class MoneyMarketSecurityUpdateRequest implements WithId, WithStartDt, Wi
|
|||
this.fullName = fullName;
|
||||
}
|
||||
|
||||
public String getConvention() {
|
||||
return convention;
|
||||
}
|
||||
|
||||
public void setConvention(String convention) {
|
||||
this.convention = convention;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return shortName;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,6 @@ kill -9 $(ps -ef | grep java | grep utility-service.jar | awk '{print $2}')
|
|||
kill -9 $(ps -ef | grep java | grep scheduler-service.jar | awk '{print $2}')
|
||||
kill -9 $(ps -ef | grep java | grep reports-service.jar | awk '{print $2}')
|
||||
kill -9 $(ps -ef | grep java | grep registry-service.jar | awk '{print $2}')
|
||||
kill -9 $(ps -ef | grep java | grep swt-importer.jar | awk '{print $2}')
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,3 +16,4 @@ cd /opt/mfd/clearing/bin
|
|||
/opt/mfd/clearing/bin/scheduler-service.sh
|
||||
/opt/mfd/clearing/bin/reports-service.sh
|
||||
/opt/mfd/clearing/bin/registry-service.sh
|
||||
/opt/mfd/clearing/bin/swt-importer.sh
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
CLEARING_HOME=/opt/mfd/clearing/
|
||||
cd $CLEARING_HOME/bin
|
||||
|
||||
CMD="java -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=7060 -jar securities-service.jar --spring.config.location=$CLEARING_HOME/settings/securities-service/"
|
||||
CMD="java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:7060 -jar securities-service.jar --spring.config.location=$CLEARING_HOME/settings/securities-service/"
|
||||
|
||||
$CMD >/dev/null 2>&1 &
|
||||
|
||||
|
|
|
|||
8
z-distr/src/main/resources/distr/bin/swt-importer.sh
Normal file
8
z-distr/src/main/resources/distr/bin/swt-importer.sh
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
CLEARING_HOME=/opt/mfd/clearing/
|
||||
cd $CLEARING_HOME/bin
|
||||
|
||||
CMD="java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:7111 -jar swt-importer.jar --spring.config.location=$CLEARING_HOME/settings/swt-importer/"
|
||||
|
||||
$CMD >/dev/null 2>&1 &
|
||||
Loading…
Add table
Reference in a new issue