Refactor collectedOrderInvoiceManageStripe.vue to integrate economic queue job for Stripe invoice booking:
- Replaced refs with computed properties for status determination (paid, draft, booked, etc.). - Integrated `useEconomicQueueJob` for stripe transfer management, including enqueue, retry, and transport error handling. - Streamlined Stripe payment data mapping with `computed` for enhanced maintainability. - Updated template to include improved UI elements for transfer status and error feedback. - Added progress indicators and notifications for queue operations.
This commit is contained in:
+200
-121
@@ -1,82 +1,118 @@
|
||||
<script setup>
|
||||
import { defineProps, ref } from 'vue';
|
||||
import { computed, onBeforeUnmount } from "vue";
|
||||
import { Colors } from "@/ThemeConfig.vue";
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
import { StripeModule } from "@/components/stripe/StripeModule.vue";
|
||||
import GetOrderInvoicePDFButton from "@/components/search/economic/getOrderInvoicePDFButton.vue";
|
||||
import Swal from "sweetalert2";
|
||||
import { useI18n } from 'vue-i18n';
|
||||
const { t } = useI18n();
|
||||
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
|
||||
import ActionSettingsWheelItem from "@/components/displays/buttons/ActionSettingsWheelItem.vue";
|
||||
import { useEconomicQueueJob } from "@/composables/useEconomicQueueJob.js";
|
||||
|
||||
const props = defineProps({
|
||||
collectedOrderInvoice: {
|
||||
type: Object,
|
||||
required: false,
|
||||
},
|
||||
})
|
||||
/** Define the variables */
|
||||
const isCollapsed = ref(true);
|
||||
const isPaid = ref((props.collectedOrderInvoice?.stripe.status === 'succeeded'));
|
||||
const isDraft = ref((props.collectedOrderInvoice?.economic_invoice_draft_id !== null));
|
||||
const isBooked = ref((props.collectedOrderInvoice?.economic_invoice_booked_id !== null));
|
||||
});
|
||||
|
||||
const stripeTransferQueue = useEconomicQueueJob({
|
||||
enqueueEndpoint: "/collected-invoices/stripe/book",
|
||||
statusEndpoint: "/collected-invoices/economic/queue/status",
|
||||
retryEndpoint: "/collected-invoices/economic/queue/retry",
|
||||
requestFn: SessionUser.request,
|
||||
buildEnqueuePayload: () => ({
|
||||
id: Number.parseInt(String(props.collectedOrderInvoice?.id ?? ""), 10),
|
||||
}),
|
||||
});
|
||||
|
||||
/** Create the invoice */
|
||||
const onBookStripeInvoice = async () => {
|
||||
// Book the invoice
|
||||
console.log('Book invoice');
|
||||
await SessionUser.objects.collectedOrderInvoices.functions.stripe.book_invoice(parseInt(props.collectedOrderInvoice.id)).then((response) => {
|
||||
console.log('Invoice booked successfully', response);
|
||||
Swal.fire({
|
||||
title: t('collected_invoice.stripe.invoice_booked'),
|
||||
text: t('collected_invoice.stripe.invoice_booked_desc'),
|
||||
icon: 'success',
|
||||
showConfirmButton: false,
|
||||
timer: 2000
|
||||
}).then(() => {
|
||||
location.reload();
|
||||
});
|
||||
}).catch((error) => {
|
||||
console.log('Error booking invoice', error);
|
||||
onBeforeUnmount(() => {
|
||||
stripeTransferQueue.dispose();
|
||||
});
|
||||
|
||||
const isPaid = computed(() => props.collectedOrderInvoice?.stripe?.status === "succeeded");
|
||||
const isDraft = computed(() => props.collectedOrderInvoice?.economic_invoice_draft_id !== null);
|
||||
const isBooked = computed(() => props.collectedOrderInvoice?.economic_invoice_booked_id !== null);
|
||||
const showStripeStatusSummary = computed(() => isPaid.value && (isDraft.value || isBooked.value));
|
||||
|
||||
const isStripeTransferBusy = computed(() => stripeTransferQueue.disableSubmit.value);
|
||||
const isStripeTransferQueuedOrProcessing = computed(() => stripeTransferQueue.isQueuedOrProcessing.value);
|
||||
const isStripeTransferCompleted = computed(() => stripeTransferQueue.isCompleted.value);
|
||||
const isStripeTransferFailed = computed(() => stripeTransferQueue.isFailed.value);
|
||||
const stripeTransferProgressPercent = computed(() => stripeTransferQueue.progressPercent.value);
|
||||
const stripeTransferProgressMessage = computed(() => stripeTransferQueue.progressMessage.value);
|
||||
const stripeTransferTransportErrorMessage = computed(() => stripeTransferQueue.transportErrorMessage.value);
|
||||
const stripeTransferFailureMessage = computed(() => stripeTransferQueue.queueFailureMessage.value);
|
||||
const stripeTransferResultMessage = computed(() => {
|
||||
const queueResult = stripeTransferQueue.result.value;
|
||||
if (!queueResult) {
|
||||
return "";
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const stripePayment = {
|
||||
id: props.collectedOrderInvoice.stripe.id || null,
|
||||
currency: props.collectedOrderInvoice.stripe.currency || 'DKK',
|
||||
amount: props.collectedOrderInvoice.stripe.amount || 0,
|
||||
amount_received: props.collectedOrderInvoice.stripe.amount_received || 0,
|
||||
amount_capturable: props.collectedOrderInvoice.stripe.amount_capturable || 0,
|
||||
status: props.collectedOrderInvoice.stripe.status || 'pending',
|
||||
receipt_url: props.collectedOrderInvoice.stripe?.latest_charge?.receipt_url || null,
|
||||
metadata: {
|
||||
tax_percentage: props.collectedOrderInvoice.stripe?.latest_charge?.metadata?.tax_percentage || 0,
|
||||
},
|
||||
fees: {
|
||||
stripe_fee: props.collectedOrderInvoice.stripe?.latest_charge?.balance_transaction?.fee || 0,
|
||||
stripe_fee_details: props.collectedOrderInvoice.stripe?.latest_charge?.balance_transaction?.fee_details || [],
|
||||
stripe_fee_amount: props.collectedOrderInvoice.stripe?.latest_charge?.balance_transaction?.fee || 0,
|
||||
stripe_net_after_fees: props.collectedOrderInvoice.stripe?.latest_charge?.balance_transaction?.net || 0,
|
||||
currency: props.collectedOrderInvoice.stripe?.latest_charge?.balance_transaction?.currency || 'DKK',
|
||||
},
|
||||
getFeePercentage: (fee, amount) => {
|
||||
if (amount > 0) {
|
||||
return ((fee / amount) * 100).toFixed(2);
|
||||
} else {
|
||||
if (typeof queueResult === "string") {
|
||||
return queueResult;
|
||||
}
|
||||
|
||||
if (typeof queueResult?.message === "string") {
|
||||
return queueResult.message;
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.stringify(queueResult);
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
const onBookStripeInvoice = async () => {
|
||||
try {
|
||||
await stripeTransferQueue.enqueue({});
|
||||
} catch (error) {
|
||||
console.log("Error booking invoice", error);
|
||||
}
|
||||
};
|
||||
|
||||
const onRetryStripeTransfer = async () => {
|
||||
try {
|
||||
await stripeTransferQueue.retry();
|
||||
} catch (error) {
|
||||
console.log("Error retrying stripe transfer", error);
|
||||
}
|
||||
};
|
||||
|
||||
const stripePayment = computed(() => {
|
||||
const stripe = props.collectedOrderInvoice?.stripe ?? {};
|
||||
const latestCharge = stripe?.latest_charge ?? {};
|
||||
const balanceTransaction = latestCharge?.balance_transaction ?? {};
|
||||
|
||||
return {
|
||||
id: stripe.id || null,
|
||||
currency: stripe.currency || "DKK",
|
||||
amount: stripe.amount || 0,
|
||||
amount_received: stripe.amount_received || 0,
|
||||
amount_capturable: stripe.amount_capturable || 0,
|
||||
status: stripe.status || "pending",
|
||||
receipt_url: latestCharge?.receipt_url || null,
|
||||
metadata: {
|
||||
tax_percentage: latestCharge?.metadata?.tax_percentage || 0,
|
||||
},
|
||||
fees: {
|
||||
stripe_fee: balanceTransaction?.fee || 0,
|
||||
stripe_fee_details: balanceTransaction?.fee_details || [],
|
||||
stripe_fee_amount: balanceTransaction?.fee || 0,
|
||||
stripe_net_after_fees: balanceTransaction?.net || 0,
|
||||
currency: balanceTransaction?.currency || "DKK",
|
||||
},
|
||||
getFeePercentage: (fee, amount) => {
|
||||
if (amount > 0) {
|
||||
return ((fee / amount) * 100).toFixed(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- If the invoice is paid -->
|
||||
<div
|
||||
v-if="isPaid"
|
||||
v-if="showStripeStatusSummary"
|
||||
class="message"
|
||||
:class="{
|
||||
'is-success': isBooked,
|
||||
@@ -87,108 +123,109 @@ const stripePayment = {
|
||||
<div class="message-body">
|
||||
<div class="columns is-vcentered is-multiline">
|
||||
<div class="column is-narrow">
|
||||
<!-- Check-mark -->
|
||||
<span
|
||||
class="icon is-large"
|
||||
:class="
|
||||
isBooked
|
||||
? 'has-text-success'
|
||||
: 'has-text-warning'
|
||||
"
|
||||
class="icon is-large"
|
||||
:class="isBooked ? 'has-text-success' : 'has-text-warning'"
|
||||
>
|
||||
<i class="fas fa-check-circle fa-3x"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="column is-fullwidth">
|
||||
<p class="title is-4">{{ $t('collected_invoice.stripe.invoice_status', { status: isDraft ? $t('collected_invoice.stripe.saved_as_draft') : isBooked ? $t('collected_invoice.stripe.booked_with') : $t('collected_invoice.stripe.not_booked') }) }} E-conomic</p>
|
||||
<p class="subtitle is-6">{{ $t('collected_invoice.stripe.invoice_paid') }} <strong>{{ isBooked ? $t('collected_invoice.stripe.and_booked') : isDraft ? $t('collected_invoice.stripe.and_saved_draft') : $t('collected_invoice.stripe.but_not_booked') }}</strong> {{ $t('collected_invoice.stripe.in_economic') }}</p>
|
||||
<p class="title is-4">
|
||||
{{ $t('collected_invoice.stripe.invoice_status', { status: isDraft ? $t('collected_invoice.stripe.saved_as_draft') : isBooked ? $t('collected_invoice.stripe.booked_with') : $t('collected_invoice.stripe.not_booked') }) }}
|
||||
E-conomic
|
||||
</p>
|
||||
<p class="subtitle is-6">
|
||||
{{ $t('collected_invoice.stripe.invoice_paid') }}
|
||||
<strong>{{ isBooked ? $t('collected_invoice.stripe.and_booked') : isDraft ? $t('collected_invoice.stripe.and_saved_draft') : $t('collected_invoice.stripe.but_not_booked') }}</strong>
|
||||
{{ $t('collected_invoice.stripe.in_economic') }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Charges or refunds overview -->
|
||||
<div class="column is-12">
|
||||
<p class="title is-4">{{ $t('collected_invoice.stripe.payment_overview') }}</p>
|
||||
<!-- Stripe payment -->
|
||||
<template v-if="collectedOrderInvoice.stripe.latest_charge">
|
||||
<template v-if="collectedOrderInvoice?.stripe?.latest_charge">
|
||||
<div class="card">
|
||||
<!-- Card header -->
|
||||
<div class="card-header">
|
||||
<div class="card-header-icon">
|
||||
<span class="icon">
|
||||
<i
|
||||
class="fas fa-circle"
|
||||
:class="{
|
||||
'has-text-success': stripePayment.status === 'succeeded',
|
||||
'has-text-danger': stripePayment.status === 'failed',
|
||||
'has-text-warning': stripePayment.status === 'pending',
|
||||
}"
|
||||
class="fas fa-circle"
|
||||
:class="{
|
||||
'has-text-success': stripePayment.status === 'succeeded',
|
||||
'has-text-danger': stripePayment.status === 'failed',
|
||||
'has-text-warning': stripePayment.status === 'pending',
|
||||
}"
|
||||
></i>
|
||||
</span>
|
||||
<div class="tag is-success is-light">
|
||||
{{stripePayment.status}}
|
||||
{{ stripePayment.status }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header-title">
|
||||
<span>{{stripePayment.id}}</span>
|
||||
<span>{{ stripePayment.id }}</span>
|
||||
</div>
|
||||
<div class="card-header-icon">
|
||||
<span class="icon">
|
||||
<i class="fas fa-money-bill-wave"></i>
|
||||
</span>
|
||||
<div class="tag is-success is-light">
|
||||
{{stripePayment.amount / 100}} {{stripePayment.currency.toUpperCase()}} ( {{stripePayment.metadata?.tax_percentage}}% moms )
|
||||
{{ stripePayment.amount / 100 }} {{ stripePayment.currency.toUpperCase() }} ( {{ stripePayment.metadata?.tax_percentage }}% moms )
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Card content -->
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<p class="subtitle is-6">{{ $t('collected_invoice.stripe.payment_id') }}: {{stripePayment.id}}</p>
|
||||
<p class="subtitle is-6">{{ $t('collected_invoice.stripe.payment_amount') }}: {{stripePayment.amount / 100}} {{stripePayment.currency.toUpperCase()}}</p>
|
||||
<p class="subtitle is-6">{{ $t('collected_invoice.stripe.payment_status') }}: {{stripePayment.status}}</p>
|
||||
<p class="subtitle is-6">{{ $t('collected_invoice.stripe.payment_id') }}: {{ stripePayment.id }}</p>
|
||||
<p class="subtitle is-6">{{ $t('collected_invoice.stripe.payment_amount') }}: {{ stripePayment.amount / 100 }} {{ stripePayment.currency.toUpperCase() }}</p>
|
||||
<p class="subtitle is-6">{{ $t('collected_invoice.stripe.payment_status') }}: {{ stripePayment.status }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Card footer -->
|
||||
<div class="card-footer">
|
||||
<!-- Button to view the payment in Stripe -->
|
||||
<a
|
||||
class="card-footer-item"
|
||||
:href="'https://dashboard.stripe.com/payments/' + stripePayment.id"
|
||||
target="_blank"
|
||||
class="card-footer-item"
|
||||
:href="'https://dashboard.stripe.com/payments/' + stripePayment.id"
|
||||
target="_blank"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
</span>
|
||||
<span>{{SessionUser.objects.global.language.show + ' ' + SessionUser.objects.global.language.in + ' Stripe'}}</span>
|
||||
<span>{{ SessionUser.objects.global.language.show + ' ' + SessionUser.objects.global.language.in + ' Stripe' }}</span>
|
||||
</a>
|
||||
<!-- Button to process the payment, shown if the payment is ready to capture -->
|
||||
<a
|
||||
v-if="stripePayment.amount_capturable > 0"
|
||||
class="card-footer-item"
|
||||
@click="StripeModule.paymentIntents.capturePaymentIntent(collectedOrderInvoice.stripe)"
|
||||
style="cursor: pointer;"
|
||||
v-if="stripePayment.amount_capturable > 0"
|
||||
class="card-footer-item"
|
||||
@click="StripeModule.paymentIntents.capturePaymentIntent(collectedOrderInvoice.stripe)"
|
||||
style="cursor: pointer;"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-check"></i>
|
||||
</span>
|
||||
<span>{{SessionUser.objects.global.language.capture}}</span>
|
||||
<span>{{ SessionUser.objects.global.language.capture }}</span>
|
||||
</a>
|
||||
<!-- Button to view the receipt -->
|
||||
<a
|
||||
v-if="stripePayment.receipt_url"
|
||||
class="card-footer-item"
|
||||
:href="stripePayment.receipt_url"
|
||||
target="_blank"
|
||||
v-if="stripePayment.receipt_url"
|
||||
class="card-footer-item"
|
||||
:href="stripePayment.receipt_url"
|
||||
target="_blank"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-receipt"></i>
|
||||
</span>
|
||||
<span>{{SessionUser.objects.global.language.show + ' ' + SessionUser.objects.global.language.payment.receipt}}</span>
|
||||
<span>{{ SessionUser.objects.global.language.show + ' ' + SessionUser.objects.global.language.payment.receipt }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- Fees overview -->
|
||||
<p class="title is-4" v-if="stripePayment.fees.stripe_fee > 0">{{ $t('collected_invoice.stripe.stripe_fees') }}</p>
|
||||
<template v-for="( fee, index ) in stripePayment.fees.stripe_fee_details" :key="index">
|
||||
<p
|
||||
v-if="stripePayment.fees.stripe_fee > 0"
|
||||
class="title is-4"
|
||||
>
|
||||
{{ $t('collected_invoice.stripe.stripe_fees') }}
|
||||
</p>
|
||||
<template
|
||||
v-for="(fee, index) in stripePayment.fees.stripe_fee_details"
|
||||
:key="index"
|
||||
>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-icon">
|
||||
@@ -196,18 +233,18 @@ const stripePayment = {
|
||||
<i class="fas fa-circle has-text-grey"></i>
|
||||
</span>
|
||||
<div class="tag is-grey is-light">
|
||||
{{fee.type}}
|
||||
{{ fee.type }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header-title">
|
||||
<span>{{fee.description}}</span>
|
||||
<span>{{ fee.description }}</span>
|
||||
</div>
|
||||
<div class="card-header-icon">
|
||||
<span class="icon">
|
||||
<i class="fas fa-money-bill-wave"></i>
|
||||
</span>
|
||||
<div class="tag is-grey is-light">
|
||||
- {{fee.amount / 100}} {{stripePayment.currency.toUpperCase()}} ( {{stripePayment.getFeePercentage(fee.amount, stripePayment.amount)}}% )
|
||||
- {{ fee.amount / 100 }} {{ stripePayment.currency.toUpperCase() }} ( {{ stripePayment.getFeePercentage(fee.amount, stripePayment.amount) }}% )
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -217,8 +254,8 @@ const stripePayment = {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- If the invoice is paid, but not booked -->
|
||||
<div v-else-if="!isBooked && isPaid"
|
||||
<div
|
||||
v-else-if="isPaid"
|
||||
class="card"
|
||||
>
|
||||
<div class="card-content">
|
||||
@@ -232,32 +269,74 @@ const stripePayment = {
|
||||
</div>
|
||||
<div class="media-content">
|
||||
<p class="title is-4">E-conomic</p>
|
||||
<p class="subtitle is-6">Brug E-conomic til at oprette fakturaer</p>
|
||||
<p class="subtitle is-6">Use E-conomic to book the paid Stripe invoice.</p>
|
||||
<div
|
||||
v-if="stripeTransferTransportErrorMessage"
|
||||
class="notification is-danger is-light mt-3"
|
||||
data-testid="collected-stripe-transport-error"
|
||||
>
|
||||
{{ stripeTransferTransportErrorMessage }}
|
||||
</div>
|
||||
<div
|
||||
v-else-if="isStripeTransferQueuedOrProcessing"
|
||||
class="mt-3"
|
||||
data-testid="collected-stripe-progress"
|
||||
>
|
||||
<p class="is-size-7 has-text-grey">
|
||||
{{ stripeTransferProgressMessage || SessionUser.objects.global.language.processing }}
|
||||
</p>
|
||||
<progress
|
||||
class="progress is-link is-small"
|
||||
max="100"
|
||||
:value="stripeTransferProgressPercent"
|
||||
></progress>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="isStripeTransferCompleted"
|
||||
class="notification is-success is-light mt-3"
|
||||
data-testid="collected-stripe-completed"
|
||||
>
|
||||
<p class="has-text-weight-semibold">{{ SessionUser.objects.global.language.succeeded }}</p>
|
||||
<p v-if="stripeTransferResultMessage">{{ stripeTransferResultMessage }}</p>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="isStripeTransferFailed"
|
||||
class="notification is-danger is-light mt-3"
|
||||
data-testid="collected-stripe-failed"
|
||||
>
|
||||
<p>{{ stripeTransferFailureMessage || SessionUser.objects.global.language.failed }}</p>
|
||||
<button
|
||||
class="button is-small is-danger is-light mt-2"
|
||||
:disabled="isStripeTransferBusy"
|
||||
data-testid="collected-stripe-retry"
|
||||
@click="onRetryStripeTransfer"
|
||||
>
|
||||
{{ SessionUser.objects.global.language.retry }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Confirm button -->
|
||||
<div class="media-right">
|
||||
<div class="buttons">
|
||||
<button
|
||||
class="button is-small is-light"
|
||||
@click="onBookStripeInvoice"
|
||||
class="button is-small is-light"
|
||||
:disabled="isStripeTransferBusy"
|
||||
data-testid="collected-stripe-book-invoice"
|
||||
@click="onBookStripeInvoice"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-file-invoice-dollar"></i>
|
||||
</span>
|
||||
<span>Bogfør faktura</span>
|
||||
<span>Book invoice</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- If the invoice is not paid -->
|
||||
<div v-else>
|
||||
<p>TEST 1234</p>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
+3
@@ -120,6 +120,9 @@ watch(
|
||||
<div class="columns is-mobile">
|
||||
<div class="column is-half">
|
||||
<SelfServeMachineStatus :machineStatus="departmentSelfServeEnabled ? 'ON' : 'OFF'" />
|
||||
<p class="is-size-7 has-text-grey mt-1" data-testid="department-self-serve-status-label">
|
||||
{{ departmentSelfServeStatusLabel }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="column is-half">
|
||||
<b-switch
|
||||
|
||||
@@ -245,6 +245,7 @@ describe("economic transfer queue workflow", () => {
|
||||
jobs: [4001, 4002],
|
||||
limit: 10,
|
||||
transfer_type: "COLLECTED_INVOICE_EXPORT",
|
||||
fallback: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -23,6 +23,10 @@ const posState = vi.hoisted(() => ({
|
||||
clearSelectedOrderBookingSelection: vi.fn(),
|
||||
skipSelectedOrderBookingSelection: vi.fn(),
|
||||
isSelectedOrderBookingSkippedForPlate: vi.fn(() => false),
|
||||
doesVehiclePlateRequireBookingSelection: vi.fn(() => false),
|
||||
getSelectedVehiclePlateBooking: vi.fn(() => null),
|
||||
loadPendingBookings: vi.fn(async () => []),
|
||||
ensureVehiclePlateBookingsLoaded: vi.fn(async () => []),
|
||||
}));
|
||||
|
||||
vi.mock("@/components/shop/POSDepartmentProcess.vue", async () => {
|
||||
@@ -67,6 +71,10 @@ vi.mock("@/components/shop/POSDepartmentProcess.vue", async () => {
|
||||
clearSelectedOrderBookingSelection: posState.clearSelectedOrderBookingSelection,
|
||||
skipSelectedOrderBookingSelection: posState.skipSelectedOrderBookingSelection,
|
||||
isSelectedOrderBookingSkippedForPlate: posState.isSelectedOrderBookingSkippedForPlate,
|
||||
doesVehiclePlateRequireBookingSelection: posState.doesVehiclePlateRequireBookingSelection,
|
||||
getSelectedVehiclePlateBooking: posState.getSelectedVehiclePlateBooking,
|
||||
loadPendingBookings: posState.loadPendingBookings,
|
||||
ensureVehiclePlateBookingsLoaded: posState.ensureVehiclePlateBookingsLoaded,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -265,6 +273,13 @@ describe("SelectVehicleFormPOS", () => {
|
||||
posState.skipSelectedOrderBookingSelection.mockClear();
|
||||
posState.isSelectedOrderBookingSkippedForPlate.mockReset();
|
||||
posState.isSelectedOrderBookingSkippedForPlate.mockReturnValue(false);
|
||||
posState.doesVehiclePlateRequireBookingSelection.mockReset();
|
||||
posState.doesVehiclePlateRequireBookingSelection.mockReturnValue(false);
|
||||
posState.getSelectedVehiclePlateBooking.mockReset();
|
||||
posState.getSelectedVehiclePlateBooking.mockReturnValue(null);
|
||||
posState.loadPendingBookings.mockClear();
|
||||
posState.ensureVehiclePlateBookingsLoaded.mockReset();
|
||||
posState.ensureVehiclePlateBookingsLoaded.mockResolvedValue([]);
|
||||
});
|
||||
|
||||
it("shows a single inline customer selector before a vehicle is linked", () => {
|
||||
|
||||
Reference in New Issue
Block a user