From 6243948cc9e6e3319e714b197d8a4255e7c20178 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Thu, 22 Jan 2026 17:07:01 +0100 Subject: [PATCH] Allow invoice generation for pending transactions via uid (#3029) - Extend getTxStatementDetails to accept both numeric id and string uid - Remove isComplete check for INVOICE (keep for RECEIPT only) - Update transaction controller to detect id vs uid parameter This enables users to download invoices for transactions that are still pending (e.g., waiting for payment). --- .../history/controllers/transaction.controller.ts | 6 ++++-- .../payment/services/transaction-helper.ts | 14 ++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/subdomains/core/history/controllers/transaction.controller.ts b/src/subdomains/core/history/controllers/transaction.controller.ts index ff9d6961d3..f59d90d8bd 100644 --- a/src/subdomains/core/history/controllers/transaction.controller.ts +++ b/src/subdomains/core/history/controllers/transaction.controller.ts @@ -435,9 +435,10 @@ export class TransactionController { @UseGuards(AuthGuard(), RoleGuard(UserRole.ACCOUNT), IpGuard, UserActiveGuard()) @ApiOkResponse({ type: PdfDto }) async generateInvoiceFromTransaction(@GetJwt() jwt: JwtPayload, @Param('id') id: string): Promise { + const txIdOrUid = isNaN(+id) ? id : +id; const txStatementDetails = await this.transactionHelper.getTxStatementDetails( jwt.account, - +id, + txIdOrUid, TxStatementType.INVOICE, ); @@ -453,9 +454,10 @@ export class TransactionController { @UseGuards(AuthGuard(), RoleGuard(UserRole.ACCOUNT), IpGuard, UserActiveGuard()) @ApiOkResponse({ type: PdfDto }) async generateReceiptFromTransaction(@GetJwt() jwt: JwtPayload, @Param('id') id: string): Promise { + const txIdOrUid = isNaN(+id) ? id : +id; const txStatementDetails = await this.transactionHelper.getTxStatementDetails( jwt.account, - +id, + txIdOrUid, TxStatementType.RECEIPT, ); diff --git a/src/subdomains/supporting/payment/services/transaction-helper.ts b/src/subdomains/supporting/payment/services/transaction-helper.ts index 945827dd88..1dd035d634 100644 --- a/src/subdomains/supporting/payment/services/transaction-helper.ts +++ b/src/subdomains/supporting/payment/services/transaction-helper.ts @@ -493,20 +493,26 @@ export class TransactionHelper implements OnModuleInit { async getTxStatementDetails( userDataId: number, - txId: number, + txIdOrUid: number | string, statementType: TxStatementType, ): Promise { - const transaction = await this.transactionService.getTransactionById(txId, { + const relations = { userData: { organization: true }, buyCrypto: { buy: { user: { wallet: true } }, cryptoRoute: true, cryptoInput: true }, buyFiat: { sell: true, cryptoInput: true }, refReward: { user: { userData: true } }, - }); + }; + + const transaction = + typeof txIdOrUid === 'number' + ? await this.transactionService.getTransactionById(txIdOrUid, relations) + : await this.transactionService.getTransactionByUid(txIdOrUid, relations); if (!transaction || !transaction.targetEntity || transaction.targetEntity instanceof BankTxReturn) throw new BadRequestException('Transaction not found'); if (!transaction.userData.isDataComplete) throw new BadRequestException('User data is not complete'); - if (!transaction.targetEntity.isComplete) throw new BadRequestException('Transaction not completed'); + if (statementType === TxStatementType.RECEIPT && !transaction.targetEntity.isComplete) + throw new BadRequestException('Transaction not completed'); if (transaction.userData.id !== userDataId) throw new ForbiddenException('Not your transaction'); if (transaction.buyCrypto && !transaction.buyCrypto.isCryptoCryptoTransaction) {