ialbert 2022-09-19 13:58:59 +03:00
parent 4a844dcc43
commit 443a71c80d
9 changed files with 377 additions and 47 deletions

View file

@ -1,19 +1,28 @@
package ru.spcex.clearing.backendapi.config;
import org.apache.kafka.clients.producer.MockProducer;
import org.apache.kafka.clients.producer.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import ru.spcex.clearing.backendapi.config.element.BackendApiSettings;
import ru.spcex.clearing.platform.messaging.config.KafkaProducerFactory;
@Configuration
public class KafkaConfig {
@Profile("!kafkaDisabled")
@Autowired
@Bean
public Producer<String, Object> createProducer(BackendApiSettings settings) {
return KafkaProducerFactory.producer(settings.getKafka());
}
@Profile("kafkaDisabled")
@Bean
public MockProducer<String, Object> createMockProducer() {
return new MockProducer<>(true, (topic, data) -> data != null ? data.getBytes() : new byte[0], (topic, data) -> data.toString().getBytes());
}
}

View file

@ -8,24 +8,33 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import ru.clearing.classes.statics.data.account.BankAccount;
import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController;
import ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction;
import ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountUpdateAction;
import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction;
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
import ru.spcex.clearing.backendapi.controller.response.cud.CudResponse;
import ru.spcex.clearing.backendapi.controller.response.entity.account.BankAccountBackendGetAll;
import ru.spcex.clearing.backendapi.controller.response.entity.account.BankAccountBackendGetById;
import ru.spcex.clearing.backendapi.service.IOperator;
import ru.spcex.clearing.backendapi.service.IStateLoader;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
@Controller
@RequestMapping("/securities/bank-accounts")
public class BankAccountController extends AbstractQueueController {
private final IStateLoader stateLoader;
@Autowired
public BankAccountController(IOperator operator) {
public BankAccountController(IOperator operator, IStateLoader stateLoader) {
super(operator);
this.stateLoader = stateLoader;
}
@ApiOperation(value = "create bank account.")
@ -61,4 +70,27 @@ public class BankAccountController extends AbstractQueueController {
deleteAction.setId(id);
return processRequest(Consts.DESTINATION_BANK_ACCOUNT_DELETE, deleteAction);
}
@ApiOperation(value = "get bank account.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = BankAccountBackendGetById.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@ResponseBody
public BankAccountBackendGetById getById(@ApiParam(value = "Идентификатор объекта", required = true, example = "1234")
@PathVariable("id") Long id) {
Optional<BankAccount> bankAccount = stateLoader.getById(id, IMDGDistributedNames.Map_BankAccount, BankAccount.class);
BankAccountBackendGetById response = new BankAccountBackendGetById();
bankAccount.ifPresentOrElse(response::fromEntity, () -> response.setCode(404));
return response;
}
@ApiOperation(value = "get all bank accounts.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = BankAccountBackendGetAll.class)})
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public BankAccountBackendGetAll getAll() {
Collection<BankAccount> all = stateLoader.getAll(IMDGDistributedNames.Map_BankAccount, BankAccount.class);
BankAccountBackendGetAll response = new BankAccountBackendGetAll();
response.fromEntity(all);
return response;
}
}

View file

@ -0,0 +1,65 @@
package ru.spcex.clearing.backendapi.controller.response.entity.account;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import ru.clearing.classes.statics.data.account.BankAccount;
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Банковские реквизиты для перечисления денежных средств
**/
@ApiModel(description = "Ответ при получении объектов BankAccount.")
public class BankAccountBackendGetAll extends BasicSpcexResponse {
@JsonProperty
@ApiModelProperty(value = "Полезная нагрузка")
private BankAccountBackendPayload payload = new BankAccountBackendPayload();
private static class BankAccountBackendPayload {
private List<BankAccountBackendGetFields> items = new ArrayList<>();
public List<BankAccountBackendGetFields> getItems() {
return items;
}
public void setItems(List<BankAccountBackendGetFields> items) {
this.items = items;
}
}
public BankAccountBackendPayload getPayload() {
return payload;
}
public void setPayload(BankAccountBackendPayload payload) {
this.payload = payload;
}
public void fromEntity(Collection<BankAccount> bankAccounts) {
var payload = this.getPayload();
for (BankAccount bankAccount : bankAccounts) {
var singleItem = new BankAccountBackendGetFields();
singleItem.setId(bankAccount.getId());
singleItem.setAccountId(bankAccount.getAccountId());
singleItem.setBankIdentificationCode(bankAccount.getBankIdentificationCode());
singleItem.setBankName(bankAccount.getBankName());
singleItem.setCorrespondentAccount(bankAccount.getCorrespondentAccount());
singleItem.setCorrespondentAccountName(bankAccount.getCorrespondentAccountName());
singleItem.setCurrency(bankAccount.getCurrency());
singleItem.setDestination(bankAccount.getDestination());
singleItem.setIban(bankAccount.getIban());
singleItem.setInternationalTransferSign(bankAccount.getInternationalTransferSign());
singleItem.setSwiftCode(bankAccount.getSwiftCode());
singleItem.setTaxpayerIdentificationNumber(bankAccount.getTaxpayerIdentificationNumber());
singleItem.setTaxRegistrationReasonCode(bankAccount.getTaxRegistrationReasonCode());
singleItem.setAccount(bankAccount.getAccount());
payload.getItems().add(singleItem);
}
}
}

View file

@ -0,0 +1,48 @@
package ru.spcex.clearing.backendapi.controller.response.entity.account;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import ru.clearing.classes.statics.data.account.BankAccount;
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
/**
* Банковские реквизиты для перечисления денежных средств
* @ApiModel(description = "Ответ в результате отправки операции в топик Kafka.")
* @ApiModelProperty(value = "Информация о принятом запросе")
**/
@ApiModel(description = "Ответ при получении объекта BankAccount.")
public class BankAccountBackendGetById extends BasicSpcexResponse {
@JsonProperty
@ApiModelProperty(value = "Поля объекта")
private BankAccountBackendGetFields payload;
public BankAccountBackendGetFields getPayload() {
return payload;
}
public void setPayload(BankAccountBackendGetFields payload) {
this.payload = payload;
}
public void fromEntity(BankAccount bankAccount) {
var payload = new BankAccountBackendGetFields();
this.setPayload(payload);
payload.setId(bankAccount.getId());
payload.setAccountId(bankAccount.getAccountId());
payload.setBankIdentificationCode(bankAccount.getBankIdentificationCode());
payload.setBankName(bankAccount.getBankName());
payload.setCorrespondentAccount(bankAccount.getCorrespondentAccount());
payload.setCorrespondentAccountName(bankAccount.getCorrespondentAccountName());
payload.setCurrency(bankAccount.getCurrency());
payload.setDestination(bankAccount.getDestination());
payload.setIban(bankAccount.getIban());
payload.setInternationalTransferSign(bankAccount.getInternationalTransferSign());
payload.setSwiftCode(bankAccount.getSwiftCode());
payload.setTaxpayerIdentificationNumber(bankAccount.getTaxpayerIdentificationNumber());
payload.setTaxRegistrationReasonCode(bankAccount.getTaxRegistrationReasonCode());
payload.setAccount(bankAccount.getAccount());
}
}

View file

@ -0,0 +1,161 @@
package ru.spcex.clearing.backendapi.controller.response.entity.account;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
public class BankAccountBackendGetFields {
@JsonProperty
@ApiModelProperty(value = "Идентификатор", example = "1234")
private Long id;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private Long accountId;
@JsonProperty
@ApiModelProperty(value = "", example = "ABCD")
private String bankIdentificationCode;
@JsonProperty
@ApiModelProperty(value = "Имя банка", example = "Сбербанк")
private String bankName;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String correspondentAccount;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String correspondentAccountName;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String currency;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String destination;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String iban;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String internationalTransferSign;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String swiftCode;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String taxpayerIdentificationNumber;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String taxRegistrationReasonCode;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String account;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long value) {
this.accountId = value;
}
public String getBankIdentificationCode() {
return bankIdentificationCode;
}
public void setBankIdentificationCode(String value) {
this.bankIdentificationCode = value;
}
public String getBankName() {
return bankName;
}
public void setBankName(String value) {
this.bankName = value;
}
public String getCorrespondentAccount() {
return correspondentAccount;
}
public void setCorrespondentAccount(String value) {
this.correspondentAccount = value;
}
public String getCorrespondentAccountName() {
return correspondentAccountName;
}
public void setCorrespondentAccountName(String value) {
this.correspondentAccountName = value;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String value) {
this.currency = value;
}
public String getDestination() {
return destination;
}
public void setDestination(String value) {
this.destination = value;
}
public String getIban() {
return iban;
}
public void setIban(String value) {
this.iban = value;
}
public String getInternationalTransferSign() {
return internationalTransferSign;
}
public void setInternationalTransferSign(String value) {
this.internationalTransferSign = value;
}
public String getSwiftCode() {
return swiftCode;
}
public void setSwiftCode(String value) {
this.swiftCode = value;
}
public String getTaxpayerIdentificationNumber() {
return taxpayerIdentificationNumber;
}
public void setTaxpayerIdentificationNumber(String value) {
this.taxpayerIdentificationNumber = value;
}
public String getTaxRegistrationReasonCode() {
return taxRegistrationReasonCode;
}
public void setTaxRegistrationReasonCode(String value) {
this.taxRegistrationReasonCode = value;
}
public String getAccount() {
return account;
}
public void setAccount(String value) {
this.account = value;
}
}

View file

@ -0,0 +1,14 @@
package ru.spcex.clearing.backendapi.service;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import java.util.Collection;
import java.util.Optional;
/**
* сделал чтобы не привязывать все контроллеры к Imdg API
*/
public interface IStateLoader {
<T extends SpcexObjectBase> Optional<T> getById(Long id, String mapName, Class<T> clazz);
<T extends SpcexObjectBase> Collection<T> getAll(String mapName, Class<T> clazz);
}

View file

@ -1,46 +0,0 @@
package ru.spcex.clearing.backendapi.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.user.User;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.log.ExceptionUtils;
import java.time.Instant;
import java.util.Map;
@Service
public class UserAutoCreateService {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<User> userMap;
@Autowired
public UserAutoCreateService(ImdgProvider imdgProvider) {
this.userMap = imdgProvider.getImdg(IMDGDistributedNames.Map_User, User.class);
}
/**
* при необходимости переделать на отдельный поток
*/
public void createUserIfNeeded(String userName) {
userMap.lockAndPerform(() -> {
try {
User username = userMap.getSingleObjectByFieldValues(Map.of("identifier", userName));
if (username == null) {
username = new User();
username.setId(userMap.nextIDSequenceFor());
username.setIdentifier(userName);
username.setCreated(Instant.now());
userMap.insert(username);
}
} catch (Throwable e) {
log.error(ExceptionUtils.getStackTrace(e));
}
});
}
}

View file

@ -0,0 +1,42 @@
package ru.spcex.clearing.backendapi.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.spcex.clearing.backendapi.service.IStateLoader;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class StateLoaderImpl implements IStateLoader {
private final Map<String, Imdg<?>> allImdgMaps;
private final ImdgProvider imdgProvider;
@Autowired
public StateLoaderImpl(ImdgProvider imdgProvider) {
this.allImdgMaps = new ConcurrentHashMap<>();
this.imdgProvider = imdgProvider;
}
@Override
public <T extends SpcexObjectBase> Optional<T> getById(Long id, String mapName, Class<T> clazz) {
Imdg<T> imdg = getImdg(mapName, clazz);
return Optional.ofNullable(imdg.getSingleObjectByID(id));
}
@Override
public <T extends SpcexObjectBase> Collection<T> getAll(String mapName, Class<T> clazz) {
Imdg<T> imdg = getImdg(mapName, clazz);
return imdg.getAllValues();
}
@SuppressWarnings("unchecked")
private <T extends SpcexObjectBase> Imdg<T> getImdg(String mapName, Class<T> clazz) {
return (Imdg<T>) allImdgMaps.computeIfAbsent(mapName, (mapName1) -> imdgProvider.getImdg(mapName, clazz));
}
}

View file

@ -23,6 +23,11 @@ public class ImdgHazelcast<T extends SpcexObjectBase> implements Imdg<T> {
private HazelcastInstance hzInstance;
@Override
public Collection<T> getAllValues() {
return map.values();
}
@Override
public void insert(T paramT) {
if (paramT.getId() == null) {