Skip to content

Commit

Permalink
feat: add invoice refunds
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanvanherwijnen committed Aug 8, 2024
1 parent bb63318 commit 06a1b84
Show file tree
Hide file tree
Showing 8 changed files with 794 additions and 720 deletions.
4 changes: 2 additions & 2 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@
"@fastify/cors": "^9.0.1",
"@fastify/middie": "8.3.1",
"@fastify/static": "7.0.4",
"@modular-api/api": "^0.4.16",
"@modular-api/api": "^0.4.17",
"@modular-api/fastify-cart": "^0.2.4",
"@modular-api/fastify-checkout": "^0.3.6",
"@modular-api/fastify-checkout": "^0.3.7",
"@modular-api/fastify-oidc": "^0.5.4",
"@mollie/api-client": "^3.7.0",
"@slimfact/app": "^0.1.0",
Expand Down
27 changes: 27 additions & 0 deletions packages/api/src/trpc/admin/invoices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -762,5 +762,32 @@ export const adminInvoiceRoutes = ({
status
})
}
}),
refundInvoice: procedure
.input(
z.object({
id: z.number()
})
)
.mutation(async ({ input }) => {
const { id } = input

if (fastify.checkout?.invoiceHandler) {
const result = await fastify.checkout.invoiceHandler.refundInvoice({
id
})

if (result.success) {
return result.refund
} else {
throw new TRPCError({
code: 'BAD_REQUEST',
message: result.errorMessage
})
}
}
throw new TRPCError({
code: 'BAD_REQUEST'
})
})
})
3 changes: 2 additions & 1 deletion packages/api/src/trpc/public/invoices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export const publicInvoiceRoutes = ({
uuid,
options: {
withAmountPaid: true,
withAmountDue: true
withAmountDue: true,
withAmountRefunded: true
}
})
if (invoice?.status !== 'concept') return invoice
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/lang/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ const lang: Language = {
pay: 'Pay',
addPayment: 'Add payment',
amountDue: 'Amount due',
amountPaid: 'Amount paid',
fields: {
transactionReference: 'Transaction reference',
description: 'Description'
Expand All @@ -212,6 +213,9 @@ const lang: Language = {
scanQrOrUseInformationBelow:
'Scan the QR code if your bank supports it or use the information supplied below.'
}
},
refund: {
refund: 'Refund'
}
}

Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/lang/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ export interface Language {
pay: string
addPayment: string
amountDue: string
amountPaid: string
fields: {
transactionReference: string
description: string
Expand All @@ -236,6 +237,9 @@ export interface Language {
scanQrOrUseInformationBelow: string
}
}
refund: {
refund: string
}
}

import type { Ref } from 'vue'
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/lang/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ const lang: Language = {
pay: 'Betaal',
addPayment: 'Betaling toevoegen',
amountDue: 'Te betalen',
amountPaid: 'Betaald',
fields: {
transactionReference: 'Transactie referentie',
description: 'Omschrijving'
Expand All @@ -214,6 +215,9 @@ const lang: Language = {
scanQrOrUseInformationBelow:
'Scan de QR code als uw bank dit ondersteunt of gebruik de informatie zoals hieronder weergegeven.'
}
},
refund: {
refund: 'Terugbetaling'
}
}

Expand Down
39 changes: 39 additions & 0 deletions packages/app/src/pages/InvoicePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@
</q-list>
</q-menu>
</q-btn>
<q-btn
v-if="
invoice &&
invoice.amountDue &&
invoice.amountDue < 0 &&
user?.roles?.includes('administrator')
"
:label="`${lang.refund.refund} ${format(-invoice.amountDue)}`"
color="primary"
@click="refund"
/>
<q-btn
v-if="invoice"
icon="download"
Expand All @@ -75,6 +86,14 @@
</div>

<div class="row justify-center">
<div v-if="invoice?.amountPaid && invoice?.amountPaid > 0" class="no-print">
{{ lang.payment.amountPaid }}:
<price
:model-value="invoice.amountPaid"
:currency="invoice.currency"
:locale="invoice.locale"
/>
</div>
<div v-if="invoice?.amountDue && invoice?.amountDue > 0" class="no-print">
{{ lang.payment.amountDue }}:
<price
Expand Down Expand Up @@ -228,6 +247,19 @@ const payWithSmartpin = async () => {
if (result.data.value) window.location.href = result.data.value
}
const refund = async () => {
if (invoice.value) {
const result = useMutation('admin.refundInvoice', {
args: {
id: invoice.value.id
},
immediate: true
})
await result.immediatePromise
}
}
const bankTransferDialogRef = ref<typeof ResponsiveDialog>()
const openBankTransferDialog = () => {
bankTransferDialogRef.value?.functions.open()
Expand Down Expand Up @@ -257,6 +289,13 @@ const onResize: InstanceType<typeof QResizeObserver>['$props']['onResize'] = (
scrollAreaSize.value.height = `${size.height}px`
}
const format = (value: number) =>
Intl.NumberFormat($q.lang.isoName, {
maximumFractionDigits: 2,
style: 'currency',
currency: invoice.value?.currency
}).format(value / 100)
const language = ref($q.lang.isoName)
onMounted(async () => {
await loadConfiguration(language)
Expand Down
Loading

0 comments on commit 06a1b84

Please sign in to comment.