Get balance

This commit is contained in:
k.struzhkin 2019-08-09 16:53:34 +03:00
parent bca5114ea2
commit 0b6b664db5
5 changed files with 88 additions and 15 deletions

View File

@ -1,5 +1,6 @@
package com.rbkmoney.shumpune.dao;
import com.rbkmoney.shumpune.domain.BalanceModel;
import com.rbkmoney.shumpune.domain.PostingModel;
import com.rbkmoney.shumpune.domain.PostingPlanModel;
import com.rbkmoney.shumpune.exception.DaoException;
@ -12,4 +13,6 @@ public interface PlanDao {
long insertPostings(List<PostingModel> postingModels);
BalanceModel getBalance(Long accountId, Long fromClock, Long toClock);
}

View File

@ -1,6 +1,8 @@
package com.rbkmoney.shumpune.dao;
import com.rbkmoney.shumpune.constant.PostingOperation;
import com.rbkmoney.shumpune.dao.mapper.PostingPlanInfoMapper;
import com.rbkmoney.shumpune.domain.BalanceModel;
import com.rbkmoney.shumpune.domain.PostingModel;
import com.rbkmoney.shumpune.domain.PostingPlanInfo;
import com.rbkmoney.shumpune.domain.PostingPlanModel;
@ -13,7 +15,9 @@ import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class PlanDaoImpl extends NamedParameterJdbcDaoSupport implements PlanDao {
@ -79,6 +83,47 @@ public class PlanDaoImpl extends NamedParameterJdbcDaoSupport implements PlanDao
return selectMaxClock(postingModel);
}
@Override
public BalanceModel getBalance(Long accountId, Long fromClock, Long toClock) {
MapSqlParameterSource params = new MapSqlParameterSource("fromClock", fromClock)
.addValue("toClock", toClock)
.addValue("acc_id", accountId);
String sqlGetFrom = "select sum(amount) as own_amount, operation " +
"from shm.posting_log " +
"where id > :fromClock and id <= :toClock " +
"and from_account_id = :acc_id " +
"GROUP BY operation";
String sqlSumTo = "select sum(amount) as own_amount, operation " +
"from shm.posting_log " +
"where id > :fromClock and id <= :toClock " +
"and to_account_id = :acc_id " +
"GROUP BY operation";
Map<String, Long> sumMapFrom = new HashMap<>();
getNamedParameterJdbcTemplate().query(sqlGetFrom, params, rs -> {
sumMapFrom.put(rs.getString("operation"), rs.getLong("own_amount"));
});
Map<String, Long> sumMapTo = new HashMap<>();
getNamedParameterJdbcTemplate().query(sqlSumTo, params, rs -> {
sumMapTo.put(rs.getString("operation"), rs.getLong("own_amount"));
});
return BalanceModel.builder()
.accountId(accountId)
.clock(toClock)
.ownAmount(safeGetSum(sumMapTo, PostingOperation.COMMIT) - safeGetSum(sumMapFrom, PostingOperation.COMMIT))
.minAvailableAmount(safeGetSum(sumMapTo, PostingOperation.HOLD) - safeGetSum(sumMapTo, PostingOperation.ROLLBACK)
- safeGetSum(sumMapFrom, PostingOperation.HOLD) - safeGetSum(sumMapFrom, PostingOperation.ROLLBACK))
.build();
}
private long safeGetSum(Map<String, Long> sumMapFrom, PostingOperation postingOperation) {
return sumMapFrom.containsKey(postingOperation.name()) ? sumMapFrom.get(postingOperation.name()) : 0L;
}
private long selectMaxClock(PostingModel postingModel) {
MapSqlParameterSource params = new MapSqlParameterSource("planId", postingModel.planId)
.addValue("batchId", postingModel.batchId);

View File

@ -27,7 +27,7 @@ public class ShumpuneServiceHandler implements AccounterSrv.Iface {
public Clock hold(PostingPlanChange postingPlanChange) throws InvalidPostingParams, InvalidRequest, TException {
log.info("Start hold postingPlanChange: {}", postingPlanChange);
try {
return postingPlanService.updatePostingPlan(postingPlanChange);
return postingPlanService.hold(postingPlanChange);
} catch (DaoException e) {
log.error("Failed to hold e: ", e);
throw new WUnavailableResultException(e);

View File

@ -1,6 +1,7 @@
package com.rbkmoney.shumpune.service;
import com.rbkmoney.damsel.shumpune.Clock;
import com.rbkmoney.damsel.shumpune.PostingPlan;
import com.rbkmoney.damsel.shumpune.PostingPlanChange;
import com.rbkmoney.shumpune.converter.PostingPlanToPostingPlanModelConverter;
import com.rbkmoney.shumpune.dao.PlanDaoImpl;
@ -23,13 +24,12 @@ public class PostingPlanService {
private final PostingBatchValidator postingBatchValidator;
@Transactional
public Clock updatePostingPlan(PostingPlanChange postingPlanChange) throws TException {
public Clock hold(PostingPlanChange postingPlanChange) throws TException {
postingPlanValidator.validate(postingPlanChange);
postingBatchValidator.validate(postingPlanChange.getBatch());
PostingPlanModel postingPlanModel = converter.convert(postingPlanChange);
long clock = planDao.insertPostings(postingPlanModel.getPostingModels());
postingPlanModel.getPostingPlanInfo().setClock(clock);
planDao.addOrUpdatePlanLog(postingPlanModel);

View File

@ -5,6 +5,9 @@ import com.rbkmoney.shumpune.DaoTestBase;
import com.rbkmoney.shumpune.ShumpuneApplication;
import com.rbkmoney.shumpune.constant.PostingOperation;
import com.rbkmoney.shumpune.dao.AccountDao;
import com.rbkmoney.shumpune.dao.PlanDao;
import com.rbkmoney.shumpune.domain.BalanceModel;
import com.rbkmoney.shumpune.utils.VectorClockSerializer;
import org.apache.thrift.TException;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
@ -36,9 +39,12 @@ public class ShumpuneServiceHandlerTest extends DaoTestBase {
@Autowired
ShumpuneServiceHandler handler;
@Autowired
PlanDao planDao;
@Test(expected = TException.class)
public void holdAccountNotFountError() throws TException {
PostingPlanChange postingPlanChange = createPostingPanChange(1111L, 22222L);
PostingPlanChange postingPlanChange = createPostingPanChange(1111L, 21L, 22222L);
handler.hold(postingPlanChange);
}
@ -48,12 +54,12 @@ public class ShumpuneServiceHandlerTest extends DaoTestBase {
//simple save
AccountPrototype accountPrototype = createAccountPrototype(now);
long accountIdFrom = handler.createAccount(accountPrototype);
long providerAcc = handler.createAccount(accountPrototype);
long merchantAcc = handler.createAccount(accountPrototype);
long systemAcc = handler.createAccount(accountPrototype);
long accountIdTo = handler.createAccount(accountPrototype);
PostingPlanChange postingPlanChange = createPostingPanChange(accountIdFrom, accountIdTo);
handler.hold(postingPlanChange);
PostingPlanChange postingPlanChange = createPostingPanChange(providerAcc, systemAcc, merchantAcc);
Clock clock = handler.hold(postingPlanChange);
jdbcTemplate.query("select * from shm.plan_log where plan_id = \'" + postingPlanChange.getId() + "\'",
(rs, rowNum) -> {
@ -62,19 +68,40 @@ public class ShumpuneServiceHandlerTest extends DaoTestBase {
Assert.assertTrue(rs.getLong("clock") > 0);
return null;
});
BalanceModel balance = planDao.getBalance(providerAcc, 0L, VectorClockSerializer.deserialize(clock.getVector()));
Assert.assertEquals(-294000L, balance.getMinAvailableAmount().longValue());
BalanceModel balanceMerch = planDao.getBalance(merchantAcc, 0L, VectorClockSerializer.deserialize(clock.getVector()));
Assert.assertEquals(291000L, balanceMerch.getMinAvailableAmount().longValue());
BalanceModel balanceSystem = planDao.getBalance(systemAcc, 0L, VectorClockSerializer.deserialize(clock.getVector()));
Assert.assertEquals(3000L, balanceSystem.getMinAvailableAmount().longValue());
}
@NotNull
private PostingPlanChange createPostingPanChange(Long fromAcc, Long toAcc) {
private PostingPlanChange createPostingPanChange(Long providerAcc, Long systemAcc, Long merchantAcc) {
PostingPlanChange postingPlanChange = new PostingPlanChange();
PostingBatch batch = new PostingBatch();
batch.setId(1L);
ArrayList<Posting> postings = new ArrayList<>();
postings.add(new Posting()
.setCurrencySymCode("RUB")
.setAmount(123)
.setFromId(fromAcc)
.setToId(toAcc)
.setAmount(300000)
.setFromId(providerAcc)
.setToId(merchantAcc)
.setDescription("qwe"));
postings.add(new Posting()
.setCurrencySymCode("RUB")
.setAmount(9000)
.setFromId(merchantAcc)
.setToId(systemAcc)
.setDescription("qwe"));
postings.add(new Posting()
.setCurrencySymCode("RUB")
.setAmount(6000)
.setFromId(systemAcc)
.setToId(providerAcc)
.setDescription("qwe"));
batch.setPostings(postings);
postingPlanChange.setBatch(batch)
@ -107,8 +134,6 @@ public class ShumpuneServiceHandlerTest extends DaoTestBase {
long account = handler.createAccount(createAccountPrototype(null));
Balance balanceByID = handler.getBalanceByID(account, Clock.latest(new LatestClock()));
assertZeroBalances(account, balanceByID);
}
private void assertZeroBalances(long account, Balance balanceByID) {