expose payment label and multi-crypto amounts in admin order invoice view.

This commit is contained in:
2026-09-06 14:19:37 +02:00
parent e7c42fcaca
commit 9e776df79f
3 changed files with 49 additions and 5 deletions
@@ -210,11 +210,45 @@ describe('OrderService', () => {
accessToken: 'plain-token', accessToken: 'plain-token',
checkoutInvoice: expect.objectContaining({ checkoutInvoice: expect.objectContaining({
statusLabel: 'Payment confirmed', statusLabel: 'Payment confirmed',
paymentLabel: 'XMR',
expectedTotalCrypto: '0.10000000' expectedTotalCrypto: '0.10000000'
}) })
}) })
); );
}); });
it('formats bitcoin checkout invoice amounts for the admin order view', async () => {
const storedOrder = {
...buildStoredOrder(),
checkoutInvoice: {
id: 'invoice-1',
fiatCurrency: 'USD',
paymentMethod: PaymentMethod.Btc,
expectedTotalAtomic: '100000000',
expiresAt: new Date('2099-01-01T00:00:00.000Z'),
btcDetails: { fiatPerBtcAtCreation: 60_000, requiredConfirmations: 1 },
moneroDetails: null,
payments: [{ id: 'pay-1', amountAtomic: '100000000', confirmations: 1, txHash: 'tx-1' }],
reason: InvoiceReason.Checkout
}
} as unknown as Order;
orderDetailQueryBuilder.getOne.mockResolvedValue(storedOrder);
const result = await service.findById('order-1');
expect(result.checkoutInvoice).toEqual(
expect.objectContaining({
paymentLabel: 'BTC',
expectedTotalCrypto: '1.00000000',
payments: [
expect.objectContaining({
amountCrypto: '1.00000000'
})
]
})
);
});
}); });
describe('setDeliveryCost', () => { describe('setDeliveryCost', () => {
@@ -8,7 +8,9 @@ import { formatInvoicePaymentConfirmationStatus } from '../../../utils/invoice/f
import { resolveInvoiceStatusMessage } from '../../../utils/invoice/resolveInvoiceStatusMessage'; import { resolveInvoiceStatusMessage } from '../../../utils/invoice/resolveInvoiceStatusMessage';
import { resolveInvoiceRequiredConfirmations } from '../../../utils/invoice/resolveInvoiceRequiredConfirmations'; import { resolveInvoiceRequiredConfirmations } from '../../../utils/invoice/resolveInvoiceRequiredConfirmations';
import type { InvoiceState } from '../../../utils/invoice/types/InvoiceState'; import type { InvoiceState } from '../../../utils/invoice/types/InvoiceState';
import { convertXmrAtomicToXmr } from '../../../utils/monero/convertXmrAtomicToXmr'; import type { CryptoAtomicConverter } from '../../../types/CryptoAtomicConverter';
import { paymentMethodLabel } from '../../../consts/paymentMethodLabel';
import { resolveAtomicToCryptoConverter } from '../../../utils/payment/resolveAtomicToCryptoConverter';
import type { Invoice } from '../../payment/entities/Invoice'; import type { Invoice } from '../../payment/entities/Invoice';
import type { InvoicePayment } from '../../payment/entities/InvoicePayment'; import type { InvoicePayment } from '../../payment/entities/InvoicePayment';
import type { InvoiceExtended } from '../../payment/types/InvoiceExtended'; import type { InvoiceExtended } from '../../payment/types/InvoiceExtended';
@@ -182,24 +184,31 @@ export class OrderService {
const statusLabel = invoiceState ? resolveInvoiceStatusMessage(invoiceState) : null; const statusLabel = invoiceState ? resolveInvoiceStatusMessage(invoiceState) : null;
const expectedTotalCrypto = convertXmrAtomicToXmr(invoice.expectedTotalAtomic); const convertAtomicToCrypto = resolveAtomicToCryptoConverter(invoice.paymentMethod);
const expectedTotalCrypto = convertAtomicToCrypto(invoice.expectedTotalAtomic);
const payments = (invoice.payments ?? []).map(payment => const payments = (invoice.payments ?? []).map(payment =>
this.toInvoicePaymentExtended(payment, requiredConfirmations) this.toInvoicePaymentExtended(payment, requiredConfirmations, convertAtomicToCrypto)
); );
return { return {
...invoice, ...invoice,
statusLabel, statusLabel,
paymentLabel: paymentMethodLabel[invoice.paymentMethod],
expectedTotalCrypto, expectedTotalCrypto,
payments payments
}; };
} }
private toInvoicePaymentExtended(payment: InvoicePayment, requiredConfirmations: number): InvoicePaymentExtended { private toInvoicePaymentExtended(
payment: InvoicePayment,
requiredConfirmations: number,
convertAtomicToCrypto: CryptoAtomicConverter
): InvoicePaymentExtended {
const isConfirmed = payment.confirmations >= requiredConfirmations; const isConfirmed = payment.confirmations >= requiredConfirmations;
const amountCrypto = convertXmrAtomicToXmr(payment.amountAtomic); const amountCrypto = convertAtomicToCrypto(payment.amountAtomic);
const confirmationsLabel = formatInvoicePaymentConfirmationStatus({ const confirmationsLabel = formatInvoicePaymentConfirmationStatus({
confirmations: payment.confirmations, confirmations: payment.confirmations,
@@ -4,6 +4,7 @@ import type { InvoiceStatusLabel } from '../../../utils/invoice/types/InvoiceSta
export type InvoiceExtended = Omit<Invoice, 'payments'> & { export type InvoiceExtended = Omit<Invoice, 'payments'> & {
statusLabel: InvoiceStatusLabel | null; statusLabel: InvoiceStatusLabel | null;
paymentLabel: string;
expectedTotalCrypto: string; expectedTotalCrypto: string;
payments: InvoicePaymentExtended[]; payments: InvoicePaymentExtended[];
}; };