From d5b7c732df6c0181c90d17b9550902961a78727b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 16 Apr 2024 15:07:22 -0300 Subject: fix #8746 --- packages/taler-wallet-core/src/pay-merchant.ts | 52 +++++++++++++++++++++----- packages/taler-wallet-core/src/shepherd.ts | 11 +++--- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts index 80e88337e..e08f23beb 100644 --- a/packages/taler-wallet-core/src/pay-merchant.ts +++ b/packages/taler-wallet-core/src/pay-merchant.ts @@ -2752,14 +2752,36 @@ async function processPurchaseAutoRefund( const download = await expectProposalDownload(wex, purchase); - if ( - !purchase.autoRefundDeadline || - AbsoluteTime.isExpired( - AbsoluteTime.fromProtocolTimestamp( - timestampProtocolFromDb(purchase.autoRefundDeadline), - ), - ) - ) { + const noAutoRefundOrExpired = !purchase.autoRefundDeadline || + AbsoluteTime.isExpired( + AbsoluteTime.fromProtocolTimestamp( + timestampProtocolFromDb(purchase.autoRefundDeadline), + ), + ) + + const totalKnownRefund = await wex.db.runReadOnlyTx( + ["refundGroups"], + async (tx) => { + const refunds = await tx.refundGroups.indexes.byProposalId.getAll( + purchase.proposalId, + ); + const am = Amounts.parseOrThrow(download.contractData.amount); + return refunds.reduce((prev, cur) => { + if ( + cur.status === RefundGroupStatus.Done || + cur.status === RefundGroupStatus.Pending + ) { + return Amounts.add(prev, cur.amountEffective).amount; + } + return prev; + }, Amounts.zeroOfAmount(am)); + }, + ); + + const refundedIsLessThanPrice = Amounts.cmp(download.contractData.amount, totalKnownRefund) === +1 + const nothingMoreToRefund = !refundedIsLessThanPrice + + if (noAutoRefundOrExpired || nothingMoreToRefund) { const transitionInfo = await wex.db.runReadWriteTx( ["purchases"], async (tx) => { @@ -2792,8 +2814,9 @@ async function processPurchaseAutoRefund( download.contractData.contractTermsHash, ); - requestUrl.searchParams.set("timeout_ms", "1000"); + requestUrl.searchParams.set("timeout_ms", "10000"); requestUrl.searchParams.set("await_refund_obtained", "yes"); + requestUrl.searchParams.set("refund", Amounts.stringify(totalKnownRefund)); const resp = await wex.http.fetch(requestUrl.href, { cancellationToken: wex.cancellationToken, @@ -3344,9 +3367,20 @@ async function storeRefunds( } const oldTxState = computePayMerchantTransactionState(myPurchase); + + const shouldCheckAutoRefund = + myPurchase.autoRefundDeadline && + !AbsoluteTime.isExpired( + AbsoluteTime.fromProtocolTimestamp( + timestampProtocolFromDb(myPurchase.autoRefundDeadline), + ), + ); + if (numPendingItemsTotal === 0) { if (isAborting) { myPurchase.purchaseStatus = PurchaseStatus.AbortedRefunded; + } else if (shouldCheckAutoRefund) { + myPurchase.purchaseStatus = PurchaseStatus.PendingQueryingAutoRefund; } else { myPurchase.purchaseStatus = PurchaseStatus.Done; } diff --git a/packages/taler-wallet-core/src/shepherd.ts b/packages/taler-wallet-core/src/shepherd.ts index b2722ce1d..58bdcf0dd 100644 --- a/packages/taler-wallet-core/src/shepherd.ts +++ b/packages/taler-wallet-core/src/shepherd.ts @@ -237,7 +237,7 @@ export class TaskSchedulerImpl implements TaskScheduler { * * Mostly useful to interrupt all waits when time-travelling. */ - reload() { + reload(): void { this.ensureRunning(); const tasksIds = [...this.sheps.keys()]; logger.info(`reloading sheperd with ${tasksIds.length} tasks`); @@ -372,9 +372,8 @@ export class TaskSchedulerImpl implements TaskScheduler { taskId, res.errorDetail, ); - let delay: Duration; const t = timestampAbsoluteFromDb(retryRecord.retryInfo.nextRetry); - delay = AbsoluteTime.remaining(t); + const delay = AbsoluteTime.remaining(t); logger.trace(`Waiting for ${delay.d_ms} ms`); await this.wait(taskId, info, delay); break; @@ -382,9 +381,8 @@ export class TaskSchedulerImpl implements TaskScheduler { case TaskRunResultType.Backoff: { logger.trace(`Shepherd for ${taskId} got backoff result.`); const retryRecord = await storePendingTaskPending(this.ws, taskId); - let delay: Duration; const t = timestampAbsoluteFromDb(retryRecord.retryInfo.nextRetry); - delay = AbsoluteTime.remaining(t); + const delay = AbsoluteTime.remaining(t); logger.trace(`Waiting for ${delay.d_ms} ms`); await this.wait(taskId, info, delay); break; @@ -396,13 +394,14 @@ export class TaskSchedulerImpl implements TaskScheduler { await storeTaskProgress(this.ws, taskId); break; } - case TaskRunResultType.ScheduleLater: + case TaskRunResultType.ScheduleLater: { logger.trace(`Shepherd for ${taskId} got schedule-later result.`); await storeTaskProgress(this.ws, taskId); const delay = AbsoluteTime.remaining(res.runAt); logger.trace(`Waiting for ${delay.d_ms} ms`); await this.wait(taskId, info, delay); break; + } case TaskRunResultType.Finished: logger.trace(`Shepherd for ${taskId} got finished result.`); await storePendingTaskFinished(this.ws, taskId); -- cgit v1.2.3