backend-api account-service META accounts POST currency

This commit is contained in:
AKurakin 2024-04-26 20:09:18 +03:00
parent 6503baf710
commit f6ffca32b4
14 changed files with 108 additions and 107 deletions

View file

@ -48,6 +48,7 @@ public class AccountValidationConfig {
addImdg.accept(IMDGDistributedNames.Map_Account);
addImdg.accept(IMDGDistributedNames.Map_ServiceStatusDictionary);
addImdg.accept(IMDGDistributedNames.Map_AccountTypeDictionary);
addImdg.accept(IMDGDistributedNames.Map_CurrencyCodeDictionary);
return new ValidatorImpl<>(context,
IdPresentRule.instance("companyId",
CorrespondentAccountNewRequest::getCompanyId,
@ -106,6 +107,15 @@ public class AccountValidationConfig {
return DictionaryPresentRule.DICTIONARY_NOT_FOUND_DECORATOR_2.decorator(causeEmpty, errorCode, fieldName, fieldValue);
}
),
DictionaryPresentRule.instance("currency",
CorrespondentAccountNewRequest::getCurrency,
IMDGDistributedNames.Map_CurrencyCodeDictionary,
ServiceStatusDictionary.class,
null,
AccountError.DictionaryNotFound,
false
),
new SameAccountValidationRule<>(AccountType.Corr, CorrespondentAccountNewRequest::getAccount)
);
};

View file

@ -38,6 +38,7 @@ public class InformationAccountValidationConfig {
addImdg.accept(IMDGDistributedNames.Map_InformationAccount);
addImdg.accept(IMDGDistributedNames.Map_ServiceStatusDictionary);
addImdg.accept(IMDGDistributedNames.Map_AccountTypeDictionary);
addImdg.accept(IMDGDistributedNames.Map_CurrencyCodeDictionary);
addImdg.accept(IMDGDistributedNames.Map_Account);
return new ValidatorImpl<>(context,
IdPresentRule.instance("companyId",
@ -59,6 +60,10 @@ public class InformationAccountValidationConfig {
DictionaryPresentRule.instance("accountType", InformationAccountNewRequest::getAccountType,
IMDGDistributedNames.Map_AccountTypeDictionary, AccountTypeDictionary.class,
AccountError.RequiredFieldEmpty, AccountError.DictionaryNotFound, false),
DictionaryPresentRule.instance("currency", InformationAccountNewRequest::getCurrency,
IMDGDistributedNames.Map_CurrencyCodeDictionary, ServiceStatusDictionary.class,
null, AccountError.DictionaryNotFound,false
),
new SameAccountValidationRule<>(AccountType.Info, InformationAccountNewRequest::getAccount)
);
};

View file

@ -129,18 +129,20 @@ public class AccountService extends QueueConsumer implements InitializingBean {
if (requestInfoUpdate != null) return requestInfoUpdate;
CorrespondentAccountNewRequest req = userRequest.getRequestPayload();
String currency = req.getCurrency() == null ? CurrencyCode.RUB.getKey() : req.getCurrency();
Instant now = Instant.now();
Account account = new Account();
account.setCompanyId(req.getCompanyId());
account.setAccount(req.getAccount());
if (AccountType.Info.equalsByKey(req.getAccountType())) {
Long infoSequenceId = informationAccountService.accountNextId();
Long infoSequenceId = informationAccountService.accountNextId(currency);
String accountValue = informationAccountService.generateInfoAccount(infoSequenceId);
log.trace("New info-account SequenceId={} account={}", infoSequenceId, accountValue);
account.setAccount(accountValue);
}
account.setAccountType(req.getAccountType());
account.setCurrency(currency);
if (req.getStatus() == null) {
account.setStatus(WorkflowStatus.Active.getKey());
log.trace("Status not set in request. Use default: {}", account.getStatus());
@ -198,10 +200,11 @@ public class AccountService extends QueueConsumer implements InitializingBean {
infoAcc.setAccountId(account.getId());
Account firstAccountAntl = accountMap.getFirstObjectByFieldValues(Map.of(
"companyId", Sender.One.getId(),
"accountType", AccountType.Anlt.getKey()
"accountType", AccountType.Anlt.getKey(),
"currency", account.getCurrency()
));
if (firstAccountAntl == null) {
log.warn("Can not find 1 ANTL account for fill information ClearingAccountId.");
log.warn("Can not find 1 ANTL {} account for fill information ClearingAccountId.", account.getCurrency());
} else {
infoAcc.setClearingAccountId(firstAccountAntl.getId());
}

View file

@ -16,7 +16,6 @@ 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.account.InformationAccountNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.TradingClearingRegistryNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.reports.NotificationRequest;
import ru.spcex.clearing.platform.messaging.serialization.LogFormatter;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
@ -26,6 +25,7 @@ import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.validation.common.ValidationHelper;
import ru.spcex.platform.enumeration.AccountType;
import ru.spcex.platform.enumeration.CurrencyCode;
import ru.spcex.platform.enumeration.ServiceStatus;
import ru.spcex.platform.enumeration.WorkflowStatus;
import ru.spcex.platform.imdg.api.Imdg;
@ -40,6 +40,7 @@ import ru.spcex.platform.utils.validation.IValidator;
import java.time.Instant;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
@ -63,7 +64,7 @@ public class InformationAccountService extends QueueConsumer implements Initiali
* Кэш-счётчик сквозных номеров счетов.
* См. accountNextId()
*/
protected AtomicLong infoCounter;
protected Map<String, AtomicLong> infoCounterByCurrency = new HashMap<>();
@Autowired
public InformationAccountService(Consumer<String, Object> kafkaQueue,
@ -115,15 +116,17 @@ public class InformationAccountService extends QueueConsumer implements Initiali
if (requestInfoUpdate != null) return requestInfoUpdate;
InformationAccountNewRequest req = userRequest.getRequestPayload();
String currency = req.getCurrency() == null ? CurrencyCode.RUB.getKey() : req.getCurrency(); //userRequest.getRequestPayload().getCurrency();
Long newId = informationAccountImdg.nextIDSequenceFor();
Long infoSequenceId = accountNextId();
Long infoSequenceId = accountNextId(currency);
String accountValue = generateInfoAccount(infoSequenceId);
log.trace("New info-account id={}, sequenceId={}, account={}", newId, infoSequenceId, accountValue);
ImdgPredicateBuilder accountPredicateBuilder = accountImdg.predicateBuilder();
ImdgPredicate companyIdPredicate = accountPredicateBuilder.equals("companyId", 1L);
ImdgPredicate accountTypePredicate = accountPredicateBuilder.equals("accountType", AccountType.Anlt.getKey());
ImdgPredicate accountTypePredicate = accountPredicateBuilder.and(accountPredicateBuilder.equals("accountType", AccountType.Anlt.getKey()),
accountPredicateBuilder.equals("currency", currency));
ImdgPredicate andPredicate = accountPredicateBuilder.and(companyIdPredicate, accountTypePredicate);
Collection<Account> accountsAnlt = accountImdg.getCollectionObjectsByPredicate(andPredicate);
if (accountsAnlt.isEmpty()) {
@ -209,8 +212,11 @@ public class InformationAccountService extends QueueConsumer implements Initiali
}
String currency = userRequest.getRequestPayload().getCurrency();
if (currency == null)
currency = CurrencyCode.RUB.getKey();
Long newId = informationAccountImdg.nextIDSequenceFor();
Long infoSequenceId = accountNextId(); // требуется последовательность n+1
Long infoSequenceId = accountNextId(currency); // требуется последовательность n+1
String accountValue = generateInfoAccount(infoSequenceId);
log.trace("New info-account id={}, sequenceId={}, account={}", newId, infoSequenceId, accountValue);
@ -218,7 +224,8 @@ public class InformationAccountService extends QueueConsumer implements Initiali
{
ImdgPredicate andPredicate = pb.and(
pb.equals("companyId", 1L),
pb.equals("accountType", AccountType.Anlt.getKey())
pb.equals("accountType", AccountType.Anlt.getKey()),
pb.equals("currency", currency)
);
Collection<Account> accountsAnlt = accountImdg.getCollectionObjectsByPredicate(andPredicate);
if (accountsAnlt.isEmpty()) {
@ -302,13 +309,20 @@ public class InformationAccountService extends QueueConsumer implements Initiali
/**
* Сквозной номер инфо-счетов
*
* @param
* @return infoCounter++
*/
public synchronized Long accountNextId() {
public synchronized Long accountNextId(String currency) {
if (currency == null)
currency = CurrencyCode.RUB.getKey(); // default
AtomicLong infoCounter = infoCounterByCurrency.get(currency);
if (infoCounter == null) synchronized (this) {
if (infoCounter == null) {
log.debug("Init account-information counter.");
Collection<Account> allInfoAcc = accountImdg.getCollectionObjectsByFieldValues(Map.of("accountType", AccountType.Info.getKey()));
Collection<Account> allInfoAcc = accountImdg.getCollectionObjectsByFieldValues(Map.of(
"accountType", AccountType.Info.getKey(),
"currency", currency
));
if (allInfoAcc.isEmpty()) {
infoCounter = new AtomicLong(1);
log.debug("No account information on map. n={}", infoCounter.get());
@ -341,6 +355,7 @@ public class InformationAccountService extends QueueConsumer implements Initiali
if (parsedCount == 0 && lastAccount != null)
log.debug("Last unparseable account: {}", lastAccount);
}
infoCounterByCurrency.put(currency, infoCounter);
}
}
return infoCounter.incrementAndGet();

View file

@ -401,7 +401,7 @@ public class TradingClearingRegistryService extends QueueConsumer implements Ini
if (sId.length() > 5)
sId = sId.substring(sId.length() - 5);
code += sId;
return code; // 12 имволов
return code; // 12 символов
}
public RequestInfoUpdate tradingClearingRegistryUpdate(BaseRequest<TradingClearingRegistryUpdateRequest> userRequest) {

View file

@ -124,6 +124,7 @@ class InformationAccountServiceTest {
Account accountAnlt = new Account();
accountAnlt.setAccountType(AccountType.Anlt.getKey());
accountAnlt.setCompanyId(1L);
accountAnlt.setCurrency("RUB");
anltAccountId = accountImdg.insert(accountAnlt);
new TestObjectCreator(hazelcastServiceTest).createUserAdmin(1000L);
@ -134,6 +135,7 @@ class InformationAccountServiceTest {
InformationAccountNewRequest InformationAccountNewRequest = new InformationAccountNewRequest();
InformationAccountNewRequest.setCompanyId(companyId);
InformationAccountNewRequest.setAccount(account);
InformationAccountNewRequest.setCurrency(null);
String jsonString = getJsonStringForNew(InformationAccountNewRequest, 0L);
@ -178,11 +180,13 @@ class InformationAccountServiceTest {
Account account = new Account();
account.setId(120L);
account.setAccountType(AccountType.Info.getKey());
account.setCurrency(CurrencyCode.RUB.getKey());
account.setCompanyId(10L);
account.setAccount("39911810000000127000");
accountImdg.insert(account);
InformationAccount accountInfo = new InformationAccount();
accountInfo.setId(121L);
account.setCurrency(CurrencyCode.RUB.getKey());
accountInfo.setAccountId(account.getId());
accountInfo.setCompanyId(account.getCompanyId());
accountInfoImdg.insert(accountInfo);
@ -190,9 +194,17 @@ class InformationAccountServiceTest {
UserRoleVerification userRoleVerification = Mockito.mock(UserRoleVerification.class);
InformationAccountService infoAccSvc=new InformationAccountService(null,null,null,
null, userRoleVerification, hazelcastServiceTest, null, null, null, null);
Long n = infoAccSvc.accountNextId();
Long n = infoAccSvc.accountNextId(null);
Assertions.assertEquals(13L, n);
n = infoAccSvc.accountNextId();
n = infoAccSvc.accountNextId(null);
Assertions.assertEquals(14L, n);
// Другие валюты
n = infoAccSvc.accountNextId(CurrencyCode.RUB.getKey());
Assertions.assertEquals(15L, n);
n = infoAccSvc.accountNextId("CNY");
Assertions.assertEquals(2L, n);
n = infoAccSvc.accountNextId("CNY");
Assertions.assertEquals(3L, n);
}
}

View file

@ -17,6 +17,9 @@ public class AccountInformationNewAction implements IAction<InformationAccountNe
@ApiModelProperty(value = "Наименование статуса", example = "ACTV")
@JsonProperty
private String status;
@ApiModelProperty(value = "Код валюты", example = "RUB")
@JsonProperty
public String currency;
@ApiModelProperty(value = "Наименование типа счета", example = "INFO")
@JsonProperty
private String accountType;
@ -26,6 +29,7 @@ public class AccountInformationNewAction implements IAction<InformationAccountNe
var req = new InformationAccountNewRequest();
req.setCompanyId(this.companyId);
req.setAccount(this.account);
req.setCurrency(this.currency);
req.setStatus(this.status);
req.setAccountType(this.accountType);
return req;

View file

@ -29,6 +29,9 @@ public class AccountNewAction implements IAction<AccountNewRequest> {
@ApiModelProperty(value = "Наименование типа счета", example = "CLRN")
@JsonProperty
private String accountType;
@ApiModelProperty(value = "Код валюты", example = "RUB")
@JsonProperty
private String currency;
@Override
public AccountNewRequest toRequest() {
@ -37,6 +40,7 @@ public class AccountNewAction implements IAction<AccountNewRequest> {
req.setAccount(this.account);
req.setStatus(this.status);
req.setAccountType(this.accountType);
req.setCurrency(this.currency);
return req;
}
@ -77,4 +81,12 @@ public class AccountNewAction implements IAction<AccountNewRequest> {
public void setAccountType(String accountType) {
this.accountType = accountType;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
}

View file

@ -1,6 +1,6 @@
{
"version": "3.11.0.83",
"version": "3.11.0.84",
"enums": {
@ -4764,6 +4764,10 @@
{"code": "accountType",
"type": 12,"name": "Наименование типа счета","shortname": "Тип","link": "accountType","required": true,"visible": false
}
,
{"code": "currency",
"type": 12,"name": "Код валюты","shortname": "Валюта","visible": true,"link": "currencyCode","linkCode": "code"
}
]
}
,

View file

@ -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.11.0.83">
<meta version="3.11.0.84">
<!-- _xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _xsi:noNamespaceSchemaLocation="file:///E:/d/projects/meta/from/meta.xsd" -->
<!--Здесь словари-->
<enums>
@ -1105,6 +1105,7 @@
<account type="2" length="50" name="Номер счета" shortname="Счет"/>
<status type="12" name="Наименование статуса" shortname="Статус" link="serviceStatus"/>
<accountType type="12" name="Наименование типа счета" shortname="Тип" link="accountType" required="true" visible="false"/>
<currency type="12" name="Код валюты" shortname="Валюта" visible="true" link="currencyCode" linkCode="code"/>
</post>
<put name="Изменение счета" confirmation="companyId,account,status" class="ru.spcex.clearing.backendapi.controller.request.cud.account.AccountUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="account" linkCode="id" required="true"/>

View file

@ -2,45 +2,6 @@ package ru.spcex.clearing.platform.messaging.domain.cud.account;
import com.fasterxml.jackson.annotation.JsonProperty;
public class AccountNewRequest {
@JsonProperty
public Long companyId;
@JsonProperty
public String account;
@JsonProperty
public String status;
@JsonProperty
public String accountType;
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getAccountType() {
return accountType;
}
public void setAccountType(String accountType) {
this.accountType = accountType;
}
@Deprecated
public class AccountNewRequest extends CorrespondentAccountNewRequest {
}

View file

@ -2,55 +2,7 @@ package ru.spcex.clearing.platform.messaging.domain.cud.account;
import com.fasterxml.jackson.annotation.JsonProperty;
public class AccountUpdateRequest {
@JsonProperty
public Long id;
@JsonProperty
public Long companyId;
@JsonProperty
public String account;
@JsonProperty
public String status;
@JsonProperty
public String accountType;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getAccountType() {
return accountType;
}
public void setAccountType(String accountType) {
this.accountType = accountType;
}
@Deprecated
public class AccountUpdateRequest extends CorrespondentAccountUpdateRequest{
}

View file

@ -15,6 +15,9 @@ public class CorrespondentAccountNewRequest {
@JsonProperty
public String accountType;
@JsonProperty
public String currency;
public Long getCompanyId() {
return companyId;
}
@ -46,4 +49,12 @@ public class CorrespondentAccountNewRequest {
public void setAccountType(String accountType) {
this.accountType = accountType;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
}

View file

@ -12,6 +12,9 @@ public class InformationAccountNewRequest {
@JsonProperty
private String status;
@JsonProperty
private String currency;
@JsonProperty
private String accountType;
@ -39,6 +42,14 @@ public class InformationAccountNewRequest {
this.status = status;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public String getAccountType() {
return accountType;
}