diff --git a/src/main/java/it/gov/pagopa/idpay/transactions/dto/batch/BatchCountersDTO.java b/src/main/java/it/gov/pagopa/idpay/transactions/dto/batch/BatchCountersDTO.java index e590f861..815637a5 100644 --- a/src/main/java/it/gov/pagopa/idpay/transactions/dto/batch/BatchCountersDTO.java +++ b/src/main/java/it/gov/pagopa/idpay/transactions/dto/batch/BatchCountersDTO.java @@ -1,8 +1,10 @@ package it.gov.pagopa.idpay.transactions.dto.batch; import lombok.Getter; +import lombok.ToString; @Getter +@ToString public class BatchCountersDTO { private Long initialAmountCents; private Long numberOfTransactions; @@ -12,14 +14,15 @@ public class BatchCountersDTO { private Long trxElaborated; private Long trxRejected; + private BatchCountersDTO() { - this.initialAmountCents = 0L; - this.numberOfTransactions = 0L; - this.approvedAmountCents = 0L; - this.suspendedAmountCents = 0L; - this.trxElaborated = 0L; - this.trxSuspended = 0L; - this.trxRejected = 0L; + this.initialAmountCents = 0L; + this.numberOfTransactions = 0L; + this.approvedAmountCents = 0L; + this.suspendedAmountCents = 0L; + this.trxElaborated = 0L; + this.trxSuspended = 0L; + this.trxRejected = 0L; } public static BatchCountersDTO newBatch() { @@ -31,12 +34,16 @@ public BatchCountersDTO incrementInitialAmountCents(Long amountCents) { return this; } - public BatchCountersDTO incrementNumberOfTransactions(Long number) { this.numberOfTransactions = this.numberOfTransactions + number; return this; } + public BatchCountersDTO decrementNumberOfTransactions() { + this.numberOfTransactions = this.numberOfTransactions - 1; + return this; + } + public BatchCountersDTO incrementApprovedAmountCents(Long amountCents) { this.approvedAmountCents = this.approvedAmountCents + amountCents; return this; @@ -57,6 +64,11 @@ public BatchCountersDTO decrementSuspendedAmountCents(Long amountCents) { return this; } + public BatchCountersDTO decrementTrxElaborated() { + this.trxElaborated = this.trxElaborated - 1L; + return this; + } + public BatchCountersDTO incrementTrxElaborated() { this.trxElaborated = this.trxElaborated + 1L; return this; @@ -67,6 +79,11 @@ public BatchCountersDTO incrementTrxElaborated(Long number) { return this; } + public BatchCountersDTO decrementTrxElaborated(Long number) { + this.trxElaborated = this.trxElaborated - number; + return this; + } + public BatchCountersDTO incrementTrxSuspended() { this.trxSuspended = this.trxSuspended + 1L; return this; diff --git a/src/main/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepository.java b/src/main/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepository.java index f03fe4a0..a6ea1c5a 100644 --- a/src/main/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepository.java +++ b/src/main/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepository.java @@ -12,7 +12,6 @@ public interface RewardBatchSpecificRepository { Mono incrementTotalAmountCents(String batchId, long accruedAmountCents); Mono decrementTotalAmountCents(String batchId, long accruedAmountCents); - Mono moveSuspendToNewBatch(String oldBatchId, String newBatchId, long accruedAmountCents); Mono moveTrxToNewBatch(String oldBatchId, String newBatchId, long accruedAmountCents, boolean isSuspended); Flux findRewardBatchesCombined(String merchantId, String status, String assigneeLevel, String month, boolean isOperator, Pageable pageable); Mono getCountCombined(String merchantId, String status, String assigneeLevel, String month, boolean isOperator); diff --git a/src/main/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepositoryImpl.java b/src/main/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepositoryImpl.java index 81261284..350a64ad 100644 --- a/src/main/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepositoryImpl.java +++ b/src/main/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepositoryImpl.java @@ -53,6 +53,7 @@ public Mono getCountCombined(String merchantId, String status, String assi return mongoTemplate.count(Query.query(criteria), RewardBatch.class); } + @Deprecated @Override public Mono incrementTotalAmountCents(String batchId, long accruedAmountCents) { return mongoTemplate.findAndModify( @@ -66,6 +67,7 @@ public Mono incrementTotalAmountCents(String batchId, long accruedA ); } + @Deprecated @Override public Mono decrementTotalAmountCents(String batchId, long accruedAmountCents) { return mongoTemplate.findAndModify( @@ -117,42 +119,6 @@ public Mono moveTrxToNewBatch(String oldBatchId, String newBatchId, .switchIfEmpty(Mono.error(new ClientExceptionNoBody(HttpStatus.BAD_REQUEST, REWARD_BATCH_NOT_FOUND))); } - @Override - public Mono moveSuspendToNewBatch(String oldBatchId, String newBatchId, long accruedAmountCents) { - - Update decOld = new Update() - //.inc(INITIAL_AMOUNT_CENTS, -accruedAmountCents) - .inc(NUMBER_OF_TRANSACTIONS, -1) - .inc(SUSPENDED_AMOUNT_CENTS, -accruedAmountCents) - .inc(NUMBER_OF_TRANSACTIONS_SUSPENDED, -1) - .inc(NUMBER_OF_TRANSACTIONS_ELABORATED, -1) - .set(RewardBatch.Fields.updateDate, LocalDateTime.now()); - - Update incNew = new Update() - .inc(INITIAL_AMOUNT_CENTS, accruedAmountCents) - .inc(NUMBER_OF_TRANSACTIONS, 1) - .inc(SUSPENDED_AMOUNT_CENTS, accruedAmountCents) - .inc(NUMBER_OF_TRANSACTIONS_SUSPENDED, 1) - .inc(NUMBER_OF_TRANSACTIONS_ELABORATED, 1) - .set(RewardBatch.Fields.updateDate, LocalDateTime.now()); - - return mongoTemplate.findAndModify( - Query.query(Criteria.where("_id").is(oldBatchId)), - decOld, - FindAndModifyOptions.options().returnNew(true), - RewardBatch.class - ) - .switchIfEmpty(Mono.error(new ClientExceptionNoBody(HttpStatus.BAD_REQUEST, REWARD_BATCH_NOT_FOUND))) - .then(mongoTemplate.findAndModify( - Query.query(Criteria.where("_id").is(newBatchId)), - incNew, - FindAndModifyOptions.options().returnNew(true), - RewardBatch.class - )) - .switchIfEmpty(Mono.error(new ClientExceptionNoBody(HttpStatus.BAD_REQUEST, REWARD_BATCH_NOT_FOUND))); - } - - private Criteria buildCombinedCriteria(String merchantId, String status, String assigneeLevel, String month, boolean isOperator) { List subCriteria = new ArrayList<>(); @@ -256,6 +222,12 @@ public Mono updateTotals(String rewardBatchId, BatchCountersDTO acc if (acc.getSuspendedAmountCents() != 0) { update.inc(RewardBatch.Fields.suspendedAmountCents, acc.getSuspendedAmountCents()); } + if (acc.getInitialAmountCents() != 0) { + update.inc(RewardBatch.Fields.initialAmountCents, acc.getInitialAmountCents()); + } + if (acc.getNumberOfTransactions() != 0) { + update.inc(RewardBatch.Fields.numberOfTransactions, acc.getNumberOfTransactions()); + } update.currentDate(RewardBatch.Fields.updateDate); diff --git a/src/main/java/it/gov/pagopa/idpay/transactions/service/PointOfSaleTransactionServiceImpl.java b/src/main/java/it/gov/pagopa/idpay/transactions/service/PointOfSaleTransactionServiceImpl.java index c5303882..554e864c 100644 --- a/src/main/java/it/gov/pagopa/idpay/transactions/service/PointOfSaleTransactionServiceImpl.java +++ b/src/main/java/it/gov/pagopa/idpay/transactions/service/PointOfSaleTransactionServiceImpl.java @@ -4,6 +4,7 @@ import it.gov.pagopa.idpay.transactions.connector.rest.UserRestClient; import it.gov.pagopa.idpay.transactions.connector.rest.dto.FiscalCodeInfoPDV; import it.gov.pagopa.idpay.transactions.dto.*; +import it.gov.pagopa.idpay.transactions.dto.batch.BatchCountersDTO; import it.gov.pagopa.idpay.transactions.dto.mapper.RewardTransactionKafkaMapper; import it.gov.pagopa.idpay.transactions.enums.PosType; import it.gov.pagopa.idpay.transactions.enums.RewardBatchTrxStatus; @@ -34,9 +35,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.time.YearMonth; -import java.time.format.DateTimeFormatter; import java.util.List; -import java.util.Locale; import java.util.Objects; import static it.gov.pagopa.idpay.transactions.enums.RewardBatchStatus.*; @@ -57,8 +56,6 @@ public class PointOfSaleTransactionServiceImpl implements PointOfSaleTransaction private final TransactionErrorNotifierService transactionErrorNotifierService; private final TransactionNotifierService transactionNotifierService; - private static final DateTimeFormatter BATCH_MONTH_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM", Locale.ITALIAN); - protected PointOfSaleTransactionServiceImpl( UserRestClient userRestClient, RewardTransactionRepository rewardTransactionRepository, InvoiceStorageClient invoiceStorageClient, RewardBatchService rewardBatchService, RewardBatchRepository rewardBatchRepository, @@ -167,11 +164,14 @@ private Mono> getTransactions(TrxFiltersDTO filters, public Mono updateInvoiceTransaction(String transactionId, String merchantId, String pointOfSaleId, FilePart file, String docNumber) { + log.info("[UPDATE_INVOICE_FILE_SERVICE] - [updateInvoiceTransaction] - start | trxId={} merchantId={} posId={} docNumber={} filename={}", + Utilities.sanitizeString(transactionId), Utilities.sanitizeString(merchantId), Utilities.sanitizeString(pointOfSaleId), Utilities.sanitizeString(docNumber), file != null ? Utilities.sanitizeString(file.filename()) : null); + Utilities.checkFileExtensionOrThrow(file); return rewardTransactionRepository .findTransactionForUpdateInvoice(merchantId, pointOfSaleId, transactionId) - .switchIfEmpty(Mono.error(new ClientExceptionNoBody(HttpStatus.BAD_REQUEST, TRANSACTION_MISSING_INVOICE))) + .switchIfEmpty(Mono.defer(() -> Mono.error(new ClientExceptionNoBody(HttpStatus.BAD_REQUEST, TRANSACTION_MISSING_INVOICE)))) .flatMap(trx -> validateBatchAndUpdateInvoiceFlow(trx, merchantId, pointOfSaleId, transactionId, file, docNumber)); } @@ -185,14 +185,13 @@ private Mono validateBatchAndUpdateInvoiceFlow(RewardTransaction trx, String oldBatchId = requireRewardBatchId(trx); return rewardBatchRepository.findRewardBatchById(oldBatchId) - .switchIfEmpty(Mono.error(new ClientExceptionNoBody(HttpStatus.BAD_REQUEST, REWARD_BATCH_NOT_FOUND))) + .switchIfEmpty(Mono.defer(() -> Mono.error(new ClientExceptionNoBody(HttpStatus.BAD_REQUEST, REWARD_BATCH_NOT_FOUND)))) .flatMap(oldBatch -> { validateOldBatchStatusAllowed(oldBatch); validateTrxBatchStatusNotApproved(trx); return updateInvoiceFileAndFields(trx, merchantId, pointOfSaleId, transactionId, file, docNumber) - .flatMap(savedTrx -> suspendIfNeeded(savedTrx, oldBatch, oldBatchId, merchantId, pointOfSaleId, transactionId)) - .flatMap(suspendedTrx -> moveToCurrentMonthBatchAndUpdateCounters(suspendedTrx, oldBatch, oldBatchId, merchantId)) + .flatMap(savedTrx -> suspendAndMoveTransaction(savedTrx, oldBatch)) .then(); }); } @@ -202,10 +201,10 @@ private String requireRewardBatchId(RewardTransaction trx) { if (oldBatchId == null) { throw new ClientExceptionNoBody(HttpStatus.BAD_REQUEST, REWARD_BATCH_NOT_FOUND); } + return oldBatchId; } - /** (1) batch deve essere EVALUATING o CREATED */ private void validateOldBatchStatusAllowed(RewardBatch oldBatch) { if (!EVALUATING.equals(oldBatch.getStatus()) && !CREATED.equals(oldBatch.getStatus())) { throw new ClientExceptionWithBody( @@ -214,12 +213,10 @@ private void validateOldBatchStatusAllowed(RewardBatch oldBatch) { ERROR_MESSAGE_REWARD_BATCH_STATUS_NOT_ALLOWED ); } - } +} - /** (2) trx batch status deve essere != APPROVED */ private void validateTrxBatchStatusNotApproved(RewardTransaction trx) { - RewardBatchTrxStatus batchTrxStatus = trx.getRewardBatchTrxStatus(); - if (batchTrxStatus == RewardBatchTrxStatus.APPROVED) { + if (trx.getRewardBatchTrxStatus() == RewardBatchTrxStatus.APPROVED) { throw new ClientExceptionWithBody( HttpStatus.BAD_REQUEST, TRANSACTION_STATUS_NOT_ALLOWED, @@ -228,7 +225,6 @@ private void validateTrxBatchStatusNotApproved(RewardTransaction trx) { } } - /** (3) replace file + update campi fattura + save trx */ private Mono updateInvoiceFileAndFields(RewardTransaction trx, String merchantId, String pointOfSaleId, @@ -250,115 +246,83 @@ private Mono updateInvoiceFileAndFields(RewardTransaction trx })); } - /** (4) DOPO update fattura -> sospende (se non già sospesa). Se batch CREATED non sospendere. */ - private Mono suspendIfNeeded(RewardTransaction savedTrx, - RewardBatch oldBatch, - String oldBatchId, - String merchantId, - String pointOfSaleId, - String transactionId) { + private Mono findOrCreateTargetBatch(RewardTransaction oldTransaction, + RewardBatch oldBatch) { - // Se CREATED non sospendere - if (CREATED.equals(oldBatch.getStatus())) { - return Mono.just(savedTrx); - } + PosType posType = oldTransaction.getPointOfSaleType(); + String businessName = oldTransaction.getBusinessName(); - // Se già suspended non fare nulla - if (savedTrx.getRewardBatchTrxStatus() == RewardBatchTrxStatus.SUSPENDED) { - return Mono.just(savedTrx); - } - - TransactionsRequest req = TransactionsRequest.builder() - .transactionIds(List.of(savedTrx.getId())) - .reason(savedTrx.getRejectionReasons() != null ? savedTrx.getRejectionReasons().toString() : null) - .build(); - - return rewardBatchService - .suspendTransactions(oldBatchId, savedTrx.getInitiativeId(), req) - .then(rewardTransactionRepository.findTransactionForUpdateInvoice(merchantId, pointOfSaleId, transactionId)) - .switchIfEmpty(Mono.error(new ClientExceptionNoBody(HttpStatus.BAD_REQUEST, TRANSACTION_MISSING_INVOICE))); - } - - /** (5) sposta trx al batch del mese corrente + contatori suspended */ - private Mono moveToCurrentMonthBatchAndUpdateCounters(RewardTransaction suspendedTrx, - RewardBatch oldBatch, - String oldBatchId, - String merchantId) { - - PosType posType = suspendedTrx.getPointOfSaleType(); - String businessName = suspendedTrx.getBusinessName(); - - YearMonth now = YearMonth.now(); + YearMonth currentMonth = YearMonth.now(); YearMonth oldMonth = YearMonth.parse(oldBatch.getMonth()); - YearMonth targetMonth = oldMonth.isAfter(now) ? oldMonth : now; - - String initiativeId = suspendedTrx.getInitiatives().getFirst(); - long accruedRewardCents = suspendedTrx.getRewards().get(initiativeId).getAccruedRewardCents(); + YearMonth targetMonth = oldMonth.isAfter(currentMonth) ? oldMonth : currentMonth; - return rewardBatchService.findOrCreateBatch(merchantId, posType, targetMonth.toString(), businessName) - .flatMap(newBatch -> { - if (newBatch.getId().equals(oldBatchId)) { - // batch già del mese odierno - return rewardTransactionRepository.save(suspendedTrx).then(); - } + log.info("[UPDATE_INVOICE_FILE_SERVICE] - [findOrCreateTargetBatch] - start | oldBatchId={} trxId={} targetMonth={}", + Utilities.sanitizeString(oldBatch.getId()), Utilities.sanitizeString(oldTransaction.getId()), targetMonth); - Mono moveCounters = computeMoveCounters(oldBatch, oldBatchId, newBatch.getId(), accruedRewardCents); - - return moveCounters - .then(Mono.fromRunnable(() -> applyBatchMoveToTransaction( - suspendedTrx, - oldBatch, - newBatch - ))) - .then(rewardTransactionRepository.save(suspendedTrx)) - .then(); - }); + return rewardBatchService.findOrCreateBatch(oldBatch.getMerchantId(), posType, targetMonth.toString(), businessName); } - private Mono computeMoveCounters(RewardBatch oldBatch, - String oldBatchId, - String newBatchId, - long accruedRewardCents) { + private Mono suspendAndMoveTransaction( + RewardTransaction oldTransaction, RewardBatch oldBatch) { if (CREATED.equals(oldBatch.getStatus())) { - return rewardBatchService.decrementTotalAmountCents(oldBatchId, accruedRewardCents) - .then(rewardBatchService.incrementTotalAmountCents(newBatchId, accruedRewardCents)) - .then(); + log.info("[UPDATE_INVOICE_FILE_SERVICE] - [suspendAndMoveTransaction] - end success | no-move (old batch CREATED)"); + return Mono.just(oldTransaction); } - return rewardBatchService.moveSuspendToNewBatch(oldBatchId, newBatchId, accruedRewardCents) - .then(); - } - - private void applyBatchMoveToTransaction(RewardTransaction suspendedTrx, - RewardBatch oldBatch, - RewardBatch newBatch) { - - suspendedTrx.setRewardBatchId(newBatch.getId()); - suspendedTrx.setUpdateDate(LocalDateTime.now()); - - if (!CREATED.equals(oldBatch.getStatus())) { - updateLastMonthElaboratedOnBatchMove( - suspendedTrx, - oldBatch.getMonth(), - newBatch.getMonth() - ); + long accruedRewardCents = + oldTransaction + .getRewards() + .get(oldTransaction.getInitiatives().getFirst()) + .getAccruedRewardCents(); + + boolean wasSuspended = oldTransaction.getRewardBatchTrxStatus() == RewardBatchTrxStatus.SUSPENDED; + boolean wasRejected = oldTransaction.getRewardBatchTrxStatus() == RewardBatchTrxStatus.REJECTED; + + BatchCountersDTO oldBatchCounter; + BatchCountersDTO newBatchCounter; + + if (wasSuspended) { + oldBatchCounter = BatchCountersDTO.newBatch() + .decrementNumberOfTransactions() + .decrementTrxElaborated(); + + newBatchCounter = BatchCountersDTO.newBatch() + .incrementInitialAmountCents(accruedRewardCents) + .incrementNumberOfTransactions(1L) + .incrementTrxSuspended(1L) + .incrementSuspendedAmountCents(accruedRewardCents) + .incrementTrxElaborated(1L); + } else { + oldBatchCounter = BatchCountersDTO.newBatch() + .decrementNumberOfTransactions() + .decrementTrxElaborated(wasRejected ? 1L : 0L); + + newBatchCounter = BatchCountersDTO.newBatch() + .incrementInitialAmountCents(accruedRewardCents) + .incrementNumberOfTransactions(1L) + .incrementTrxSuspended(1L) + .incrementSuspendedAmountCents(accruedRewardCents) + .incrementTrxElaborated(1L); } - } - - - private YearMonth getYearMonth (String yearMonthString){ - return YearMonth.parse(yearMonthString.toLowerCase(), BATCH_MONTH_FORMAT); - } - private void updateLastMonthElaboratedOnBatchMove(RewardTransaction trx, String oldBatchMonth, String newBatchMonth) { - if (trx.getRewardBatchLastMonthElaborated() == null - || getYearMonth(trx.getRewardBatchLastMonthElaborated()).isBefore(getYearMonth(newBatchMonth))) { - trx.setRewardBatchLastMonthElaborated(oldBatchMonth); - } + return findOrCreateTargetBatch(oldTransaction, oldBatch) + .flatMap(newBatch -> { + log.info("[UPDATE_INVOICE_FILE_SERVICE] - [suspendAndMoveTransaction] - moving trx | trxId={} fromBatchId={} toBatchId={} oldCounters={} newCounters={}", + Utilities.sanitizeString(oldTransaction.getId()), Utilities.sanitizeString(oldBatch.getId()), Utilities.sanitizeString(newBatch.getId()), + oldBatchCounter, newBatchCounter); + + oldTransaction.setRewardBatchTrxStatus(RewardBatchTrxStatus.SUSPENDED); + oldTransaction.setRewardBatchId(newBatch.getId()); + oldTransaction.setUpdateDate(LocalDateTime.now()); + + return rewardTransactionRepository.save(oldTransaction) + .then(rewardBatchRepository.updateTotals(oldBatch.getId(), oldBatchCounter)) + .then(rewardBatchRepository.updateTotals(newBatch.getId(), newBatchCounter)) + .thenReturn(oldTransaction); + }); } - public Mono reversalTransaction( String transactionId, String merchantId, diff --git a/src/main/java/it/gov/pagopa/idpay/transactions/service/RewardBatchService.java b/src/main/java/it/gov/pagopa/idpay/transactions/service/RewardBatchService.java index 674b734a..a46fc505 100644 --- a/src/main/java/it/gov/pagopa/idpay/transactions/service/RewardBatchService.java +++ b/src/main/java/it/gov/pagopa/idpay/transactions/service/RewardBatchService.java @@ -17,7 +17,6 @@ public interface RewardBatchService { Mono> getRewardBatches(String merchantId, String organizationRole, String status, String assigneeLevel, String month, Pageable pageable); Mono incrementTotalAmountCents(String batchId, long accruedAmountCents); Mono decrementTotalAmountCents(String batchId, long accruedAmountCents); - Mono moveSuspendToNewBatch(String oldBatchId, String newBatchId, long accruedAmountCents); Mono rewardBatchConfirmation(String initiativeId, String rewardBatchId); Mono rewardBatchConfirmationBatch(String initiativeId, List rewardBatchIds); diff --git a/src/main/java/it/gov/pagopa/idpay/transactions/service/RewardBatchServiceImpl.java b/src/main/java/it/gov/pagopa/idpay/transactions/service/RewardBatchServiceImpl.java index a013dd05..26fca6f3 100644 --- a/src/main/java/it/gov/pagopa/idpay/transactions/service/RewardBatchServiceImpl.java +++ b/src/main/java/it/gov/pagopa/idpay/transactions/service/RewardBatchServiceImpl.java @@ -124,6 +124,8 @@ public Mono findOrCreateBatch(String merchantId, PosType posType, S month) .switchIfEmpty(Mono.defer(() -> createBatch(merchantId, posType, month, businessName) + .doOnSuccess(batch -> log.info("[REWARD_BATCH_REPOSITORY]- findOrCreateBatch - created new batch with id: {}, month: {}", + batch.getId(), batch.getMonth())) .onErrorResume(DuplicateKeyException.class, ex -> rewardBatchRepository.findByMerchantIdAndPosTypeAndMonth(merchantId, posType, month)))); @@ -175,21 +177,18 @@ private Mono createBatch(String merchantId, PosType posType, String return rewardBatchRepository.save(batch); } + @Deprecated @Override public Mono incrementTotalAmountCents(String batchId, long accruedAmountCents) { return rewardBatchRepository.incrementTotalAmountCents(batchId, accruedAmountCents); } + @Deprecated @Override public Mono decrementTotalAmountCents(String batchId, long accruedAmountCents) { return rewardBatchRepository.decrementTotalAmountCents(batchId, accruedAmountCents); } - @Override - public Mono moveSuspendToNewBatch(String oldBatchId, String newBatchId, long accruedAmountCents) { - return rewardBatchRepository.moveSuspendToNewBatch(oldBatchId, newBatchId, accruedAmountCents); - } - @Override public Mono sendRewardBatch(String merchantId, String batchId) { return rewardBatchRepository.findById(batchId) diff --git a/src/test/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepositoryImplTest.java b/src/test/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepositoryImplTest.java index 313f3be8..24815a98 100644 --- a/src/test/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepositoryImplTest.java +++ b/src/test/java/it/gov/pagopa/idpay/transactions/repository/RewardBatchSpecificRepositoryImplTest.java @@ -894,119 +894,6 @@ void findPreviousEmptyBatches_shouldReturnOnlyEmptyBatchesBeforeCurrentMonth_sor assertEquals("old-empty-2", result.get(1).getId()); } - @Test - void moveSuspendToNewBatch_ok_shouldMoveCountersAndAmounts() { - long accrued = 150L; - - RewardBatch oldBatch = rewardBatchRepository.findById("batch1").block(); - RewardBatch newBatch = rewardBatchRepository.findById("batch2").block(); - assertNotNull(oldBatch); - assertNotNull(newBatch); - - oldBatch.setInitialAmountCents(accrued); - oldBatch.setSuspendedAmountCents(accrued); - oldBatch.setNumberOfTransactions(ONE_LONG); - oldBatch.setNumberOfTransactionsSuspended(ONE_LONG); - oldBatch.setNumberOfTransactionsElaborated(ONE_LONG); - - newBatch.setInitialAmountCents(ZERO_LONG); - newBatch.setSuspendedAmountCents(ZERO_LONG); - newBatch.setNumberOfTransactions(ZERO_LONG); - newBatch.setNumberOfTransactionsSuspended(ZERO_LONG); - newBatch.setNumberOfTransactionsElaborated(ZERO_LONG); - - rewardBatchRepository.saveAll(List.of(oldBatch, newBatch)).collectList().block(); - - LocalDateTime oldUpdateBefore = oldBatch.getUpdateDate(); - LocalDateTime newUpdateBefore = newBatch.getUpdateDate(); - - Mono result = rewardBatchSpecificRepository - .moveSuspendToNewBatch("batch1", "batch2", accrued); - - StepVerifier.create(result) - .assertNext(updatedNew -> { - assertEquals("batch2", updatedNew.getId()); - - assertEquals(accrued, updatedNew.getInitialAmountCents()); - assertEquals(accrued, updatedNew.getSuspendedAmountCents()); - assertEquals(ONE_LONG, updatedNew.getNumberOfTransactions()); - assertEquals(ONE_LONG, updatedNew.getNumberOfTransactionsSuspended()); - assertEquals(ONE_LONG, updatedNew.getNumberOfTransactionsElaborated()); - - assertNotNull(updatedNew.getUpdateDate()); - if (newUpdateBefore != null) { - assertNotEquals(newUpdateBefore, updatedNew.getUpdateDate()); - } - }) - .verifyComplete(); - - RewardBatch oldAfter = rewardBatchRepository.findById("batch1").block(); - RewardBatch newAfter = rewardBatchRepository.findById("batch2").block(); - assertNotNull(oldAfter); - assertNotNull(newAfter); - - assertEquals(150L, oldAfter.getInitialAmountCents()); - assertEquals(0, oldAfter.getSuspendedAmountCents()); - assertEquals(ZERO_LONG, oldAfter.getNumberOfTransactions()); - assertEquals(ZERO_LONG, oldAfter.getNumberOfTransactionsSuspended()); - assertEquals(ZERO_LONG, oldAfter.getNumberOfTransactionsElaborated()); - - assertNotNull(oldAfter.getUpdateDate()); - if (oldUpdateBefore != null) { - assertNotEquals(oldUpdateBefore, oldAfter.getUpdateDate()); - } - } - - @Test - void moveSuspendToNewBatch_oldBatchNotFound_returnsBadRequest() { - Mono result = rewardBatchSpecificRepository - .moveSuspendToNewBatch("NOT_EXISTING", "batch2", 150L); - - StepVerifier.create(result) - .expectErrorSatisfies(ex -> { - assertInstanceOf(ClientExceptionNoBody.class, ex); - assertEquals(org.springframework.http.HttpStatus.BAD_REQUEST, - ((ClientExceptionNoBody) ex).getHttpStatus()); - }) - .verify(); - } - - - @Test - void moveSuspendToNewBatch_newBatchNotFound_returnsBadRequest_andOldWasDecremented() { - long accrued = 150L; - - RewardBatch oldBatch = rewardBatchRepository.findById("batch1").block(); - assertNotNull(oldBatch); - - oldBatch.setInitialAmountCents(ONE_LONG); - oldBatch.setSuspendedAmountCents(accrued); - oldBatch.setNumberOfTransactions(ONE_LONG); - oldBatch.setNumberOfTransactionsSuspended(ONE_LONG); - oldBatch.setNumberOfTransactionsElaborated(ONE_LONG); - rewardBatchRepository.save(oldBatch).block(); - - Mono result = rewardBatchSpecificRepository - .moveSuspendToNewBatch("batch1", "NOT_EXISTING", accrued); - - StepVerifier.create(result) - .expectErrorSatisfies(ex -> { - assertInstanceOf(ClientExceptionNoBody.class, ex); - assertEquals(org.springframework.http.HttpStatus.BAD_REQUEST, - ((ClientExceptionNoBody) ex).getHttpStatus()); - }) - .verify(); - - RewardBatch oldAfter = rewardBatchRepository.findById("batch1").block(); - assertNotNull(oldAfter); - - assertEquals(ONE_LONG, oldAfter.getInitialAmountCents()); - assertEquals(ZERO_LONG, oldAfter.getSuspendedAmountCents()); - assertEquals(ZERO_LONG, oldAfter.getNumberOfTransactions()); - assertEquals(ZERO_LONG, oldAfter.getNumberOfTransactionsSuspended()); - assertEquals(ZERO_LONG, oldAfter.getNumberOfTransactionsElaborated()); - } - @Test void moveTrxToNewBatch_notSuspended_updatesBothBatchesCorrectly() { diff --git a/src/test/java/it/gov/pagopa/idpay/transactions/service/PointOfSaleTransactionServiceImplTest.java b/src/test/java/it/gov/pagopa/idpay/transactions/service/PointOfSaleTransactionServiceImplTest.java index ef715990..94b3d41c 100644 --- a/src/test/java/it/gov/pagopa/idpay/transactions/service/PointOfSaleTransactionServiceImplTest.java +++ b/src/test/java/it/gov/pagopa/idpay/transactions/service/PointOfSaleTransactionServiceImplTest.java @@ -14,8 +14,8 @@ import it.gov.pagopa.idpay.transactions.dto.FranchisePointOfSaleDTO; import it.gov.pagopa.idpay.transactions.dto.InvoiceData; import it.gov.pagopa.idpay.transactions.dto.RewardTransactionKafkaDTO; -import it.gov.pagopa.idpay.transactions.dto.TransactionsRequest; import it.gov.pagopa.idpay.transactions.dto.TrxFiltersDTO; +import it.gov.pagopa.idpay.transactions.dto.batch.BatchCountersDTO; import it.gov.pagopa.idpay.transactions.enums.PosType; import it.gov.pagopa.idpay.transactions.enums.RewardBatchStatus; import it.gov.pagopa.idpay.transactions.enums.RewardBatchTrxStatus; @@ -92,57 +92,6 @@ void cleanup() throws Exception { Files.deleteIfExists(srcFile); } - @Test - void updateInvoiceTransaction_evaluatingBatch_withRejectionReasons() { - FilePart fp = filePartBackedBySrc("invoice.pdf", true); - - RewardTransaction trx = baseInvoicedTrx(); - trx.setId(TRX_ID); - trx.setMerchantId(MERCHANT_ID); - trx.setPointOfSaleId(POS_ID); - trx.setStatus(SyncTrxStatus.INVOICED.name()); - trx.setRewardBatchId("OLD"); - trx.setInvoiceData(InvoiceData.builder().filename("old.pdf").build()); - trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.CONSULTABLE); - trx.setInitiativeId(INITIATIVE_ID); - trx.setRejectionReasons(List.of("REASON1", "REASON2")); - - RewardBatch oldBatch = new RewardBatch(); - oldBatch.setId("OLD"); - oldBatch.setStatus(RewardBatchStatus.EVALUATING); - oldBatch.setMonth("2024-01"); - - RewardBatch newBatch = new RewardBatch(); - newBatch.setId("NEW"); - newBatch.setStatus(RewardBatchStatus.CREATED); - newBatch.setMonth(YearMonth.now().toString()); - - @SuppressWarnings("unchecked") - Response uploadResponse = (Response) mock(Response.class); - when(invoiceStorageClient.upload(any(InputStream.class), anyString(), anyString())).thenReturn(uploadResponse); - - when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) - .thenReturn(Mono.just(trx)) - .thenReturn(Mono.just(cloneTrx(trx))); - - when(rewardBatchRepository.findRewardBatchById("OLD")).thenReturn(Mono.just(oldBatch)); - when(rewardTransactionRepository.save(any())).thenAnswer(inv -> Mono.just(inv.getArgument(0))); - - ArgumentCaptor reqCaptor = ArgumentCaptor.forClass(TransactionsRequest.class); - when(rewardBatchService.suspendTransactions(eq("OLD"), eq(INITIATIVE_ID), reqCaptor.capture())) - .thenReturn(Mono.just(oldBatch)); - - when(rewardBatchService.findOrCreateBatch(anyString(), any(), anyString(), anyString())) - .thenReturn(Mono.just(newBatch)); - when(rewardBatchService.moveSuspendToNewBatch(anyString(), anyString(), anyLong())) - .thenReturn(Mono.just(oldBatch)); - - StepVerifier.create(service.updateInvoiceTransaction(TRX_ID, MERCHANT_ID, POS_ID, fp, DOC_NUMBER)) - .verifyComplete(); - - TransactionsRequest capturedReq = reqCaptor.getValue(); - assertNotNull(capturedReq.getReason()); - } @Test void getPointOfSaleTransactions_withFiscalCode_resolvesUserAndReturnsPage() { RewardTransaction trx = RewardTransactionFaker.mockInstance(1); @@ -749,7 +698,7 @@ void updateInvoiceTransaction_rewardBatchNotFound_throws() { } @Test - void updateInvoiceTransaction_rewardBatchStatusNotAllowed_throws() { + void updateInvoiceTransaction_rewardBatchStatusNotAllowed_throws1() { FilePart fp = mockFilePart("invoice.pdf", true); RewardTransaction trx = new RewardTransaction(); @@ -773,7 +722,7 @@ void updateInvoiceTransaction_rewardBatchStatusNotAllowed_throws() { } @Test - void updateInvoiceTransaction_trxApprovedNotAllowed_throws() { + void updateInvoiceTransaction_trxApprovedNotAllowed_throws1() { FilePart fp = mockFilePart("invoice.pdf", true); RewardTransaction trx = new RewardTransaction(); @@ -796,138 +745,6 @@ void updateInvoiceTransaction_trxApprovedNotAllowed_throws() { .verify(); } - @Test - void updateInvoiceTransaction_createdBatch_updatesInvoiceButDoesNotSuspendOrMoveBatch() { - FilePart fp = filePartBackedBySrc("invoice.pdf", true); - - RewardTransaction trx = baseInvoicedTrx(); - trx.setId(TRX_ID); - trx.setMerchantId(MERCHANT_ID); - trx.setPointOfSaleId(POS_ID); - trx.setStatus(SyncTrxStatus.INVOICED.name()); - trx.setRewardBatchId("B1"); - trx.setInvoiceData(InvoiceData.builder().filename("old.pdf").build()); - trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.CONSULTABLE); - - RewardBatch batch = new RewardBatch(); - batch.setId("B1"); - batch.setStatus(RewardBatchStatus.CREATED); - batch.setMonth("2026-01"); - - @SuppressWarnings("unchecked") - Response uploadResponse = (Response) mock(Response.class); - when(invoiceStorageClient.upload(any(InputStream.class), anyString(), anyString())) - .thenReturn(uploadResponse); - - when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) - .thenReturn(Mono.just(trx)); - when(rewardBatchRepository.findRewardBatchById("B1")) - .thenReturn(Mono.just(batch)); - when(rewardTransactionRepository.save(any())) - .thenAnswer(inv -> Mono.just(inv.getArgument(0))); - - when(rewardBatchService.findOrCreateBatch( - eq(MERCHANT_ID), - any(PosType.class), - anyString(), - anyString() - )).thenReturn(Mono.just(batch)); - - StepVerifier.create(service.updateInvoiceTransaction(TRX_ID, MERCHANT_ID, POS_ID, fp, DOC_NUMBER)) - .verifyComplete(); - - verify(rewardBatchService, never()) - .suspendTransactions(anyString(), anyString(), any(TransactionsRequest.class)); - - verify(rewardBatchService, times(1)).findOrCreateBatch( - eq(MERCHANT_ID), - any(PosType.class), - anyString(), - anyString() - ); - - verify(rewardBatchService, never()).moveSuspendToNewBatch(anyString(), anyString(), anyLong()); - verify(rewardBatchService, never()).decrementTotalAmountCents(anyString(), anyLong()); - verify(rewardBatchService, never()).incrementTotalAmountCents(anyString(), anyLong()); - - verify(invoiceStorageClient).deleteFile( - "invoices/merchant/MERCHANTID1/pos/POINTOFSALEID1/transaction/TRX_ID/invoice/old.pdf" - ); - verify(invoiceStorageClient).upload( - any(InputStream.class), - eq("invoices/merchant/MERCHANTID1/pos/POINTOFSALEID1/transaction/TRX_ID/invoice/invoice.pdf"), - eq(APPLICATION_PDF_VALUE) - ); - - verify(rewardTransactionRepository, atLeastOnce()).save(any()); - } - - - @Test - void updateInvoiceTransaction_evaluatingBatch_suspendsAndMovesToCurrentMonthBatch() { - FilePart fp = filePartBackedBySrc("invoice.pdf", true); - - RewardTransaction trx = baseInvoicedTrx(); - trx.setId(TRX_ID); - trx.setMerchantId(MERCHANT_ID); - trx.setPointOfSaleId(POS_ID); - trx.setUserId(USER_ID); - trx.setStatus(SyncTrxStatus.INVOICED.name()); - trx.setRewardBatchId("OLD"); - trx.setInvoiceData(InvoiceData.builder().filename("old.pdf").build()); - trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.CONSULTABLE); - trx.setInitiatives(List.of(INITIATIVE_ID)); - trx.setBusinessName("Biz"); - trx.setPointOfSaleType(PosType.PHYSICAL); - trx.setRewards(Map.of(INITIATIVE_ID, Reward.builder().accruedRewardCents(123L).build())); - trx.setInitiativeId(INITIATIVE_ID); - - RewardBatch oldBatch = new RewardBatch(); - oldBatch.setId("OLD"); - oldBatch.setStatus(RewardBatchStatus.EVALUATING); - oldBatch.setMonth("2024-01"); - - RewardBatch newBatch = new RewardBatch(); - newBatch.setId("NEW"); - newBatch.setStatus(RewardBatchStatus.CREATED); - newBatch.setMonth(YearMonth.now().toString()); - - @SuppressWarnings("unchecked") - Response uploadResponse = (Response) mock(Response.class); - when(invoiceStorageClient.upload(any(InputStream.class), anyString(), anyString())) - .thenReturn(uploadResponse); - - when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) - .thenReturn(Mono.just(trx)); - - when(rewardBatchRepository.findRewardBatchById("OLD")).thenReturn(Mono.just(oldBatch)); - - when(rewardTransactionRepository.save(any())).thenAnswer(inv -> Mono.just(inv.getArgument(0))); - - when(rewardBatchService.suspendTransactions(eq("OLD"), eq(INITIATIVE_ID), any(TransactionsRequest.class))) - .thenReturn(Mono.just(oldBatch)); - - RewardTransaction suspended = cloneTrx(trx); - suspended.setRewardBatchTrxStatus(RewardBatchTrxStatus.SUSPENDED); - suspended.setRewardBatchLastMonthElaborated("2024-01"); - when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) - .thenReturn(Mono.just(trx)) - .thenReturn(Mono.just(suspended)); - - when(rewardBatchService.findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), eq(YearMonth.now().toString()), eq("Biz"))) - .thenReturn(Mono.just(newBatch)); - - when(rewardBatchService.moveSuspendToNewBatch("OLD", "NEW", 123L)).thenReturn(Mono.just(oldBatch)); - - StepVerifier.create(service.updateInvoiceTransaction(TRX_ID, MERCHANT_ID, POS_ID, fp, DOC_NUMBER)) - .verifyComplete(); - - verify(rewardBatchService).suspendTransactions(eq("OLD"), eq(INITIATIVE_ID), any(TransactionsRequest.class)); - verify(rewardBatchService).findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), eq(YearMonth.now().toString()), eq("Biz")); - verify(rewardBatchService).moveSuspendToNewBatch("OLD", "NEW", 123L); - verify(rewardTransactionRepository, atLeastOnce()).save(any()); - } - private RewardTransaction baseInvoicedTrx() { Reward r = new Reward(); r.setAccruedRewardCents(123L); @@ -991,7 +808,7 @@ private FilePart filePartBackedBySrc(String filename, boolean withPdfContentType } @Test - void updateInvoiceTransaction_evaluatingBatch_alreadySuspended_doesNotSuspendButMovesBatch() { + void updateInvoiceTransaction_createdBatch_updatesInvoice_only_noCountersMoves() { FilePart fp = filePartBackedBySrc("invoice.pdf", true); RewardTransaction trx = baseInvoicedTrx(); @@ -999,24 +816,15 @@ void updateInvoiceTransaction_evaluatingBatch_alreadySuspended_doesNotSuspendBut trx.setMerchantId(MERCHANT_ID); trx.setPointOfSaleId(POS_ID); trx.setStatus(SyncTrxStatus.INVOICED.name()); - trx.setRewardBatchId("OLD"); + trx.setRewardBatchId("B1"); trx.setInvoiceData(InvoiceData.builder().filename("old.pdf").build()); - trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.SUSPENDED); - trx.setInitiatives(List.of(INITIATIVE_ID)); - trx.setBusinessName("Biz"); - trx.setPointOfSaleType(PosType.PHYSICAL); - trx.setRewards(Map.of(INITIATIVE_ID, Reward.builder().accruedRewardCents(123L).build())); - trx.setInitiativeId(INITIATIVE_ID); - - RewardBatch oldBatch = new RewardBatch(); - oldBatch.setId("OLD"); - oldBatch.setStatus(RewardBatchStatus.EVALUATING); - oldBatch.setMonth("2024-01"); + trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.CONSULTABLE); - RewardBatch newBatch = new RewardBatch(); - newBatch.setId("NEW"); - newBatch.setStatus(RewardBatchStatus.CREATED); - newBatch.setMonth(YearMonth.now().toString()); + RewardBatch batch = new RewardBatch(); + batch.setId("B1"); + batch.setMerchantId(MERCHANT_ID); + batch.setStatus(RewardBatchStatus.CREATED); + batch.setMonth("2024-01"); @SuppressWarnings("unchecked") Response uploadResponse = (Response) mock(Response.class); @@ -1025,25 +833,32 @@ void updateInvoiceTransaction_evaluatingBatch_alreadySuspended_doesNotSuspendBut when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) .thenReturn(Mono.just(trx)); - - when(rewardBatchRepository.findRewardBatchById("OLD")).thenReturn(Mono.just(oldBatch)); - when(rewardTransactionRepository.save(any())).thenAnswer(inv -> Mono.just(inv.getArgument(0))); - - when(rewardBatchService.findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), eq(YearMonth.now().toString()), eq("Biz"))) - .thenReturn(Mono.just(newBatch)); - - when(rewardBatchService.moveSuspendToNewBatch("OLD", "NEW", 123L)).thenReturn(Mono.just(oldBatch)); + when(rewardBatchRepository.findRewardBatchById("B1")) + .thenReturn(Mono.just(batch)); + when(rewardTransactionRepository.save(any())) + .thenAnswer(inv -> Mono.just(inv.getArgument(0))); StepVerifier.create(service.updateInvoiceTransaction(TRX_ID, MERCHANT_ID, POS_ID, fp, DOC_NUMBER)) .verifyComplete(); - verify(rewardBatchService, never()).suspendTransactions(anyString(), anyString(), any(TransactionsRequest.class)); - verify(rewardBatchService).findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), eq(YearMonth.now().toString()), eq("Biz")); - verify(rewardBatchService).moveSuspendToNewBatch("OLD", "NEW", 123L); + // invoice replace + save trx fatta, ma nessun update contatori/move + verify(rewardBatchRepository, never()).updateTotals(anyString(), any()); + verify(rewardBatchService, never()).findOrCreateBatch(anyString(), any(), anyString(), anyString()); + + verify(invoiceStorageClient).deleteFile( + "invoices/merchant/MERCHANTID1/pos/POINTOFSALEID1/transaction/TRX_ID/invoice/old.pdf" + ); + verify(invoiceStorageClient).upload( + any(InputStream.class), + eq("invoices/merchant/MERCHANTID1/pos/POINTOFSALEID1/transaction/TRX_ID/invoice/invoice.pdf"), + eq(APPLICATION_PDF_VALUE) + ); + + verify(rewardTransactionRepository, times(1)).save(any()); // solo update invoice } @Test - void updateInvoiceTransaction_evaluatingBatch_suspendOkButRefetchEmpty_throws() { + void updateInvoiceTransaction_evaluatingBatch_notSuspended_savesTwice_andUpdatesTotalsOldAndNew() { FilePart fp = filePartBackedBySrc("invoice.pdf", true); RewardTransaction trx = baseInvoicedTrx(); @@ -1058,95 +873,59 @@ void updateInvoiceTransaction_evaluatingBatch_suspendOkButRefetchEmpty_throws() trx.setBusinessName("Biz"); trx.setPointOfSaleType(PosType.PHYSICAL); trx.setRewards(Map.of(INITIATIVE_ID, Reward.builder().accruedRewardCents(123L).build())); - trx.setInitiativeId(INITIATIVE_ID); RewardBatch oldBatch = new RewardBatch(); oldBatch.setId("OLD"); + oldBatch.setMerchantId(MERCHANT_ID); oldBatch.setStatus(RewardBatchStatus.EVALUATING); oldBatch.setMonth("2024-01"); + RewardBatch newBatch = new RewardBatch(); + newBatch.setId("NEW"); + newBatch.setMerchantId(MERCHANT_ID); + newBatch.setStatus(RewardBatchStatus.CREATED); + newBatch.setMonth(YearMonth.now().toString()); + @SuppressWarnings("unchecked") Response uploadResponse = (Response) mock(Response.class); when(invoiceStorageClient.upload(any(InputStream.class), anyString(), anyString())) .thenReturn(uploadResponse); - when(rewardTransactionRepository.save(any())).thenAnswer(inv -> Mono.just(inv.getArgument(0))); - when(rewardBatchRepository.findRewardBatchById("OLD")).thenReturn(Mono.just(oldBatch)); - when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) - .thenReturn(Mono.just(trx)) - .thenReturn(Mono.empty()); - - when(rewardBatchService.suspendTransactions(eq("OLD"), eq(INITIATIVE_ID), any(TransactionsRequest.class))) + .thenReturn(Mono.just(trx)); + when(rewardBatchRepository.findRewardBatchById("OLD")) .thenReturn(Mono.just(oldBatch)); - StepVerifier.create(service.updateInvoiceTransaction(TRX_ID, MERCHANT_ID, POS_ID, fp, DOC_NUMBER)) - .expectError(ClientExceptionNoBody.class) - .verify(); - - verify(rewardBatchService).suspendTransactions(eq("OLD"), eq(INITIATIVE_ID), any(TransactionsRequest.class)); - } - - @Test - void updateInvoiceTransaction_evaluatingBatch_newBatchSameAsOld_doesNotMoveCounters() { - FilePart fp = filePartBackedBySrc("invoice.pdf", true); - - RewardTransaction trx = baseInvoicedTrx(); - trx.setId(TRX_ID); - trx.setMerchantId(MERCHANT_ID); - trx.setPointOfSaleId(POS_ID); - trx.setUserId(USER_ID); - trx.setStatus(SyncTrxStatus.INVOICED.name()); - trx.setRewardBatchId("SAME"); - trx.setInvoiceData(InvoiceData.builder().filename("old.pdf").build()); - trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.CONSULTABLE); - trx.setInitiatives(List.of(INITIATIVE_ID)); - trx.setBusinessName("Biz"); - trx.setPointOfSaleType(PosType.PHYSICAL); - trx.setRewards(Map.of(INITIATIVE_ID, Reward.builder().accruedRewardCents(123L).build())); - trx.setInitiativeId(INITIATIVE_ID); - - RewardBatch oldBatch = new RewardBatch(); - oldBatch.setId("SAME"); - oldBatch.setStatus(RewardBatchStatus.EVALUATING); - oldBatch.setMonth("2024-01"); - - RewardBatch sameBatch = new RewardBatch(); - sameBatch.setId("SAME"); - sameBatch.setStatus(RewardBatchStatus.EVALUATING); - sameBatch.setMonth(YearMonth.now().toString()); - - @SuppressWarnings("unchecked") - Response uploadResponse = (Response) mock(Response.class); - when(invoiceStorageClient.upload(any(InputStream.class), anyString(), anyString())) - .thenReturn(uploadResponse); - - when(rewardTransactionRepository.save(any())).thenAnswer(inv -> Mono.just(inv.getArgument(0))); - when(rewardBatchRepository.findRewardBatchById("SAME")).thenReturn(Mono.just(oldBatch)); - - RewardTransaction suspended = cloneTrx(trx); - suspended.setRewardBatchTrxStatus(RewardBatchTrxStatus.SUSPENDED); - - when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) - .thenReturn(Mono.just(trx)) - .thenReturn(Mono.just(suspended)); + // save chiamata 2 volte: (1) update invoice (2) set status SUSPENDED + ArgumentCaptor trxCaptor = ArgumentCaptor.forClass(RewardTransaction.class); + when(rewardTransactionRepository.save(trxCaptor.capture())) + .thenAnswer(inv -> Mono.just(inv.getArgument(0))); - when(rewardBatchService.suspendTransactions(eq("SAME"), eq(INITIATIVE_ID), any(TransactionsRequest.class))) + when(rewardBatchRepository.updateTotals(eq("OLD"), any(BatchCountersDTO.class))) .thenReturn(Mono.just(oldBatch)); - - when(rewardBatchService.findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), eq(YearMonth.now().toString()), eq("Biz"))) - .thenReturn(Mono.just(sameBatch)); + when(rewardBatchService.findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), anyString(), eq("Biz"))) + .thenReturn(Mono.just(newBatch)); + when(rewardBatchRepository.updateTotals(eq("NEW"), any(BatchCountersDTO.class))) + .thenReturn(Mono.just(newBatch)); StepVerifier.create(service.updateInvoiceTransaction(TRX_ID, MERCHANT_ID, POS_ID, fp, DOC_NUMBER)) .verifyComplete(); - verify(rewardBatchService, never()).moveSuspendToNewBatch(anyString(), anyString(), anyLong()); - verify(rewardBatchService, never()).decrementTotalAmountCents(anyString(), anyLong()); - verify(rewardBatchService, never()).incrementTotalAmountCents(anyString(), anyLong()); + verify(rewardBatchRepository).updateTotals(eq("OLD"), any(BatchCountersDTO.class)); + verify(rewardBatchRepository).updateTotals(eq("NEW"), any(BatchCountersDTO.class)); + verify(rewardBatchService).findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), anyString(), eq("Biz")); + + // verifica che almeno una delle save imposti SUSPENDED + assertTrue( + trxCaptor.getAllValues().stream().anyMatch(t -> t.getRewardBatchTrxStatus() == RewardBatchTrxStatus.SUSPENDED), + "Expected a save with RewardBatchTrxStatus=SUSPENDED" + ); + verify(rewardTransactionRepository, times(2)).save(any()); } + @Test - void updateInvoiceTransaction_createdBatch_newBatchDifferent_movesTotalsWithDecrementAndIncrement() { + void updateInvoiceTransaction_evaluatingBatch_alreadySuspended_savesOnce_andUpdatesTotalsOldAndNew() { FilePart fp = filePartBackedBySrc("invoice.pdf", true); RewardTransaction trx = baseInvoicedTrx(); @@ -1156,20 +935,21 @@ void updateInvoiceTransaction_createdBatch_newBatchDifferent_movesTotalsWithDecr trx.setStatus(SyncTrxStatus.INVOICED.name()); trx.setRewardBatchId("OLD"); trx.setInvoiceData(InvoiceData.builder().filename("old.pdf").build()); - trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.CONSULTABLE); + trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.SUSPENDED); trx.setInitiatives(List.of(INITIATIVE_ID)); trx.setBusinessName("Biz"); trx.setPointOfSaleType(PosType.PHYSICAL); trx.setRewards(Map.of(INITIATIVE_ID, Reward.builder().accruedRewardCents(123L).build())); - trx.setInitiativeId(INITIATIVE_ID); RewardBatch oldBatch = new RewardBatch(); oldBatch.setId("OLD"); - oldBatch.setStatus(RewardBatchStatus.CREATED); + oldBatch.setMerchantId(MERCHANT_ID); + oldBatch.setStatus(RewardBatchStatus.EVALUATING); oldBatch.setMonth("2024-01"); RewardBatch newBatch = new RewardBatch(); newBatch.setId("NEW"); + newBatch.setMerchantId(MERCHANT_ID); newBatch.setStatus(RewardBatchStatus.CREATED); newBatch.setMonth(YearMonth.now().toString()); @@ -1180,86 +960,83 @@ void updateInvoiceTransaction_createdBatch_newBatchDifferent_movesTotalsWithDecr when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) .thenReturn(Mono.just(trx)); + when(rewardBatchRepository.findRewardBatchById("OLD")) + .thenReturn(Mono.just(oldBatch)); - when(rewardBatchRepository.findRewardBatchById("OLD")).thenReturn(Mono.just(oldBatch)); - when(rewardTransactionRepository.save(any())).thenAnswer(inv -> Mono.just(inv.getArgument(0))); + when(rewardTransactionRepository.save(any())) + .thenAnswer(inv -> Mono.just(inv.getArgument(0))); - when(rewardBatchService.findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), eq(YearMonth.now().toString()), eq("Biz"))) + when(rewardBatchRepository.updateTotals(eq("OLD"), any(BatchCountersDTO.class))) + .thenReturn(Mono.just(oldBatch)); + when(rewardBatchService.findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), anyString(), eq("Biz"))) + .thenReturn(Mono.just(newBatch)); + when(rewardBatchRepository.updateTotals(eq("NEW"), any(BatchCountersDTO.class))) .thenReturn(Mono.just(newBatch)); - - when(rewardBatchService.decrementTotalAmountCents("OLD", 123L)).thenReturn(Mono.just(oldBatch)); - when(rewardBatchService.incrementTotalAmountCents("NEW", 123L)).thenReturn(Mono.just(newBatch)); StepVerifier.create(service.updateInvoiceTransaction(TRX_ID, MERCHANT_ID, POS_ID, fp, DOC_NUMBER)) .verifyComplete(); - verify(rewardBatchService, never()).suspendTransactions(anyString(), anyString(), any()); - verify(rewardBatchService).decrementTotalAmountCents("OLD", 123L); - verify(rewardBatchService).incrementTotalAmountCents("NEW", 123L); - verify(rewardBatchService, never()).moveSuspendToNewBatch(anyString(), anyString(), anyLong()); + verify(rewardTransactionRepository, times(2)).save(any()); + + verify(rewardBatchRepository).updateTotals(eq("OLD"), any(BatchCountersDTO.class)); + verify(rewardBatchRepository).updateTotals(eq("NEW"), any(BatchCountersDTO.class)); + verify(rewardBatchService).findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), anyString(), eq("Biz")); } @Test - void updateInvoiceTransaction_evaluatingBatch_onBatchMove_updatesLastMonthElaborated() { - FilePart fp = filePartBackedBySrc("invoice.pdf", true); + void updateInvoiceTransaction_rewardBatchStatusNotAllowed_throws() { + FilePart fp = mockFilePart("invoice.pdf", true); - RewardTransaction trx = baseInvoicedTrx(); - trx.setId(TRX_ID); + RewardTransaction trx = new RewardTransaction(); + trx.setRewardBatchId("B1"); trx.setMerchantId(MERCHANT_ID); trx.setPointOfSaleId(POS_ID); - trx.setUserId(USER_ID); - trx.setStatus(SyncTrxStatus.INVOICED.name()); - trx.setRewardBatchId("OLD"); trx.setInvoiceData(InvoiceData.builder().filename("old.pdf").build()); - trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.CONSULTABLE); - trx.setInitiatives(List.of(INITIATIVE_ID)); - trx.setBusinessName("Biz"); - trx.setPointOfSaleType(PosType.PHYSICAL); - trx.setRewards(Map.of(INITIATIVE_ID, Reward.builder().accruedRewardCents(123L).build())); - trx.setInitiativeId(INITIATIVE_ID); - - RewardBatch oldBatch = new RewardBatch(); - oldBatch.setId("OLD"); - oldBatch.setStatus(RewardBatchStatus.EVALUATING); - oldBatch.setMonth("2024-01"); + trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.SUSPENDED); - RewardBatch newBatch = new RewardBatch(); - newBatch.setId("NEW"); - newBatch.setStatus(RewardBatchStatus.CREATED); - newBatch.setMonth(YearMonth.now().toString()); + RewardBatch batch = new RewardBatch(); + batch.setId("B1"); + batch.setStatus(RewardBatchStatus.SENT); - @SuppressWarnings("unchecked") - Response uploadResponse = (Response) mock(Response.class); - when(invoiceStorageClient.upload(any(InputStream.class), anyString(), anyString())) - .thenReturn(uploadResponse); + when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) + .thenReturn(Mono.just(trx)); + when(rewardBatchRepository.findRewardBatchById("B1")) + .thenReturn(Mono.just(batch)); - when(rewardBatchRepository.findRewardBatchById("OLD")).thenReturn(Mono.just(oldBatch)); + StepVerifier.create(service.updateInvoiceTransaction(TRX_ID, MERCHANT_ID, POS_ID, fp, DOC_NUMBER)) + .expectError(ClientExceptionWithBody.class) + .verify(); - when(rewardBatchService.suspendTransactions(eq("OLD"), eq(INITIATIVE_ID), any(TransactionsRequest.class))) - .thenReturn(Mono.just(oldBatch)); + verify(rewardTransactionRepository, never()).save(any()); + verify(rewardBatchRepository, never()).updateTotals(anyString(), any()); + } - RewardTransaction suspended = cloneTrx(trx); - suspended.setRewardBatchTrxStatus(RewardBatchTrxStatus.SUSPENDED); - suspended.setRewardBatchLastMonthElaborated("2024-01"); - when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) - .thenReturn(Mono.just(trx)) - .thenReturn(Mono.just(suspended)); + @Test + void updateInvoiceTransaction_trxApprovedNotAllowed_throws() { + FilePart fp = mockFilePart("invoice.pdf", true); - when(rewardBatchService.findOrCreateBatch(eq(MERCHANT_ID), eq(PosType.PHYSICAL), eq(YearMonth.now().toString()), eq("Biz"))) - .thenReturn(Mono.just(newBatch)); + RewardTransaction trx = new RewardTransaction(); + trx.setRewardBatchId("B1"); + trx.setMerchantId(MERCHANT_ID); + trx.setPointOfSaleId(POS_ID); + trx.setInvoiceData(InvoiceData.builder().filename("old.pdf").build()); + trx.setRewardBatchTrxStatus(RewardBatchTrxStatus.APPROVED); - when(rewardBatchService.moveSuspendToNewBatch("OLD", "NEW", 123L)).thenReturn(Mono.just(oldBatch)); + RewardBatch batch = new RewardBatch(); + batch.setId("B1"); + batch.setStatus(RewardBatchStatus.EVALUATING); - ArgumentCaptor captor = ArgumentCaptor.forClass(RewardTransaction.class); - when(rewardTransactionRepository.save(captor.capture())) - .thenAnswer(inv -> Mono.just(inv.getArgument(0))); + when(rewardTransactionRepository.findTransactionForUpdateInvoice(MERCHANT_ID, POS_ID, TRX_ID)) + .thenReturn(Mono.just(trx)); + when(rewardBatchRepository.findRewardBatchById("B1")) + .thenReturn(Mono.just(batch)); StepVerifier.create(service.updateInvoiceTransaction(TRX_ID, MERCHANT_ID, POS_ID, fp, DOC_NUMBER)) - .verifyComplete(); + .expectError(ClientExceptionWithBody.class) + .verify(); - assertTrue(captor.getAllValues().stream().anyMatch(t -> - "NEW".equals(t.getRewardBatchId()) && - t.getRewardBatchLastMonthElaborated() != null - )); + verify(rewardTransactionRepository, never()).save(any()); + verify(rewardBatchRepository, never()).updateTotals(anyString(), any()); } + } diff --git a/src/test/java/it/gov/pagopa/idpay/transactions/service/RewardBatchServiceImplTest.java b/src/test/java/it/gov/pagopa/idpay/transactions/service/RewardBatchServiceImplTest.java index 6fe96744..465df61e 100644 --- a/src/test/java/it/gov/pagopa/idpay/transactions/service/RewardBatchServiceImplTest.java +++ b/src/test/java/it/gov/pagopa/idpay/transactions/service/RewardBatchServiceImplTest.java @@ -217,11 +217,9 @@ void incrementDecrementMoveSuspend_callsRepository() { when(rewardBatchRepository.incrementTotalAmountCents(BATCH_ID, 50L)).thenReturn(Mono.just(rb)); when(rewardBatchRepository.decrementTotalAmountCents(BATCH_ID, 10L)).thenReturn(Mono.just(rb)); - when(rewardBatchRepository.moveSuspendToNewBatch("OLD", "NEW", 99L)).thenReturn(Mono.just(rb)); StepVerifier.create(service.incrementTotalAmountCents(BATCH_ID, 50L)).expectNext(rb).verifyComplete(); StepVerifier.create(service.decrementTotalAmountCents(BATCH_ID, 10L)).expectNext(rb).verifyComplete(); - StepVerifier.create(service.moveSuspendToNewBatch("OLD", "NEW", 99L)).expectNext(rb).verifyComplete(); } @Test