Resolve conflicts
This commit is contained in:
commit
b19bf710e8
16
src/App.vue
16
src/App.vue
|
@ -1,11 +1,11 @@
|
|||
<script setup>
|
||||
import { useAppStore } from 'stores/app';
|
||||
import { onBeforeMount } from 'vue';
|
||||
const appStore = useAppStore();
|
||||
|
||||
onBeforeMount(() => appStore.init());
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'App'
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -206,7 +206,6 @@ defineExpose({
|
|||
ref="addressFormRef"
|
||||
class="form"
|
||||
:class="separationBetweenInputs"
|
||||
@submit="submit()"
|
||||
>
|
||||
<span v-if="title" class="text-h6 text-bold">
|
||||
{{ title }}
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { currency, formatDateTitle } from 'src/lib/filters.js';
|
||||
import VnImg from 'src/components/ui/VnImg.vue';
|
||||
|
||||
defineProps({
|
||||
ticket: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
rows: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const lineDiscountSubtotal = line => {
|
||||
return line.quantity * line.price;
|
||||
};
|
||||
|
||||
const lineSubtotal = line =>
|
||||
lineDiscountSubtotal(line) * ((100 - line.discount) / 100);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QCard class="vn-w-sm" style="padding: 32px">
|
||||
<QCardSection class="no-padding q-mb-md">
|
||||
<div class="text-h6">#{{ ticket.id }}</div>
|
||||
</QCardSection>
|
||||
<QCardSection class="no-padding q-mb-md q-gutter-y-xs">
|
||||
<div class="text-subtitle1 text-bold">
|
||||
{{ t('shippingInformation') }}
|
||||
</div>
|
||||
<div>
|
||||
{{ t('preparation') }}
|
||||
{{ formatDateTitle(ticket.shipped) }}
|
||||
</div>
|
||||
<div>
|
||||
{{ t('delivery') }}
|
||||
{{ formatDateTitle(ticket.landed) }}
|
||||
</div>
|
||||
<div>
|
||||
{{ t(ticket.method != 'PICKUP' ? 'agency' : 'warehouse') }}
|
||||
{{ ticket.agency }}
|
||||
</div>
|
||||
</QCardSection>
|
||||
<QCardSection class="no-padding q-mb-md q-gutter-y-xs">
|
||||
<div class="text-subtitle1 text-bold">
|
||||
{{ t('deliveryAddress') }}
|
||||
</div>
|
||||
<div>{{ ticket.nickname }}</div>
|
||||
<div>{{ ticket.street }}</div>
|
||||
<div>
|
||||
{{ ticket.postalCode }} {{ ticket.city }} ({{
|
||||
ticket.province
|
||||
}})
|
||||
</div>
|
||||
</QCardSection>
|
||||
<QCardSection
|
||||
class="no-padding q-mb-md text-subtitle1 text-bold column"
|
||||
>
|
||||
<span class="text-right">
|
||||
{{ t('total') }} {{ currency(ticket.taxBase) }}
|
||||
</span>
|
||||
<span class="text-right">
|
||||
{{ t('totalTax') }} {{ currency(ticket.total) }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QSeparator inset />
|
||||
<QList v-for="row in rows" :key="row.itemFk">
|
||||
<QItem>
|
||||
<QItemSection avatar>
|
||||
<VnImg
|
||||
storage="catalog"
|
||||
size="200x200"
|
||||
:id="row.image"
|
||||
rounded
|
||||
/>
|
||||
</QItemSection>
|
||||
<QItemSection>
|
||||
<QItemLabel lines="1">
|
||||
{{ row.concept }}
|
||||
</QItemLabel>
|
||||
<QItemLabel lines="1" caption>
|
||||
{{ row.value5 }} {{ row.value6 }} {{ row.value7 }}
|
||||
</QItemLabel>
|
||||
<QItemLabel lines="1">
|
||||
{{ row.quantity }} x {{ currency(row.price) }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
<QItemSection side class="total">
|
||||
<QItemLabel>
|
||||
<span class="discount" v-if="row.discount">
|
||||
{{ currency(lineDiscountSubtotal(row)) }} -
|
||||
{{ currency(row.discount) }} =
|
||||
</span>
|
||||
{{ currency(lineSubtotal(row)) }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</QList>
|
||||
</QCard>
|
||||
</template>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en-US:
|
||||
shippingInformation: Shipping Information
|
||||
preparation: Preparation
|
||||
delivery: Delivery
|
||||
agency: Agency
|
||||
warehouse: Store
|
||||
deliveryAddress: Delivery address
|
||||
total: Total
|
||||
totalTax: Total + IVA
|
||||
es-ES:
|
||||
shippingInformation: Datos de envío
|
||||
preparation: Preparación
|
||||
delivery: Entrega
|
||||
agency: Agencia
|
||||
warehouse: Almacén
|
||||
deliveryAddress: Dirección de entrega
|
||||
total: Total
|
||||
totalTax: Total + IVA
|
||||
ca-ES:
|
||||
shippingInformation: Dades d'enviament
|
||||
preparation: Preparació
|
||||
delivery: Lliurament
|
||||
agency: Agència
|
||||
warehouse: Magatzem
|
||||
deliveryAddress: Adreça de lliurament
|
||||
total: Total
|
||||
totalTax: Total + IVA
|
||||
fr-FR:
|
||||
shippingInformation: Informations sur la livraison
|
||||
preparation: Préparation
|
||||
delivery: Livraison
|
||||
warehouse: Entrepôt
|
||||
deliveryAddress: Adresse de livraison
|
||||
total: Total
|
||||
totalTax: Total + IVA
|
||||
pt-PT:
|
||||
shippingInformation: Dados de envio
|
||||
preparation: Preparação
|
||||
delivery: Entrega
|
||||
agency: Agência
|
||||
warehouse: Armazém
|
||||
deliveryAddress: Endereço de entrega
|
||||
total: Total
|
||||
totalTax: Total + IVA
|
||||
</i18n>
|
|
@ -0,0 +1,41 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps({
|
||||
noDataLabel: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
hideBottom: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
rowsPerPageOptions: {
|
||||
type: Array,
|
||||
default: () => [0]
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QTable
|
||||
v-bind="$attrs"
|
||||
:no-data-label="props.noDataLabel || t('noInvoicesFound')"
|
||||
:hide-bottom="props.hideBottom"
|
||||
:rows-per-page-options="props.rowsPerPageOptions"
|
||||
table-header-class="vntable-header-default"
|
||||
>
|
||||
<template v-for="(_, slotName) in $slots" v-slot:[slotName]="slotProps">
|
||||
<slot :name="slotName" v-bind="slotProps" />
|
||||
</template>
|
||||
</QTable>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.vntable-header-default {
|
||||
background-color: $accent !important;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,38 @@
|
|||
import { useUserStore } from 'stores/user';
|
||||
|
||||
import axios from 'axios';
|
||||
import { useQuasar } from 'quasar';
|
||||
|
||||
export function usePrintService() {
|
||||
const quasar = useQuasar();
|
||||
const userStore = useUserStore();
|
||||
const token = userStore.token;
|
||||
|
||||
function sendEmail(path, params) {
|
||||
return axios.post(path, params).then(() =>
|
||||
quasar.notify({
|
||||
message: 'Notification sent',
|
||||
type: 'positive',
|
||||
icon: 'check'
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function openReport(path, params) {
|
||||
params = Object.assign(
|
||||
{
|
||||
access_token: token
|
||||
},
|
||||
params
|
||||
);
|
||||
|
||||
const query = new URLSearchParams(params).toString();
|
||||
|
||||
window.open(`api/${path}?${query}`);
|
||||
}
|
||||
|
||||
return {
|
||||
sendEmail,
|
||||
openReport
|
||||
};
|
||||
}
|
|
@ -37,7 +37,7 @@ export default {
|
|||
'November',
|
||||
'December'
|
||||
],
|
||||
shortMonths: [
|
||||
monthsShort: [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
|
|
|
@ -43,7 +43,7 @@ export default {
|
|||
'Noviembre',
|
||||
'Diciembre'
|
||||
],
|
||||
shortMonths: [
|
||||
monthsShort: [
|
||||
'Ene',
|
||||
'Feb',
|
||||
'Mar',
|
||||
|
|
|
@ -24,7 +24,7 @@ export default {
|
|||
'Novembre',
|
||||
'Décembre'
|
||||
],
|
||||
shortMonths: [
|
||||
monthsShort: [
|
||||
'Jan',
|
||||
'Fév',
|
||||
'Mar',
|
||||
|
|
|
@ -24,7 +24,7 @@ export default {
|
|||
'Novembro',
|
||||
'Dezembro'
|
||||
],
|
||||
shortMonths: [
|
||||
monthsShort: [
|
||||
'Jan',
|
||||
'Fev',
|
||||
'Mar',
|
||||
|
|
|
@ -3,6 +3,8 @@ import { useI18n } from 'vue-i18n';
|
|||
import { ref, onMounted, inject } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import CardList from 'src/components/ui/CardList.vue';
|
||||
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { useVnConfirm } from 'src/composables/useVnConfirm.js';
|
||||
import { useAppStore } from 'stores/app';
|
||||
|
@ -97,42 +99,33 @@ onMounted(async () => {
|
|||
no-caps
|
||||
/>
|
||||
</Teleport>
|
||||
<QPage class="column items-center">
|
||||
<QList
|
||||
class="full-width rounded-borders shadow-1 shadow-transition"
|
||||
style="max-width: 544px"
|
||||
separator
|
||||
>
|
||||
<QItem
|
||||
<QPage class="vn-w-sm">
|
||||
<QList class="rounded-borders shadow-1 shadow-transition" separator>
|
||||
<CardList
|
||||
v-for="(address, index) in addresses"
|
||||
:key="index"
|
||||
clickable
|
||||
v-ripple
|
||||
:rounded="false"
|
||||
tag="label"
|
||||
class="full-width row items-center justify-between address-item"
|
||||
style="padding: 20px"
|
||||
>
|
||||
<QItemSection>
|
||||
<div class="row">
|
||||
<QRadio
|
||||
v-model="defaultAddress"
|
||||
:val="address.id"
|
||||
class="q-mr-sm"
|
||||
@update:model-value="changeDefaultAddress"
|
||||
/>
|
||||
<div>
|
||||
<QItemLabel class="text-bold q-mb-sm">
|
||||
{{ address.nickname }}
|
||||
</QItemLabel>
|
||||
<QItemLabel>{{ address.street }}</QItemLabel>
|
||||
<QItemLabel>
|
||||
{{ address.postalCode }},
|
||||
{{ address.city }}
|
||||
</QItemLabel>
|
||||
</div>
|
||||
</div>
|
||||
</QItemSection>
|
||||
<QItemSection class="actions-wrapper" side>
|
||||
<template #prepend>
|
||||
<QRadio
|
||||
v-model="defaultAddress"
|
||||
:val="address.id"
|
||||
class="q-mr-sm"
|
||||
@update:model-value="changeDefaultAddress"
|
||||
/>
|
||||
</template>
|
||||
<template #content>
|
||||
<span class="text-bold q-mb-sm">
|
||||
{{ address.nickname }}
|
||||
</span>
|
||||
<span>{{ address.street }}</span>
|
||||
<span>
|
||||
{{ address.postalCode }},
|
||||
{{ address.city }}
|
||||
</span>
|
||||
</template>
|
||||
<template #actions>
|
||||
<QBtn
|
||||
icon="delete"
|
||||
flat
|
||||
|
@ -151,25 +144,12 @@ onMounted(async () => {
|
|||
rounded
|
||||
@click.stop="goToAddressDetails(address.id)"
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</CardList>
|
||||
</QList>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.address-item {
|
||||
.actions-wrapper {
|
||||
visibility: hidden;
|
||||
}
|
||||
&:hover {
|
||||
.actions-wrapper {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en-US:
|
||||
addAddress: Add address
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
import { ref, inject, onMounted, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import VnTable from 'src/components/ui/VnTable.vue';
|
||||
|
||||
const jApi = inject('jApi');
|
||||
const { t } = useI18n();
|
||||
|
||||
|
@ -53,32 +55,15 @@ onMounted(() => getPackages());
|
|||
|
||||
<template>
|
||||
<QPage class="flex justify-center q-pa-md">
|
||||
<QTable
|
||||
<VnTable
|
||||
:columns="columns"
|
||||
:rows="packages"
|
||||
:loading="loading"
|
||||
class="q-mt-lg"
|
||||
style="max-width: 100%; height: max-content"
|
||||
table-header-class="packages-table-header"
|
||||
hide-bottom
|
||||
>
|
||||
<template #body-cell-id="{ row }">
|
||||
<QTd auto-width @click.stop>
|
||||
<QBtn flat color="blue">{{ row.id }}</QBtn>
|
||||
<ItemDescriptorProxy :id="row.id" />
|
||||
</QTd>
|
||||
</template>
|
||||
</QTable>
|
||||
style="height: max-content; max-width: 100%"
|
||||
/>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.packages-table-header {
|
||||
background-color: $accent !important;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en-US:
|
||||
agency: Agency
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<template>Basket view</template>
|
|
@ -10,7 +10,7 @@
|
|||
dense
|
||||
standout
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<template #prepend>
|
||||
<QIcon v-if="search === ''" name="search" />
|
||||
<QIcon
|
||||
v-else
|
||||
|
@ -220,7 +220,7 @@
|
|||
</QCardActions>
|
||||
</QCard>
|
||||
</div>
|
||||
<template v-slot:loading>
|
||||
<template #loading>
|
||||
<div class="row justify-center q-my-md">
|
||||
<QSpinner color="primary" name="dots" size="40px" />
|
||||
</div>
|
||||
|
@ -343,8 +343,7 @@
|
|||
</style>
|
||||
|
||||
<script>
|
||||
import { date, currency } from 'src/lib/filters.js';
|
||||
import { date as qdate } from 'quasar';
|
||||
import { date, currency, formatDate } from 'src/lib/filters.js';
|
||||
import axios from 'axios';
|
||||
import { useAppStore } from 'stores/app';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
@ -362,7 +361,7 @@ export default {
|
|||
return {
|
||||
uid: 0,
|
||||
search: '',
|
||||
orderDate: qdate.formatDate(new Date(), 'YYYY/MM/DD'),
|
||||
orderDate: formatDate(new Date(), 'YYYY/MM/DD'),
|
||||
category: null,
|
||||
categories: [],
|
||||
type: null,
|
||||
|
@ -453,7 +452,7 @@ export default {
|
|||
if (!value) return;
|
||||
|
||||
const res = await this.$jApi.execQuery(
|
||||
`CALL myBasket_getAvailable;
|
||||
`CALL myOrder_getAvailable(${this.appStore.basketOrderId});
|
||||
SELECT DISTINCT t.id, l.name
|
||||
FROM vn.item i
|
||||
JOIN vn.itemType t ON t.id = i.typeFk
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<template>Checkout</template>
|
|
@ -1,190 +0,0 @@
|
|||
<template>
|
||||
<Teleport v-if="isHeaderMounted" to="#actions">
|
||||
<QSelect
|
||||
v-model="year"
|
||||
:options="years"
|
||||
color="white"
|
||||
dark
|
||||
standout
|
||||
dense
|
||||
rounded
|
||||
/>
|
||||
</Teleport>
|
||||
<div class="vn-w-sm">
|
||||
<div
|
||||
v-if="!invoices?.length"
|
||||
class="text-subtitle1 text-center text-grey-7 q-pa-md"
|
||||
>
|
||||
{{ $t('noInvoicesFound') }}
|
||||
</div>
|
||||
<QCard v-if="invoices?.length">
|
||||
<QTable
|
||||
:columns="columns"
|
||||
:pagination="pagination"
|
||||
:rows="invoices"
|
||||
row-key="id"
|
||||
hide-header
|
||||
hide-bottom
|
||||
>
|
||||
<template v-slot:body="props">
|
||||
<QTr :props="props">
|
||||
<QTd key="ref" :props="props">
|
||||
{{ props.row.ref }}
|
||||
</QTd>
|
||||
<QTd key="issued" :props="props">
|
||||
{{ date(props.row.issued, 'ddd, MMMM Do') }}
|
||||
</QTd>
|
||||
<QTd key="amount" :props="props">
|
||||
{{ currency(props.row.amount) }}
|
||||
</QTd>
|
||||
<QTd key="hasPdf" :props="props">
|
||||
<QBtn
|
||||
v-if="props.row.hasPdf"
|
||||
icon="download"
|
||||
:title="$t('downloadInvoicePdf')"
|
||||
:href="invoiceUrl(props.row.id)"
|
||||
target="_blank"
|
||||
flat
|
||||
round
|
||||
/>
|
||||
<QIcon
|
||||
v-else
|
||||
name="warning"
|
||||
:title="$t('notDownloadable')"
|
||||
color="warning"
|
||||
size="24px"
|
||||
/>
|
||||
</QTd>
|
||||
</QTr>
|
||||
</template>
|
||||
</QTable>
|
||||
</QCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { date, currency } from 'src/lib/filters.js';
|
||||
import { useAppStore } from 'stores/app';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
export default {
|
||||
name: 'OrdersPendingIndex',
|
||||
setup() {
|
||||
const appStore = useAppStore();
|
||||
const { isHeaderMounted } = storeToRefs(appStore);
|
||||
return { isHeaderMounted };
|
||||
},
|
||||
data() {
|
||||
const curYear = new Date().getFullYear();
|
||||
const years = [];
|
||||
|
||||
for (let year = curYear - 5; year <= curYear; year++) {
|
||||
years.push(year);
|
||||
}
|
||||
|
||||
return {
|
||||
columns: [
|
||||
{ name: 'ref', label: 'serial', field: 'ref', align: 'left' },
|
||||
{
|
||||
name: 'issued',
|
||||
label: 'issued',
|
||||
field: 'issued',
|
||||
align: 'left'
|
||||
},
|
||||
{ name: 'amount', label: 'amount', field: 'amount' },
|
||||
{
|
||||
name: 'hasPdf',
|
||||
label: 'download',
|
||||
field: 'hasPdf',
|
||||
align: 'center'
|
||||
}
|
||||
],
|
||||
pagination: {
|
||||
rowsPerPage: 0
|
||||
},
|
||||
year: curYear,
|
||||
years,
|
||||
invoices: null
|
||||
};
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
await this.fetchUser();
|
||||
},
|
||||
|
||||
watch: {
|
||||
async year() {
|
||||
await this.fetchUser();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
date,
|
||||
currency,
|
||||
|
||||
async fetchUser() {
|
||||
const params = {
|
||||
from: new Date(this.year, 0),
|
||||
to: new Date(this.year, 11, 31, 23, 59, 59)
|
||||
};
|
||||
this._invoices = await this.$jApi.query(
|
||||
`SELECT id, ref, issued, amount, hasPdf
|
||||
FROM myInvoice
|
||||
WHERE issued BETWEEN #from AND #to
|
||||
ORDER BY issued DESC
|
||||
LIMIT 500`,
|
||||
params
|
||||
);
|
||||
},
|
||||
|
||||
invoiceUrl(id) {
|
||||
return (
|
||||
'?' +
|
||||
new URLSearchParams({
|
||||
srv: 'rest:dms/invoice',
|
||||
invoice: id,
|
||||
access_token: this.$user.token
|
||||
}).toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en-US:
|
||||
noInvoicesFound: No invoices found
|
||||
serial: Serial
|
||||
issued: Date
|
||||
amount: Import
|
||||
downloadInvoicePdf: Download invoice PDF
|
||||
notDownloadable: Not available for download, request the invoice to your salesperson
|
||||
es-ES:
|
||||
noInvoicesFound: No se han encontrado facturas
|
||||
serial: Serie
|
||||
issued: Fecha
|
||||
amount: Importe
|
||||
downloadInvoicePdf: Descargar factura en PDF
|
||||
notDownloadable: No disponible para descarga, solicita la factura a tu comercial
|
||||
ca-ES:
|
||||
noInvoicesFound: No s'han trobat factures
|
||||
serial: Sèrie
|
||||
issued: Data
|
||||
amount: Import
|
||||
downloadInvoicePdf: Descarregar PDF
|
||||
notDownloadable: No disponible per cescarrega, sol·licita la factura al teu comercial
|
||||
fr-FR:
|
||||
noInvoicesFound: Aucune facture trouvée
|
||||
serial: Série
|
||||
issued: Date
|
||||
amount: Montant
|
||||
downloadInvoicePdf: Télécharger le PDF
|
||||
notDownloadable: Non disponible en téléchargement, demander la facture à votre commercial
|
||||
pt-PT:
|
||||
noInvoicesFound: Nenhuma fatura encontrada
|
||||
serial: Serie
|
||||
issued: Data
|
||||
amount: Importe
|
||||
downloadInvoicePdf: Baixar PDF
|
||||
notDownloadable: Não disponível para download, solicite a fatura ao seu comercial
|
||||
</i18n>
|
|
@ -0,0 +1,162 @@
|
|||
<script setup>
|
||||
import { ref, onMounted, inject, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import VnTable from 'src/components/ui/VnTable.vue';
|
||||
|
||||
import { currency, formatDate } from 'src/lib/filters.js';
|
||||
import { usePrintService } from 'src/composables/usePrintService';
|
||||
import { useAppStore } from 'stores/app';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
const { t } = useI18n();
|
||||
const jApi = inject('jApi');
|
||||
const { openReport } = usePrintService();
|
||||
const appStore = useAppStore();
|
||||
const { isHeaderMounted } = storeToRefs(appStore);
|
||||
|
||||
const currentYear = ref(Date.vnNew().getFullYear());
|
||||
const years = ref([]);
|
||||
const invoices = ref([]);
|
||||
|
||||
const columns = computed(() => [
|
||||
{ name: 'ref', label: t('invoice'), field: 'ref', align: 'left' },
|
||||
{
|
||||
name: 'issued',
|
||||
label: t('issued'),
|
||||
field: 'issued',
|
||||
align: 'left',
|
||||
format: val => formatDate(val, 'D MMM YYYY')
|
||||
},
|
||||
{
|
||||
name: 'amount',
|
||||
label: t('amount'),
|
||||
field: 'amount',
|
||||
format: val => currency(val)
|
||||
},
|
||||
{
|
||||
name: 'hasPdf',
|
||||
field: 'hasPdf',
|
||||
align: 'center'
|
||||
}
|
||||
]);
|
||||
|
||||
const fetchInvoices = async () => {
|
||||
const params = {
|
||||
from: new Date(currentYear.value, 0),
|
||||
to: new Date(currentYear.value, 11, 31, 23, 59, 59)
|
||||
};
|
||||
invoices.value = await jApi.query(
|
||||
`SELECT id, ref, issued, amount, hasPdf
|
||||
FROM myInvoice
|
||||
WHERE issued BETWEEN #from AND #to
|
||||
ORDER BY issued DESC
|
||||
LIMIT 100`,
|
||||
params
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await fetchInvoices();
|
||||
for (let year = currentYear.value - 5; year <= currentYear.value; year++) {
|
||||
years.value.push(year);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport v-if="isHeaderMounted" to="#actions">
|
||||
<QSelect
|
||||
v-model="currentYear"
|
||||
:options="years"
|
||||
color="white"
|
||||
dark
|
||||
standout
|
||||
dense
|
||||
rounded
|
||||
@update:model-value="fetchInvoices()"
|
||||
/>
|
||||
</Teleport>
|
||||
<div class="vn-w-sm">
|
||||
<VnTable
|
||||
:columns="columns"
|
||||
:rows="invoices"
|
||||
:hide-header="!invoices?.length"
|
||||
>
|
||||
<template #body-cell-hasPdf="{ row }">
|
||||
<QTd
|
||||
auto-width
|
||||
@click.stop
|
||||
class="flex full-width justify-center items-center"
|
||||
>
|
||||
<QBtn
|
||||
v-if="row.hasPdf"
|
||||
icon="download"
|
||||
target="_blank"
|
||||
flat
|
||||
round
|
||||
@click="openReport(`InvoiceOuts/${row.id}/download`)"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('downloadInvoicePdf') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
<QIcon
|
||||
v-else
|
||||
name="warning"
|
||||
:title="t('notDownloadable')"
|
||||
color="warning"
|
||||
size="sm"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('requestTheInvoiceToComercial') }}
|
||||
</QTooltip>
|
||||
</QIcon>
|
||||
</QTd>
|
||||
</template>
|
||||
</VnTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en-US:
|
||||
noInvoicesFound: No invoices found
|
||||
invoice: Invoice
|
||||
issued: Date
|
||||
amount: Import
|
||||
downloadInvoicePdf: Download invoice PDF
|
||||
notDownloadable: Not available for download, request the invoice to your salesperson
|
||||
requestTheInvoiceToComercial: Request the invoice to your salesperson
|
||||
es-ES:
|
||||
noInvoicesFound: No se han encontrado facturas
|
||||
invoice: Factura
|
||||
issued: Fecha
|
||||
amount: Importe
|
||||
downloadInvoicePdf: Descargar factura en PDF
|
||||
notDownloadable: No disponible para descarga, solicita la factura a tu comercial
|
||||
requestTheInvoiceToComercial: Solicita la factura a tu comercial
|
||||
ca-ES:
|
||||
noInvoicesFound: No s'han trobat factures
|
||||
invoice: Factura
|
||||
issued: Data
|
||||
amount: Import
|
||||
downloadInvoicePdf: Descarregar PDF
|
||||
notDownloadable: No disponible per cescarrega, sol·licita la factura al teu comercial
|
||||
requestTheInvoiceToComercial: Sol·licita la factura al teu comercial
|
||||
fr-FR:
|
||||
noInvoicesFound: Aucune facture trouvée
|
||||
invoice: Facture
|
||||
issued: Date
|
||||
amount: Montant
|
||||
downloadInvoicePdf: Télécharger le PDF
|
||||
notDownloadable: Non disponible en téléchargement, demander la facture à votre commercial
|
||||
requestTheInvoiceToComercial: Demander la facture à votre commercial
|
||||
pt-PT:
|
||||
noInvoicesFound: Nenhuma fatura encontrada
|
||||
invoice: Fatura
|
||||
issued: Data
|
||||
amount: Importe
|
||||
downloadInvoicePdf: Baixar PDF
|
||||
notDownloadable: Não disponível para download, solicite a fatura ao seu comercial
|
||||
requestTheInvoiceToComercial: Solicite a fatura ao seu comercial
|
||||
</i18n>
|
|
@ -1,70 +1,135 @@
|
|||
<script setup>
|
||||
import { ref, onMounted, inject } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import CardList from 'src/components/ui/CardList.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
||||
|
||||
import { currency, formatDateTitle } from 'src/lib/filters.js';
|
||||
import { tpvStore } from 'stores/tpv';
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const jApi = inject('jApi');
|
||||
|
||||
const showAmountToPayDialog = ref(null);
|
||||
const amountToPay = ref(null);
|
||||
const orders = ref(null);
|
||||
const debt = ref(0);
|
||||
const tpv = tpvStore();
|
||||
|
||||
onMounted(async () => {
|
||||
await tpv.check(route);
|
||||
|
||||
orders.value = await jApi.query('CALL myTicket_list(NULL, NULL)');
|
||||
debt.value = await jApi.getValue('SELECT -myClient_getDebt(NULL)');
|
||||
});
|
||||
|
||||
const onPayClick = async () => {
|
||||
showAmountToPayDialog.value = true;
|
||||
|
||||
if (debt.value <= 0) {
|
||||
amountToPay.value = -debt.value;
|
||||
}
|
||||
};
|
||||
|
||||
const onConfirmPay = async () => {
|
||||
if (amountToPay.value) {
|
||||
const amount = amountToPay.value.toString().replace('.', ',');
|
||||
amountToPay.value = parseFloat(amount);
|
||||
await tpv.pay(amountToPay.value);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport v-if="isHeaderMounted" to="#actions">
|
||||
<div class="balance">
|
||||
<span class="label">{{ $t('balance') }}</span>
|
||||
<span class="label">{{ t('balance') }}</span>
|
||||
<span class="amount" :class="{ negative: debt < 0 }">
|
||||
{{ currency(debt || 0) }}
|
||||
</span>
|
||||
<QIcon
|
||||
name="info"
|
||||
:title="$t('paymentInfo')"
|
||||
class="info"
|
||||
size="24px"
|
||||
/>
|
||||
<QIcon name="info" class="info" size="sm">
|
||||
<QTooltip max-width="450px">
|
||||
{{ t('paymentInfo') }}
|
||||
</QTooltip>
|
||||
</QIcon>
|
||||
</div>
|
||||
<QBtn
|
||||
icon="payments"
|
||||
:label="$t('makePayment')"
|
||||
:label="t('makePayment')"
|
||||
@click="onPayClick()"
|
||||
rounded
|
||||
no-caps
|
||||
/>
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('makePayment') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
to="/ecomerce/basket"
|
||||
:to="{ name: 'basket' }"
|
||||
icon="shopping_cart"
|
||||
:label="$t('shoppingCart')"
|
||||
:label="t('shoppingCart')"
|
||||
rounded
|
||||
no-caps
|
||||
/>
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('shoppingCart') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</Teleport>
|
||||
<div class="vn-w-sm">
|
||||
<QPage class="vn-w-sm">
|
||||
<div
|
||||
v-if="!orders?.length"
|
||||
class="text-subtitle1 text-center text-grey-7 q-pa-md"
|
||||
>
|
||||
{{ $t('noOrdersFound') }}
|
||||
{{ t('noOrdersFound') }}
|
||||
</div>
|
||||
<QCard v-if="orders?.length">
|
||||
<QList bordered separator padding>
|
||||
<QItem
|
||||
v-for="order in orders"
|
||||
:key="order.id"
|
||||
:to="`ticket/${order.id}`"
|
||||
clickable
|
||||
v-ripple
|
||||
>
|
||||
<QItemSection>
|
||||
<QItemLabel>
|
||||
{{ date(order.landed, 'ddd, MMMM Do') }}
|
||||
</QItemLabel>
|
||||
<QItemLabel caption>#{{ order.id }}</QItemLabel>
|
||||
<QItemLabel caption>{{ order.nickname }}</QItemLabel>
|
||||
<QItemLabel caption>{{ order.agency }}</QItemLabel>
|
||||
</QItemSection>
|
||||
<QItemSection side top> {{ order.total }}€ </QItemSection>
|
||||
</QItem>
|
||||
</QList>
|
||||
</QCard>
|
||||
<QList v-if="orders?.length">
|
||||
<CardList
|
||||
v-for="order in orders"
|
||||
:key="order.id"
|
||||
:to="`ticket/${order.id}`"
|
||||
tag="label"
|
||||
>
|
||||
<template #content>
|
||||
<QItemLabel
|
||||
class="full-width text-bold q-mb-sm flex row justify-between"
|
||||
>
|
||||
<span>{{ formatDateTitle(order.landed) }}</span>
|
||||
<span>{{ currency(order.total) }}</span>
|
||||
</QItemLabel>
|
||||
<QItemLabel>#{{ order.id }}</QItemLabel>
|
||||
<QItemLabel>{{ order.nickname }}</QItemLabel>
|
||||
<QItemLabel>{{ order.agency }}</QItemLabel>
|
||||
</template>
|
||||
</CardList>
|
||||
</QList>
|
||||
<QPageSticky>
|
||||
<QBtn
|
||||
fab
|
||||
icon="add_shopping_cart"
|
||||
color="accent"
|
||||
to="/ecomerce/catalog"
|
||||
:title="$t('startOrder')"
|
||||
:to="{ name: 'catalog' }"
|
||||
:title="t('startOrder')"
|
||||
/>
|
||||
</QPageSticky>
|
||||
</div>
|
||||
<VnConfirm
|
||||
v-model="showAmountToPayDialog"
|
||||
:message="t('amountToPay')"
|
||||
:promise="onConfirmPay"
|
||||
>
|
||||
<template #customHTML>
|
||||
<VnInput
|
||||
v-model="amountToPay"
|
||||
:clearable="false"
|
||||
class="full-width"
|
||||
/>
|
||||
</template>
|
||||
</VnConfirm>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -92,57 +157,6 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { date, currency } from 'src/lib/filters.js';
|
||||
import { tpvStore } from 'stores/tpv';
|
||||
import { useAppStore } from 'stores/app';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
export default {
|
||||
name: 'OrdersPendingIndex',
|
||||
setup() {
|
||||
const appStore = useAppStore();
|
||||
const { isHeaderMounted } = storeToRefs(appStore);
|
||||
return { isHeaderMounted };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
orders: null,
|
||||
debt: 0,
|
||||
tpv: tpvStore()
|
||||
};
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
await this.tpv.check(this.$route);
|
||||
|
||||
this.orders = await this.$jApi.query('CALL myTicket_list(NULL, NULL)');
|
||||
this.debt = await this.$jApi.getValue('SELECT -myClient_getDebt(NULL)');
|
||||
},
|
||||
|
||||
methods: {
|
||||
date,
|
||||
currency,
|
||||
|
||||
async onPayClick() {
|
||||
let amount = -this.debt;
|
||||
amount = amount <= 0 ? null : amount;
|
||||
|
||||
let defaultAmountStr = '';
|
||||
if (amount !== null) {
|
||||
defaultAmountStr = amount;
|
||||
}
|
||||
amount = prompt(this.$t('amountToPay'), defaultAmountStr);
|
||||
|
||||
if (amount != null) {
|
||||
amount = parseFloat(amount.replace(',', '.'));
|
||||
await this.tpv.pay(amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en-US:
|
||||
startOrder: Start order
|
||||
|
@ -155,6 +169,7 @@ en-US:
|
|||
disregards future orders. For get your order shipped, this amount must be
|
||||
equal to or greater than 0. If you want to make a down payment, click the
|
||||
payment button, delete the suggested amount and enter the amount you want.
|
||||
amountToPay: 'Amount to pay (€):'
|
||||
es-ES:
|
||||
startOrder: Empezar pedido
|
||||
noOrdersFound: No se encontrado pedidos
|
||||
|
@ -167,6 +182,7 @@ es-ES:
|
|||
esta cantidad debe ser igual o mayor que 0. Si quieres realizar una entrega a
|
||||
cuenta, pulsa el botón de pago, borra la cantidad sugerida e introduce la
|
||||
cantidad que desees.
|
||||
amountToPay: 'Cantidad a pagar (€):'
|
||||
ca-ES:
|
||||
startOrder: Començar encàrrec
|
||||
noOrdersFound: No s'han trobat comandes
|
||||
|
@ -179,6 +195,7 @@ ca-ES:
|
|||
enviat, aquesta quantitat ha de ser igual o més gran que 0. Si vols fer un
|
||||
lliurament a compte, prem el botó de pagament, esborra la quantitat suggerida
|
||||
e introdueix la quantitat que vulguis.
|
||||
amountToPay: 'Quantitat a pagar (€):'
|
||||
fr-FR:
|
||||
startOrder: Acheter
|
||||
noOrdersFound: Aucune commande trouvée
|
||||
|
@ -191,6 +208,7 @@ fr-FR:
|
|||
commande est expédiée, ce montant doit être égal ou supérieur à 0. Si vous
|
||||
voulez faire un versement, le montant suggéré effacé et entrez le montant que
|
||||
vous souhaitez.
|
||||
amountToPay: 'Montant à payer (€):'
|
||||
pt-PT:
|
||||
startOrder: Iniciar encomenda
|
||||
noOrdersFound: Nenhum pedido encontrado
|
||||
|
@ -203,4 +221,5 @@ pt-PT:
|
|||
quantidade deve ser igual ou superior a 0. Se queres realizar um depósito à
|
||||
conta, clique no botão de pagamento, apague a quantidade sugerida e introduza
|
||||
a quantidade que deseje.
|
||||
amountToPay: 'Valor a pagar (€):'
|
||||
</i18n>
|
|
@ -0,0 +1,137 @@
|
|||
<script setup>
|
||||
import { ref, inject, onMounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import CardList from 'src/components/ui/CardList.vue';
|
||||
import { currency, formatDateTitle } from 'src/lib/filters.js';
|
||||
import { useVnConfirm } from 'src/composables/useVnConfirm.js';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { useAppStore } from 'stores/app';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
const jApi = inject('jApi');
|
||||
const { t } = useI18n();
|
||||
const { openConfirmationModal } = useVnConfirm();
|
||||
const { notify } = useNotify();
|
||||
const appStore = useAppStore();
|
||||
const { isHeaderMounted } = storeToRefs(appStore);
|
||||
const router = useRouter();
|
||||
|
||||
const orders = ref([]);
|
||||
|
||||
const getOrders = async () => {
|
||||
try {
|
||||
orders.value = await jApi.query(
|
||||
`SELECT o.id, o.sent, o.deliveryMethodFk, o.taxableBase,
|
||||
a.nickname, am.description agency
|
||||
FROM myOrder o
|
||||
JOIN myAddress a ON a.id = o.addressFk
|
||||
JOIN vn.agencyMode am ON am.id = o.agencyModeFk
|
||||
WHERE NOT o.isConfirmed
|
||||
ORDER BY o.sent DESC`
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error getting orders:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const removeOrder = async (id, index) => {
|
||||
try {
|
||||
await jApi.execQuery(
|
||||
`START TRANSACTION;
|
||||
DELETE FROM hedera.myOrder WHERE ((id = #id));
|
||||
COMMIT`,
|
||||
{
|
||||
id
|
||||
}
|
||||
);
|
||||
orders.value.splice(index, 1);
|
||||
notify(t('dataSaved'), 'positive');
|
||||
} catch (error) {
|
||||
console.error('Error removing order:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const loadOrder = orderId => {
|
||||
// store.loadIntoBasket(orderId);
|
||||
router.push({ name: 'catalog' });
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
getOrders();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport v-if="isHeaderMounted" to="#actions">
|
||||
<QBtn
|
||||
:to="{ name: 'checkout' }"
|
||||
icon="add_shopping_cart"
|
||||
:label="t('newOrder')"
|
||||
rounded
|
||||
no-caps
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('newOrder') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</Teleport>
|
||||
<QPage class="vn-w-sm">
|
||||
<CardList
|
||||
v-for="(order, index) in orders"
|
||||
:key="index"
|
||||
:to="{ name: 'basket', params: { id: order.id } }"
|
||||
>
|
||||
<template #content>
|
||||
<QItemLabel class="text-bold q-mb-sm">{{
|
||||
formatDateTitle(order.sent)
|
||||
}}</QItemLabel>
|
||||
<QItemLabel> #{{ order.id }} </QItemLabel>
|
||||
<QItemLabel>{{ order.nickname }}</QItemLabel>
|
||||
<QItemLabel>{{ order.agency }}</QItemLabel>
|
||||
<QItemLabel>{{ currency(order.taxableBase) }}</QItemLabel>
|
||||
</template>
|
||||
<template #actions>
|
||||
<QBtn
|
||||
icon="delete"
|
||||
flat
|
||||
rounded
|
||||
@click.stop.prevent="
|
||||
openConfirmationModal(
|
||||
null,
|
||||
t('areYouSureDeleteOrder'),
|
||||
() => removeOrder(order.id, index)
|
||||
)
|
||||
"
|
||||
/>
|
||||
<QBtn
|
||||
icon="shopping_bag"
|
||||
flat
|
||||
rounded
|
||||
@click.stop.prevent="loadOrder(order.id)"
|
||||
/>
|
||||
</template>
|
||||
</CardList>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en-US:
|
||||
newOrder: New order
|
||||
areYouSureDeleteOrder: Are you sure you want to delete the order?
|
||||
es-ES:
|
||||
newOrder: Nuevo pedido
|
||||
areYouSureDeleteOrder: ¿Seguro que quieres borrar el pedido?
|
||||
ca-ES:
|
||||
newOrder: Nova comanda
|
||||
areYouSureDeleteOrder: Segur que vols esborrar la comanda?
|
||||
fr-FR:
|
||||
newOrder: Nouvelle commande
|
||||
areYouSureDeleteOrder: Êtes-vous sûr de vouloir supprimer la commande?
|
||||
pt-PT:
|
||||
newOrder: Novo pedido
|
||||
areYouSureDeleteOrder: Tem certeza de que deseja excluir o pedido?
|
||||
</i18n>
|
|
@ -1,151 +0,0 @@
|
|||
<template>
|
||||
<Teleport v-if="isHeaderMounted" to="#actions">
|
||||
<QBtn
|
||||
icon="print"
|
||||
:label="$t('printDeliveryNote')"
|
||||
@click="onPrintClick()"
|
||||
rounded
|
||||
no-caps
|
||||
/>
|
||||
</Teleport>
|
||||
<div>
|
||||
<QCard class="vn-w-sm">
|
||||
<QCardSection>
|
||||
<div class="text-h6">#{{ ticket.id }}</div>
|
||||
</QCardSection>
|
||||
<QCardSection>
|
||||
<div class="text-h6">{{ $t('shippingInformation') }}</div>
|
||||
<div>
|
||||
{{ $t('preparation') }}
|
||||
{{ date(ticket.shipped, 'ddd, MMMM Do') }}
|
||||
</div>
|
||||
<div>
|
||||
{{ $t('delivery') }}
|
||||
{{ date(ticket.shipped, 'ddd, MMMM Do') }}
|
||||
</div>
|
||||
<div>
|
||||
{{ $t(ticket.method != 'PICKUP' ? 'agency' : 'warehouse') }}
|
||||
{{ ticket.agency }}
|
||||
</div>
|
||||
</QCardSection>
|
||||
<QCardSection>
|
||||
<div class="text-h6">{{ $t('deliveryAddress') }}</div>
|
||||
<div>{{ ticket.nickname }}</div>
|
||||
<div>{{ ticket.street }}</div>
|
||||
<div>
|
||||
{{ ticket.postalCode }} {{ ticket.city }} ({{
|
||||
ticket.province
|
||||
}})
|
||||
</div>
|
||||
</QCardSection>
|
||||
<QSeparator inset />
|
||||
<QList v-for="row in rows" :key="row.itemFk">
|
||||
<QItem>
|
||||
<QItemSection avatar>
|
||||
<QAvatar size="68px">
|
||||
<img
|
||||
:src="`${$app.imageUrl}/catalog/200x200/${row.image}`"
|
||||
/>
|
||||
</QAvatar>
|
||||
</QItemSection>
|
||||
<QItemSection>
|
||||
<QItemLabel lines="1">
|
||||
{{ row.concept }}
|
||||
</QItemLabel>
|
||||
<QItemLabel lines="1" caption>
|
||||
{{ row.value5 }} {{ row.value6 }} {{ row.value7 }}
|
||||
</QItemLabel>
|
||||
<QItemLabel lines="1">
|
||||
{{ row.quantity }} x {{ currency(row.price) }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
<QItemSection side class="total">
|
||||
<QItemLabel>
|
||||
<span class="discount" v-if="row.discount">
|
||||
{{ currency(discountSubtotal(row)) }} -
|
||||
{{ currency(row.discount) }} =
|
||||
</span>
|
||||
{{ currency(subtotal(row)) }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</QList>
|
||||
</QCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.total {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { date, currency } from 'src/lib/filters.js';
|
||||
import { useAppStore } from 'stores/app';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
export default {
|
||||
name: 'OrdersConfirmedView',
|
||||
setup() {
|
||||
const appStore = useAppStore();
|
||||
const { isHeaderMounted } = storeToRefs(appStore);
|
||||
return { isHeaderMounted };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ticket: {},
|
||||
rows: null,
|
||||
services: null,
|
||||
packages: null
|
||||
};
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
const params = {
|
||||
ticket: parseInt(this.$route.params.id)
|
||||
};
|
||||
this.ticket = await this.$jApi.getObject(
|
||||
'CALL myTicket_get(#ticket)',
|
||||
params
|
||||
);
|
||||
this.rows = await this.$jApi.query(
|
||||
'CALL myTicket_getRows(#ticket)',
|
||||
params
|
||||
);
|
||||
this.services = await this.$jApi.query(
|
||||
'CALL myTicket_getServices(#ticket)',
|
||||
params
|
||||
);
|
||||
this.packages = await this.$jApi.query(
|
||||
'CALL myTicket_getPackages(#ticket)',
|
||||
params
|
||||
);
|
||||
},
|
||||
|
||||
methods: {
|
||||
date,
|
||||
currency,
|
||||
|
||||
discountSubtotal(line) {
|
||||
return line.quantity * line.price;
|
||||
},
|
||||
|
||||
subtotal(line) {
|
||||
const discount = line.discount;
|
||||
return this.discountSubtotal(line) * ((100 - discount) / 100);
|
||||
},
|
||||
|
||||
onPrintClick() {
|
||||
const params = new URLSearchParams({
|
||||
access_token: this.$user.token,
|
||||
recipientId: this.$user.id,
|
||||
type: 'deliveryNote'
|
||||
});
|
||||
window.open(
|
||||
`/api/Tickets/${this.ticket.id}/delivery-note-pdf?${params.toString()}`
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,78 @@
|
|||
<script setup>
|
||||
import { onMounted, inject, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import TicketDetails from 'src/components/ui/TicketDetails.vue';
|
||||
|
||||
import { useUserStore } from 'stores/user';
|
||||
import { useAppStore } from 'stores/app';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
const { t } = useI18n();
|
||||
const jApi = inject('jApi');
|
||||
const route = useRoute();
|
||||
const userStore = useUserStore();
|
||||
const appStore = useAppStore();
|
||||
const { isHeaderMounted } = storeToRefs(appStore);
|
||||
|
||||
const ticket = ref({});
|
||||
const rows = ref([]);
|
||||
const services = ref(null);
|
||||
const packages = ref(null);
|
||||
|
||||
onMounted(async () => {
|
||||
const params = {
|
||||
ticket: parseInt(route.params.id)
|
||||
};
|
||||
ticket.value = await jApi.getObject('CALL myTicket_get(#ticket)', params);
|
||||
rows.value = await jApi.query('CALL myTicket_getRows(#ticket)', params);
|
||||
services.value = await jApi.query(
|
||||
'CALL myTicket_getServices(#ticket)',
|
||||
params
|
||||
);
|
||||
packages.value = await jApi.query(
|
||||
'CALL myTicket_getPackages(#ticket)',
|
||||
params
|
||||
);
|
||||
});
|
||||
|
||||
const onPrintClick = () => {
|
||||
const params = new URLSearchParams({
|
||||
access_token: userStore.token,
|
||||
recipientId: userStore.id,
|
||||
type: 'deliveryNote'
|
||||
});
|
||||
window.open(
|
||||
`/api/Tickets/${ticket.value.id}/delivery-note-pdf?${params.toString()}`
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport v-if="isHeaderMounted" to="#actions">
|
||||
<QBtn
|
||||
icon="print"
|
||||
:label="t('printDeliveryNote')"
|
||||
@click="onPrintClick()"
|
||||
rounded
|
||||
no-caps
|
||||
/>
|
||||
</Teleport>
|
||||
<QPage>
|
||||
<TicketDetails :rows="rows" :ticket="ticket" />
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<i18n lang="yaml">
|
||||
en-US:
|
||||
printDeliveryNote: Print delivery note
|
||||
es-ES:
|
||||
printDeliveryNote: Imprimir albarán
|
||||
ca-ES:
|
||||
printDeliveryNote: Imprimir albarà
|
||||
fr-FR:
|
||||
printDeliveryNote: Imprimer bulletin de livraison
|
||||
pt-PT:
|
||||
printDeliveryNote: Imprimir nota de entrega
|
||||
</i18n>
|
|
@ -37,13 +37,38 @@ const routes = [
|
|||
{
|
||||
name: 'confirmedOrders',
|
||||
path: '/ecomerce/orders',
|
||||
component: () => import('src/pages/Ecomerce/Orders.vue')
|
||||
component: () => import('pages/Ecomerce/OrdersView.vue')
|
||||
},
|
||||
{
|
||||
name: 'ticket',
|
||||
path: '/ecomerce/ticket/:id',
|
||||
component: () => import('pages/Ecomerce/TicketView.vue')
|
||||
},
|
||||
{
|
||||
name: 'invoices',
|
||||
path: '/ecomerce/invoices',
|
||||
component: () => import('pages/Ecomerce/InvoicesView.vue')
|
||||
},
|
||||
{
|
||||
name: 'pendingOrders',
|
||||
path: '/ecomerce/pending',
|
||||
component: () => import('pages/Ecomerce/PendingOrders.vue')
|
||||
},
|
||||
{
|
||||
name: 'catalog',
|
||||
path: '/ecomerce/catalog/:category?/:type?',
|
||||
component: () => import('pages/Ecomerce/Catalog.vue')
|
||||
},
|
||||
{
|
||||
name: 'basket',
|
||||
path: '/ecomerce/basket/:id?',
|
||||
component: () => import('pages/Ecomerce/BasketView.vue')
|
||||
},
|
||||
{
|
||||
name: 'checkout',
|
||||
path: '/ecomerce/checkout',
|
||||
component: () => import('pages/Ecomerce/CheckoutView.vue')
|
||||
},
|
||||
{
|
||||
name: 'agencyPackages',
|
||||
path: '/agencies/packages',
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { defineStore } from 'pinia';
|
||||
import { jApi } from 'boot/axios';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
|
||||
const { notify } = useNotify();
|
||||
|
||||
export const useAppStore = defineStore('hedera', {
|
||||
state: () => ({
|
||||
|
@ -9,7 +12,8 @@ export const useAppStore = defineStore('hedera', {
|
|||
useRightDrawer: false,
|
||||
rightDrawerOpen: false,
|
||||
isHeaderMounted: false,
|
||||
menuEssentialLinks: []
|
||||
menuEssentialLinks: [],
|
||||
basketOrderId: null
|
||||
}),
|
||||
|
||||
actions: {
|
||||
|
@ -38,9 +42,40 @@ export const useAppStore = defineStore('hedera', {
|
|||
|
||||
this.menuEssentialLinks = sectionTree;
|
||||
},
|
||||
|
||||
async loadConfig() {
|
||||
const imageUrl = await jApi.getValue('SELECT url FROM imageConfig');
|
||||
this.$patch({ imageUrl });
|
||||
},
|
||||
|
||||
async init() {
|
||||
this.getBasketOrderId();
|
||||
},
|
||||
|
||||
getBasketOrderId() {
|
||||
this.basketOrderId = localStorage.getItem('hederaBasket');
|
||||
},
|
||||
|
||||
async checkOrder(orderId) {
|
||||
try {
|
||||
const resultSet = await jApi.execQuery(
|
||||
'CALL myOrder_checkConfig(#id)',
|
||||
{ id: orderId }
|
||||
);
|
||||
resultSet.fetchValue();
|
||||
} catch (err) {
|
||||
console.error('Error checking order', err);
|
||||
}
|
||||
},
|
||||
|
||||
loadIntoBasket(orderId) {
|
||||
console.log('loadIntoBasket', orderId);
|
||||
console.log('this.basketOrderId', this.basketOrderId);
|
||||
if (this.basketOrderId !== orderId) {
|
||||
localStorage.setItem('hederaBasket', orderId);
|
||||
this.basketOrderId = orderId;
|
||||
notify('orderLoadedIntoBasket', 'positive');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue