From 4651e7063176ca8bd4a44e6c285b37172acf86b0 Mon Sep 17 00:00:00 2001 From: Boubaker Khanfir Date: Fri, 8 Sep 2023 08:19:26 +0100 Subject: [PATCH] fix: Fix Displaye of Rewarded Transaction information wehn duplicated in database - MEED-2455 - Meeds-io/meeds#1086 Prior to this change, when the reward information is duplicated in database for a same period and identity, the first reward entity is retrieved which may not contain the Transaction information. This change ensures to display the reward information having the sent transaction instead of the first created one. --- .../wallet/reward/dao/RewardDAO.java | 4 +- .../service/WalletRewardReportService.java | 18 +- .../storage/WalletRewardReportStorage.java | 34 +++- .../WalletRewardReportServiceTest.java | 165 ++++++++++++++++-- wallet-webapps/pom.xml | 6 - 5 files changed, 200 insertions(+), 27 deletions(-) diff --git a/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/dao/RewardDAO.java b/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/dao/RewardDAO.java index 8c99aa00f..15befdb7c 100644 --- a/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/dao/RewardDAO.java +++ b/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/dao/RewardDAO.java @@ -92,11 +92,11 @@ private double toNotNullDouble(Double result) { return result == null ? 0 : result; } - private WalletRewardEntity getFirstItem(List resultList) { + private static WalletRewardEntity getFirstItem(List resultList) { if (CollectionUtils.isEmpty(resultList)) { return null; } else { - return resultList.stream().filter(r -> StringUtils.isNotBlank(r.getTransactionHash())).sorted((r1, r2) -> { + return resultList.stream().filter(r -> StringUtils.isNotBlank(r.getTransactionHash())).sorted((r2, r1) -> { if (r1.getTokensSent() > r2.getTokensSent()) { return 1; } else if (r2.getTokensSent() > r1.getTokensSent()) { diff --git a/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/service/WalletRewardReportService.java b/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/service/WalletRewardReportService.java index 5a47ba2a6..1cbd3299c 100644 --- a/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/service/WalletRewardReportService.java +++ b/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/service/WalletRewardReportService.java @@ -368,11 +368,19 @@ private Set retrieveWalletRewards(RewardReport rewardReport, Set wallet != null && wr.getWallet() != null - && wr.getIdentityId() == wallet.getTechnicalId()) - .findFirst() - .orElse(null); + List walletRewardList = walletRewards.stream() + .filter(wr -> wallet != null && wr.getWallet() != null + && wr.getIdentityId() == wallet.getTechnicalId()) + .toList(); + WalletReward walletReward = walletRewardList.stream().filter(r -> r.getTransaction() != null).sorted((r2, r1) -> { + if (r1.getTokensSent() > r2.getTokensSent()) { + return 1; + } else if (r2.getTokensSent() > r1.getTokensSent()) { + return -1; + } else { + return 0; + } + }).findFirst().orElseGet(() -> walletRewardList.isEmpty() ? null : walletRewardList.get(0)); if (walletReward == null) { walletReward = new WalletReward(); walletRewards.add(walletReward); diff --git a/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/storage/WalletRewardReportStorage.java b/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/storage/WalletRewardReportStorage.java index 42af3a690..6ddb63572 100644 --- a/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/storage/WalletRewardReportStorage.java +++ b/wallet-reward-services/src/main/java/org/exoplatform/wallet/reward/storage/WalletRewardReportStorage.java @@ -20,6 +20,7 @@ import java.time.LocalDate; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; @@ -118,9 +119,36 @@ private RewardReport getRewardReport(WalletRewardPeriodEntity rewardPeriodEntity List rewardEntities = rewardDAO.findRewardsByPeriodId(rewardPeriodEntity.getId()); if (rewardEntities != null) { - Set rewards = rewardEntities.stream() - .map(rewardEntity -> toDTO(rewardEntity, zoneId)) - .collect(Collectors.toSet()); + List walletRewardEntities = new ArrayList<>(); + rewardEntities.forEach(reward -> { + List walletRewardList = rewardEntities.stream() + .filter(wr -> wr.getIdentityId() == reward.getIdentityId()) + .toList(); + if (walletRewardList.size() == 1) { + walletRewardEntities.add(reward); + } else { + WalletRewardEntity walletRewardEntity = walletRewardList.stream() + .filter(r -> r.getTransactionHash() != null) + .sorted((r2, r1) -> { + if (r1.getTokensSent() > r2.getTokensSent()) { + return 1; + } else if (r2.getTokensSent() > r1.getTokensSent()) { + return -1; + } else { + return 0; + } + }) + .findFirst() + .orElseGet(() -> walletRewardList.get(0)); + if (walletRewardEntity.getId().longValue() == reward.getId().longValue()) { + walletRewardEntities.add(reward); + } + } + }); + + Set rewards = walletRewardEntities.stream() + .map(rewardEntity -> toDTO(rewardEntity, zoneId)) + .collect(Collectors.toSet()); rewardReport.setRewards(rewards); } return rewardReport; diff --git a/wallet-reward-services/src/test/java/org/exoplatform/wallet/reward/service/WalletRewardReportServiceTest.java b/wallet-reward-services/src/test/java/org/exoplatform/wallet/reward/service/WalletRewardReportServiceTest.java index da5b81ff7..170970e44 100644 --- a/wallet-reward-services/src/test/java/org/exoplatform/wallet/reward/service/WalletRewardReportServiceTest.java +++ b/wallet-reward-services/src/test/java/org/exoplatform/wallet/reward/service/WalletRewardReportServiceTest.java @@ -39,11 +39,16 @@ import org.exoplatform.wallet.model.reward.RewardPluginSettings; import org.exoplatform.wallet.model.reward.RewardReport; import org.exoplatform.wallet.model.reward.RewardSettings; +import org.exoplatform.wallet.model.reward.RewardStatus; import org.exoplatform.wallet.model.reward.RewardTeam; import org.exoplatform.wallet.model.reward.WalletPluginReward; import org.exoplatform.wallet.model.reward.WalletReward; import org.exoplatform.wallet.model.transaction.TransactionDetail; import org.exoplatform.wallet.reward.BaseWalletRewardTest; +import org.exoplatform.wallet.reward.dao.RewardDAO; +import org.exoplatform.wallet.reward.dao.RewardPeriodDAO; +import org.exoplatform.wallet.reward.entity.WalletRewardEntity; +import org.exoplatform.wallet.reward.entity.WalletRewardPeriodEntity; import org.exoplatform.wallet.reward.storage.WalletRewardReportStorage; import org.exoplatform.wallet.service.WalletAccountService; import org.exoplatform.wallet.service.WalletTokenAdminService; @@ -268,6 +273,125 @@ public void testComputeRewards() { } } + @Test + public void testComputeRewardWithDuplication() { + WalletTransactionService walletTransactionService = getService(WalletTransactionService.class); + WalletRewardReportService walletRewardService = getService(WalletRewardReportService.class); + LocalDate date = YearMonth.of(2019, 03).atEndOfMonth(); + RewardReport rewardReport = walletRewardService.computeRewards(date); + assertNotNull(rewardReport); + assertNotNull(rewardReport.getRewards()); + assertEquals(0, rewardReport.getRewards().size()); + + WalletAccountService accountService = getService(WalletAccountService.class); + int enabledWalletsCount = 60; + for (int i = 0; i < enabledWalletsCount; i++) { + Wallet wallet = newWallet(i + 1l); + wallet = accountService.saveWallet(wallet, true); + updateWalletBlockchainState(wallet); + accountService.saveWalletBlockchainState(wallet, WalletUtils.getContractAddress()); + entitiesToClean.add(wallet); + } + + rewardReport = walletRewardService.computeRewards(date); + assertNotNull(rewardReport); + assertEquals(enabledWalletsCount, rewardReport.getRewards().size()); + + WalletRewardSettingsService rewardSettingsService = getService(WalletRewardSettingsService.class); + RewardSettings defaultSettings = rewardSettingsService.getSettings(); + rewardSettingsService.registerPlugin(CUSTOM_REWARD_PLUGIN); + try { + // Build new settings + RewardSettings newSettings = cloneSettings(rewardSettingsService.getSettings()); + + Set newPluginSettings = newSettings.getPluginSettings(); + long amount = 3l; + + newSettings.setPeriodType(RewardPeriodType.MONTH); + + RewardPluginSettings customPluginSetting = newPluginSettings.stream() + .filter(plugin -> CUSTOM_PLUGIN_ID.equals(plugin.getPluginId())) + .findFirst() + .orElse(null); + + assertNotNull(customPluginSetting); + + customPluginSetting.setAmount(amount); // NOSONAR + customPluginSetting.setBudgetType(RewardBudgetType.FIXED_PER_POINT); + customPluginSetting.setThreshold(0); + customPluginSetting.setEnabled(true); + customPluginSetting.setUsePools(false); + rewardSettingsService.saveSettings(newSettings); + + // Check computed amount for plugin per wallet when no teams and with + // fixed budget per point + double sumOfTokensToSend = checkComputedRewards(walletRewardService, + date, + enabledWalletsCount, + amount); + customPluginSetting.setBudgetType(RewardBudgetType.FIXED); + customPluginSetting.setAmount(sumOfTokensToSend); + rewardSettingsService.saveSettings(newSettings); + + rewardReport = walletRewardService.computeRewards(date); + + // check total budget to send + double tokensToSend = rewardReport.getRewards().stream().mapToDouble(WalletReward::getTokensToSend).sum(); + assertEquals(sumOfTokensToSend, tokensToSend, 0); + + Set rewards = rewardReport.getRewards(); + RewardPeriod period = rewardReport.getPeriod(); + RewardPeriodDAO rewardPeriodDAO = getService(RewardPeriodDAO.class); + WalletRewardPeriodEntity rewardPeriodEntity = rewardPeriodDAO.findRewardPeriodByTypeAndTime(period.getRewardPeriodType(), + period.getPeriodMedianDateInSeconds()); + if (rewardPeriodEntity == null) { + rewardPeriodEntity = new WalletRewardPeriodEntity(); + rewardPeriodEntity.setPeriodType(period.getRewardPeriodType()); + rewardPeriodEntity.setStatus(RewardStatus.PENDING); + rewardPeriodEntity.setStartTime(period.getStartDateInSeconds()); + rewardPeriodEntity.setEndTime(period.getEndDateInSeconds()); + rewardPeriodEntity.setTimeZone(period.getTimeZone()); + rewardPeriodEntity = rewardPeriodDAO.create(rewardPeriodEntity); + } + // Create entity with empty transaction information + for (WalletReward walletReward : rewards) { + WalletRewardEntity rewardEntity = new WalletRewardEntity(); + rewardEntity.setEnabled(true); + rewardEntity.setIdentityId(walletReward.getIdentityId()); + rewardEntity.setTokensToSend(walletReward.getTokensToSend()); + rewardEntity.setPeriod(rewardPeriodEntity); + rewardEntity = getService(RewardDAO.class).create(rewardEntity); + } + restartTransaction(); + + rewardReport = walletRewardService.computeRewards(date); + assertEquals(0, rewardReport.getTokensSent(), 0); + assertFalse(rewardReport.isCompletelyProceeded()); + + // Create duplicated entity with sent transaction information + // for the same identity and period + for (WalletReward walletReward : rewards) { + WalletRewardEntity rewardEntity = new WalletRewardEntity(); + rewardEntity.setEnabled(true); + rewardEntity.setIdentityId(walletReward.getIdentityId()); + rewardEntity.setTokensToSend(walletReward.getTokensToSend()); + rewardEntity.setPeriod(rewardPeriodEntity); + rewardEntity.setTokensSent(tokensToSend); + TransactionDetail transactionDetail = createWalltRewardTransaction(walletTransactionService, walletReward); + rewardEntity.setTransactionHash(transactionDetail.getHash()); + rewardEntity = getService(RewardDAO.class).create(rewardEntity); + } + restartTransaction(); + + rewardReport = walletRewardService.computeRewards(date); + assertEquals(rewardReport.getTokensToSend(), rewardReport.getTokensSent(), 0); + assertTrue(rewardReport.isCompletelyProceeded()); + } finally { + rewardSettingsService.unregisterPlugin(CUSTOM_PLUGIN_ID); + rewardSettingsService.saveSettings(defaultSettings); + } + } + @Test public void testComputeRewardsByUser() { @@ -660,19 +784,10 @@ private void resetTokenAdminService(WalletTransactionService walletTransactionSe @Override public TransactionDetail answer(InvocationOnMock invocation) throws Throwable { TransactionDetail transactionDetail = invocation.getArgument(0, TransactionDetail.class); - transactionDetail.setHash(generateTransactionHash()); - transactionDetail.setPending(pendingTransactions); - transactionDetail.setSucceeded(successTransactions); - transactionDetail.setContractMethodName("reward"); - RequestLifeCycle.begin(container); - try { - walletTransactionService.saveTransactionDetail(transactionDetail, false); - } finally { - RequestLifeCycle.end(); - } - entitiesToClean.add(transactionDetail); + saveRewardTransaction(walletTransactionService, pendingTransactions, successTransactions, transactionDetail); return transactionDetail; } + }); } @@ -724,4 +839,32 @@ private double checkComputedRewards(WalletRewardReportService walletRewardServic return sumOfTokensToSend; } + private TransactionDetail createWalltRewardTransaction(WalletTransactionService walletTransactionService, + WalletReward walletReward) { + TransactionDetail transactionDetail = new TransactionDetail(); + transactionDetail.setFrom("adminWalletAddress"); + transactionDetail.setTo(walletReward.getWallet().getAddress()); + transactionDetail.setContractAmount(walletReward.getTokensToSend()); + transactionDetail.setValue(walletReward.getTokensToSend()); + saveRewardTransaction(walletTransactionService, false, true, transactionDetail); + return transactionDetail; + } + + private void saveRewardTransaction(WalletTransactionService walletTransactionService, + boolean pendingTransactions, + boolean successTransactions, + TransactionDetail transactionDetail) { + transactionDetail.setHash(generateTransactionHash()); + transactionDetail.setPending(pendingTransactions); + transactionDetail.setSucceeded(successTransactions); + transactionDetail.setContractMethodName("reward"); + RequestLifeCycle.begin(container); + try { + walletTransactionService.saveTransactionDetail(transactionDetail, false); + } finally { + RequestLifeCycle.end(); + } + entitiesToClean.add(transactionDetail); + } + } diff --git a/wallet-webapps/pom.xml b/wallet-webapps/pom.xml index a53911b16..8f3d2e4e0 100644 --- a/wallet-webapps/pom.xml +++ b/wallet-webapps/pom.xml @@ -58,12 +58,6 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - - - org.apache.maven.plugins - maven-dependency-plugin - platform-ui-src generate-sources