5241-virtual_pos #44
|
@ -9,7 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added...
|
- (Clientes) => Añadida nueva sección "Pagos Web" para gestionar los pagos de todos los clientes
|
||||||
|
- (Tickets) => Añadida opción en el menú desplegable del ticket para enviar SMS al cliente
|
||||||
|
- (Reclamaciones) => Añadida nueva sección "Registros de auditoría"
|
||||||
|
- (Trabajadores) => Añadido módulo de trabajadores
|
||||||
|
|||||||
|
- (General) => Añadida barra de búsqueda general en los listados principales
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"assets/*": ["src/assets/*"],
|
"assets/*": ["src/assets/*"],
|
||||||
"boot/*": ["src/boot/*"],
|
"boot/*": ["src/boot/*"],
|
||||||
"stores/*": ["src/stores/*"],
|
"stores/*": ["src/stores/*"],
|
||||||
|
"filters/*": ["src/filters/*"],
|
||||||
"vue$": ["node_modules/vue/dist/vue.runtime.esm-bundler.js"]
|
"vue$": ["node_modules/vue/dist/vue.runtime.esm-bundler.js"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -141,8 +141,11 @@ function formatValue(value) {
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item>
|
<q-item>
|
||||||
<div v-if="tags.length === 0" class="text-grey centered font-xs">
|
<div
|
||||||
{{ t(`You didn't enter any filter`) }}
|
v-if="tags.length === 0"
|
||||||
|
class="text-grey font-xs text-center full-width"
|
||||||
|
>
|
||||||
|
{{ t(`No filters applied`) }}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<q-chip
|
<q-chip
|
||||||
|
@ -194,7 +197,7 @@ function formatValue(value) {
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
You didn't enter any filter: No has introducido ningún filtro
|
No filters applied: No se han aplicado filtros
|
||||||
alexandre marked this conversation as resolved
alexandre
commented
No seria millor posar les traduccions en els fitxers src/i18n/en/index.js i src/i18n/es/index.js? No seria millor posar les traduccions en els fitxers *src/i18n/en/index.js* i *src/i18n/es/index.js*?
|
|||||||
Applied filters: Filtros aplicados
|
Applied filters: Filtros aplicados
|
||||||
Remove filters: Eliminar filtros
|
Remove filters: Eliminar filtros
|
||||||
Refresh: Refrescar
|
Refresh: Refrescar
|
||||||
|
|
|
@ -51,14 +51,7 @@ const props = defineProps({
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const arrayData = useArrayData(props.dataKey, {
|
const arrayData = useArrayData(props.dataKey, { ...props });
|
||||||
url: props.url,
|
|
||||||
filter: props.filter,
|
|
||||||
where: props.where,
|
|
||||||
limit: props.limit,
|
|
||||||
order: props.order,
|
|
||||||
userParams: props.userParams,
|
|
||||||
});
|
|
||||||
const store = arrayData.store;
|
const store = arrayData.store;
|
||||||
const searchText = ref('');
|
const searchText = ref('');
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,20 @@ export function useArrayData(key, userOptions) {
|
||||||
});
|
});
|
||||||
|
|
||||||
function setOptions() {
|
function setOptions() {
|
||||||
|
const allowedOptions = [
|
||||||
|
'url',
|
||||||
|
'filter',
|
||||||
|
'where',
|
||||||
|
'order',
|
||||||
|
'limit',
|
||||||
|
'skip',
|
||||||
|
'userParams',
|
||||||
|
'userFilter'
|
||||||
|
];
|
||||||
if (typeof userOptions === 'object') {
|
if (typeof userOptions === 'object') {
|
||||||
for (const option in userOptions) {
|
for (const option in userOptions) {
|
||||||
if (userOptions[option] == null) continue;
|
const isEmpty = userOptions[option] == null || userOptions[option] == ''
|
||||||
|
if (isEmpty || !allowedOptions.includes(option)) continue;
|
||||||
|
|
||||||
if (Object.prototype.hasOwnProperty.call(store, option)) {
|
if (Object.prototype.hasOwnProperty.call(store, option)) {
|
||||||
store[option] = userOptions[option];
|
store[option] = userOptions[option];
|
||||||
|
@ -62,6 +73,7 @@ export function useArrayData(key, userOptions) {
|
||||||
|
|
||||||
Object.assign(params, store.userParams);
|
Object.assign(params, store.userParams);
|
||||||
|
|
||||||
|
store.isLoading = true
|
||||||
const response = await axios.get(store.url, {
|
const response = await axios.get(store.url, {
|
||||||
signal: canceller.signal,
|
signal: canceller.signal,
|
||||||
params,
|
params,
|
||||||
|
@ -82,6 +94,8 @@ export function useArrayData(key, userOptions) {
|
||||||
updateStateParams();
|
updateStateParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
store.isLoading = false
|
||||||
|
|
||||||
canceller = null;
|
canceller = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +153,8 @@ export function useArrayData(key, userOptions) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalRows = computed(() => store.data && store.data.length | 0);
|
const totalRows = computed(() => store.data && store.data.length || 0);
|
||||||
|
const isLoading = computed(() => store.isLoading || false)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fetch,
|
fetch,
|
||||||
|
@ -152,5 +167,6 @@ export function useArrayData(key, userOptions) {
|
||||||
hasMoreData,
|
hasMoreData,
|
||||||
totalRows,
|
totalRows,
|
||||||
updateStateParams,
|
updateStateParams,
|
||||||
|
isLoading
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ export default {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
customers: 'Customers',
|
customers: 'Customers',
|
||||||
list: 'List',
|
list: 'List',
|
||||||
|
webPayments: 'Web Payments',
|
||||||
createCustomer: 'Create customer',
|
createCustomer: 'Create customer',
|
||||||
summary: 'Summary',
|
summary: 'Summary',
|
||||||
basicData: 'Basic Data',
|
basicData: 'Basic Data',
|
||||||
|
|
|
@ -60,9 +60,10 @@ export default {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
customers: 'Clientes',
|
customers: 'Clientes',
|
||||||
list: 'Listado',
|
list: 'Listado',
|
||||||
|
webPayments: 'Pagos Web',
|
||||||
createCustomer: 'Crear cliente',
|
createCustomer: 'Crear cliente',
|
||||||
summary: 'Resumen',
|
|
||||||
basicData: 'Datos básicos',
|
basicData: 'Datos básicos',
|
||||||
|
summary: 'Resumen'
|
||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
phone: 'Teléfono',
|
phone: 'Teléfono',
|
||||||
|
|
|
@ -0,0 +1,294 @@
|
||||||
|
<script setup>
|
||||||
|
import axios from 'axios';
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
|
import Paginate from 'components/PaginateData.vue';
|
||||||
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
|
import CustomerDescriptorProxy from './Card/CustomerDescriptorProxy.vue';
|
||||||
|
import { toDate, toCurrency } from 'filters/index';
|
||||||
|
import CustomerPaymentsFilter from './CustomerPaymentsFilter.vue';
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const quasar = useQuasar();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const arrayData = useArrayData('CustomerTransactions');
|
||||||
|
|
||||||
|
async function confirm(transaction) {
|
||||||
|
quasar
|
||||||
|
.dialog({
|
||||||
|
component: VnConfirm,
|
||||||
|
componentProps: {
|
||||||
|
data: transaction,
|
||||||
|
title: t('Confirm transaction'),
|
||||||
|
promise: confirmTransaction,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.onOk((row) => (row.isConfirmed = true));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function confirmTransaction({ id }) {
|
||||||
alexandre
commented
és correcte passar-li com a parametre el id dins de claus? és correcte passar-li com a parametre el id dins de claus?
joan
commented
Si, el parámetre que li arriva es un objecte data, i ahí el que estic fent es desestructurar el objecte per a extraure directament les propietats Igual com fer
Si, el parámetre que li arriva es un objecte data, i ahí el que estic fent es desestructurar el objecte per a extraure directament les propietats
Igual com fer
`const { id } = data`
|
|||||||
|
await axios.post('Clients/confirmTransaction', { id });
|
||||||
|
quasar.notify({
|
||||||
|
message: t('Payment confirmed'),
|
||||||
|
type: 'positive',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const grid = ref(false);
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
label: t('Transaction ID'),
|
||||||
|
field: (row) => row.id,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'customerId',
|
||||||
|
label: t('Customer ID'),
|
||||||
|
field: (row) => row.clientFk,
|
||||||
|
align: 'right',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'customer',
|
||||||
|
label: t('Customer Name'),
|
||||||
|
field: (row) => row.customerName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'state',
|
||||||
|
label: t('State'),
|
||||||
|
field: (row) => row.isConfirmed,
|
||||||
|
format: (value) => (value ? t('Confirmed') : t('Unconfirmed')),
|
||||||
|
align: 'left',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'dated',
|
||||||
|
label: t('Dated'),
|
||||||
|
field: (row) => toDate(row.created),
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'amount',
|
||||||
|
label: t('Amount'),
|
||||||
|
field: (row) => row.amount,
|
||||||
|
format: (value) => toCurrency(value),
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'actions',
|
||||||
|
label: t('Actions'),
|
||||||
|
grid: false,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const isLoading = computed(() => arrayData.isLoading.value);
|
||||||
|
|
||||||
|
function stateColor(row) {
|
||||||
|
if (row.isConfirmed) return 'positive';
|
||||||
|
return 'primary';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<template v-if="stateStore.isHeaderMounted()">
|
||||||
|
<Teleport to="#actions-append">
|
||||||
|
<div class="row q-gutter-x-sm">
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
@click="stateStore.toggleRightDrawer()"
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
icon="menu"
|
||||||
|
>
|
||||||
|
<q-tooltip bottom anchor="bottom right">
|
||||||
|
{{ t('globals.collapseMenu') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
|
<q-drawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
|
<q-scroll-area class="fit text-grey-8">
|
||||||
|
<CustomerPaymentsFilter data-key="CustomerTransactions" />
|
||||||
|
</q-scroll-area>
|
||||||
|
</q-drawer>
|
||||||
|
<q-page class="column items-center q-pa-md">
|
||||||
|
<div class="card-list">
|
||||||
|
<q-toolbar class="q-pa-none">
|
||||||
|
<q-toolbar-title>{{ t('Web Payments') }}</q-toolbar-title>
|
||||||
|
<q-btn
|
||||||
|
@click="arrayData.refresh()"
|
||||||
|
:loading="isLoading"
|
||||||
|
icon="refresh"
|
||||||
|
color="primary"
|
||||||
|
class="q-mr-sm"
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
></q-btn>
|
||||||
|
<q-btn @click="grid = !grid" icon="list" color="primary" round dense>
|
||||||
|
<q-tooltip>{{ t('Change view') }}</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</q-toolbar>
|
||||||
|
<paginate
|
||||||
|
data-key="CustomerTransactions"
|
||||||
|
url="Clients/transactions"
|
||||||
|
order="created DESC"
|
||||||
|
:limit="20"
|
||||||
|
:offset="50"
|
||||||
|
auto-load
|
||||||
|
>
|
||||||
|
<template #body="{ rows }">
|
||||||
|
<q-table
|
||||||
|
:dense="$q.screen.lt.md"
|
||||||
|
:columns="columns"
|
||||||
|
:rows="rows"
|
||||||
|
row-key="id"
|
||||||
|
:pagination="{ rowsPerPage: 0 }"
|
||||||
|
:grid="grid || $q.screen.lt.sm"
|
||||||
|
class="q-mt-xs"
|
||||||
|
hide-pagination
|
||||||
|
>
|
||||||
|
<template #body-cell-actions="{ row }">
|
||||||
|
<q-td auto-width class="text-center">
|
||||||
|
<q-btn
|
||||||
|
v-if="!row.isConfirmed"
|
||||||
|
icon="check"
|
||||||
|
@click="confirm(row)"
|
||||||
|
color="primary"
|
||||||
|
size="md"
|
||||||
|
round
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
>
|
||||||
|
<q-tooltip>{{ t('Confirm transaction') }}</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</q-td>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-customerId="{ row }">
|
||||||
|
<q-td align="right">
|
||||||
|
<span class="link">
|
||||||
|
{{ row.clientFk }}
|
||||||
|
<CustomerDescriptorProxy :id="row.clientFk" />
|
||||||
|
</span>
|
||||||
|
</q-td>
|
||||||
|
</template>
|
||||||
|
<template #body-cell-state="{ row }">
|
||||||
|
<q-td auto-width class="text-center">
|
||||||
|
<q-badge :color="stateColor(row)">
|
||||||
|
{{
|
||||||
|
row.isConfirmed
|
||||||
|
? t('Confirmed')
|
||||||
|
: t('Unconfirmed')
|
||||||
|
}}
|
||||||
|
</q-badge>
|
||||||
|
</q-td>
|
||||||
|
</template>
|
||||||
|
<template #item="{ cols, row }">
|
||||||
|
<div class="q-mb-md col-12">
|
||||||
|
<q-card>
|
||||||
|
<q-item class="q-pa-none items-start">
|
||||||
|
<q-item-section class="q-pa-md">
|
||||||
|
<q-list>
|
||||||
|
<template
|
||||||
|
v-for="col of cols"
|
||||||
|
:key="col.name"
|
||||||
|
>
|
||||||
|
<q-item
|
||||||
|
v-if="col.grid !== false"
|
||||||
|
class="q-pa-none"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ col.label }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label
|
||||||
|
v-if="col.name == 'state'"
|
||||||
|
>
|
||||||
|
<q-badge
|
||||||
|
:color="
|
||||||
|
stateColor(row)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ col.value }}
|
||||||
|
</q-badge>
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label
|
||||||
|
v-if="col.name != 'state'"
|
||||||
|
>
|
||||||
|
{{ col.value }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</template>
|
||||||
|
</q-list>
|
||||||
|
<!-- <q-list>
|
||||||
|
<q-item class="q-pa-none">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
<q-skeleton />
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label
|
||||||
|
><q-skeleton type="text"
|
||||||
|
/></q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list> -->
|
||||||
|
</q-item-section>
|
||||||
|
<template v-if="!row.isConfirmed">
|
||||||
|
<q-separator vertical />
|
||||||
|
<q-card-actions
|
||||||
|
vertical
|
||||||
|
class="justify-between"
|
||||||
|
>
|
||||||
|
<q-btn
|
||||||
|
icon="check"
|
||||||
|
@click="confirm(row)"
|
||||||
|
color="primary"
|
||||||
|
size="md"
|
||||||
|
round
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
>
|
||||||
|
<q-tooltip>{{
|
||||||
|
t('Confirm transaction')
|
||||||
|
}}</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</q-card-actions>
|
||||||
|
</template>
|
||||||
|
</q-item>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</template>
|
||||||
|
</paginate>
|
||||||
|
</div>
|
||||||
|
</q-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card-list {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 60em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Web Payments: Pagos Web
|
||||||
|
Confirm transaction: Confirmar transacción
|
||||||
|
Transaction ID: ID transacción
|
||||||
|
Customer ID: ID cliente
|
||||||
|
Customer Name: Nombre cliente
|
||||||
|
State: Estado
|
||||||
|
Dated: Fecha
|
||||||
|
Amount: Importe
|
||||||
|
Actions: Acciones
|
||||||
|
Confirmed: Confirmada
|
||||||
|
Unconfirmed: Sin confirmar
|
||||||
|
Change view: Cambiar vista
|
||||||
|
Payment confirmed: Pago confirmado
|
||||||
|
</i18n>
|
|
@ -0,0 +1,78 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const props = defineProps({
|
||||||
|
dataKey: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
|
||||||
|
<template #tags="{ tag, formatFn }">
|
||||||
|
<div class="q-gutter-x-xs">
|
||||||
|
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
||||||
|
<span>{{ formatFn(tag.value) }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #body="{ params }">
|
||||||
|
<q-list dense>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-input
|
||||||
|
:label="t('Order ID')"
|
||||||
|
v-model="params.orderFk"
|
||||||
|
lazy-rules
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<q-icon name="vn:basket" size="sm"></q-icon>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-input
|
||||||
|
:label="t('Customer ID')"
|
||||||
|
v-model="params.clientFk"
|
||||||
|
lazy-rules
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<q-icon name="vn:client" size="sm"></q-icon>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-input :label="t('Amount')" v-model="params.amount" lazy-rules>
|
||||||
|
<template #prepend>
|
||||||
|
<q-icon name="euro" size="sm"></q-icon>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</template>
|
||||||
|
</VnFilterPanel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
en:
|
||||||
|
params:
|
||||||
|
orderFk: Order
|
||||||
|
clientFk: Customer
|
||||||
|
amount: Amount
|
||||||
|
es:
|
||||||
|
params:
|
||||||
|
orderFk: Pedido
|
||||||
|
clientFk: Cliente
|
||||||
|
amount: Importe
|
||||||
|
Order ID: ID pedido
|
||||||
|
Customer ID: ID cliente
|
||||||
|
Amount: Importe
|
||||||
|
</i18n>
|
|
@ -10,7 +10,7 @@ export default {
|
||||||
component: RouterView,
|
component: RouterView,
|
||||||
redirect: { name: 'CustomerMain' },
|
redirect: { name: 'CustomerMain' },
|
||||||
menus: {
|
menus: {
|
||||||
main: ['CustomerList', 'CustomerCreate'],
|
main: ['CustomerList', 'CustomerPayments', 'CustomerCreate'],
|
||||||
card: ['CustomerBasicData'],
|
card: ['CustomerBasicData'],
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
@ -29,6 +29,15 @@ export default {
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Customer/CustomerList.vue')
|
component: () => import('src/pages/Customer/CustomerList.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'payments',
|
||||||
|
name: 'CustomerPayments',
|
||||||
|
meta: {
|
||||||
|
title: 'webPayments',
|
||||||
|
icon: 'vn:onlinepayment',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Customer/CustomerPayments.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'create',
|
path: 'create',
|
||||||
name: 'CustomerCreate',
|
name: 'CustomerCreate',
|
||||||
|
|
|
@ -18,6 +18,7 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
|
||||||
skip: 0,
|
skip: 0,
|
||||||
order: '',
|
order: '',
|
||||||
data: ref(),
|
data: ref(),
|
||||||
|
isLoading: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
|
||||||
|
import { createWrapper, axios } from 'app/test/vitest/helper';
|
||||||
|
import CustomerPayments from 'pages/Customer/CustomerPayments.vue';
|
||||||
|
|
||||||
|
describe('CustomerPayments', () => {
|
||||||
|
let vm;
|
||||||
|
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
vm = createWrapper(CustomerPayments, {
|
||||||
|
global: {
|
||||||
|
stubs: ['Paginate'],
|
||||||
|
mocks: {
|
||||||
|
fetch: vi.fn(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}).vm;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('confirmTransaction()', () => {
|
||||||
|
it('should make a POST request and then call to quasar notify method', async () => {
|
||||||
|
vi.spyOn(axios, 'post').mockResolvedValue({ data: true });
|
||||||
|
vi.spyOn(vm.quasar, 'notify');
|
||||||
|
|
||||||
|
await vm.confirmTransaction({ id: 1 });
|
||||||
|
|
||||||
|
|
||||||
|
expect(vm.quasar.notify).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
message: 'Payment confirmed',
|
||||||
|
type: 'positive'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('stateColor()', () => {
|
||||||
|
it('should return "positive" when isConfirmed property is truthy', async () => {
|
||||||
|
const result = await vm.stateColor({ isConfirmed: true });
|
||||||
|
|
||||||
|
expect(result).toEqual('positive');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return "primary" when isConfirmed property is falsy', async () => {
|
||||||
|
const result = await vm.stateColor({ isConfirmed: false });
|
||||||
|
|
||||||
|
expect(result).toEqual('primary');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Llevar accent en añadido