Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 4722-routes_refactor
gitea/salix-front/pipeline/head This commit looks good
Details
gitea/salix-front/pipeline/head This commit looks good
Details
This commit is contained in:
commit
5a397a5302
|
@ -0,0 +1,54 @@
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
maxLength: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="fetchedTags">
|
||||||
|
<div class="wrap">
|
||||||
|
<div class="inline-tag" :class="{ empty: !$props.item.value5 }">{{ $props.item.value5 }}</div>
|
||||||
|
<div class="inline-tag" :class="{ empty: !$props.item.value6 }">{{ $props.item.value6 }}</div>
|
||||||
|
<div class="inline-tag" :class="{ empty: !$props.item.value7 }">{{ $props.item.value7 }}</div>
|
||||||
|
<div class="inline-tag" :class="{ empty: !$props.item.value8 }">{{ $props.item.value8 }}</div>
|
||||||
|
<div class="inline-tag" :class="{ empty: !$props.item.value9 }">{{ $props.item.value9 }}</div>
|
||||||
|
<div class="inline-tag" :class="{ empty: !$props.item.value10 }">{{ $props.item.value10 }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.fetchedTags {
|
||||||
|
align-items: center;
|
||||||
|
.wrap {
|
||||||
|
width: 100%;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-tag {
|
||||||
|
height: 1rem;
|
||||||
|
margin: 0.05rem;
|
||||||
|
color: $secondary;
|
||||||
|
text-align: center;
|
||||||
|
font-size: smaller;
|
||||||
|
padding: 1px;
|
||||||
|
flex: 1;
|
||||||
|
border: 1px solid $color-spacer;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
min-width: 4rem;
|
||||||
|
max-width: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
border: 1px solid $color-spacer-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -22,3 +22,9 @@ $positive: #21ba45;
|
||||||
$negative: #c10015;
|
$negative: #c10015;
|
||||||
$info: #31ccec;
|
$info: #31ccec;
|
||||||
$warning: #f2c037;
|
$warning: #f2c037;
|
||||||
|
|
||||||
|
$color-spacer-light: rgba(255, 255, 255, .12);
|
||||||
|
$color-spacer:rgba(255, 255, 255, .3);
|
||||||
|
$border-thin-light: 1px solid $color-spacer-light;
|
||||||
|
|
||||||
|
$spacing-md: 16px;
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
export default function (value) {
|
||||||
|
if (value == null || value === '') return '-';
|
||||||
|
return value;
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import toDate from './toDate';
|
||||||
import toCurrency from './toCurrency';
|
import toCurrency from './toCurrency';
|
||||||
import toPercentage from './toPercentage';
|
import toPercentage from './toPercentage';
|
||||||
import toLowerCamel from './toLowerCamel';
|
import toLowerCamel from './toLowerCamel';
|
||||||
|
import dashIfEmpty from './dashIfEmpty';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
toLowerCase,
|
toLowerCase,
|
||||||
|
@ -10,4 +11,5 @@ export {
|
||||||
toDate,
|
toDate,
|
||||||
toCurrency,
|
toCurrency,
|
||||||
toPercentage,
|
toPercentage,
|
||||||
|
dashIfEmpty,
|
||||||
};
|
};
|
||||||
|
|
|
@ -187,6 +187,49 @@ export default {
|
||||||
selectVideo: 'Select video:',
|
selectVideo: 'Select video:',
|
||||||
notFound: 'No videos available',
|
notFound: 'No videos available',
|
||||||
},
|
},
|
||||||
|
summary: {
|
||||||
|
state: 'State',
|
||||||
|
salesPerson: 'Sales person',
|
||||||
|
agency: 'Agency',
|
||||||
|
zone: 'Zone',
|
||||||
|
warehouse: 'Warehouse',
|
||||||
|
route: 'Route',
|
||||||
|
invoice: 'Invoice',
|
||||||
|
shipped: 'Shipped',
|
||||||
|
landed: 'Landed',
|
||||||
|
packages: 'Packages',
|
||||||
|
consigneePhone: 'Consignee phone',
|
||||||
|
consigneeMobile: 'Consignee mobile',
|
||||||
|
clientPhone: 'Client phone',
|
||||||
|
clientMobile: 'Client mobile',
|
||||||
|
consignee: 'Consignee',
|
||||||
|
subtotal: 'Subtotal',
|
||||||
|
vat: 'VAT',
|
||||||
|
total: 'Total',
|
||||||
|
saleLines: 'Line items',
|
||||||
|
item: 'Item',
|
||||||
|
visible: 'Visible',
|
||||||
|
available: 'Available',
|
||||||
|
quantity: 'Quantity',
|
||||||
|
description: 'Description',
|
||||||
|
price: 'Price',
|
||||||
|
discount: 'Discount',
|
||||||
|
amount: 'Amount',
|
||||||
|
packing: 'Packing',
|
||||||
|
hasComponentLack: 'Component lack',
|
||||||
|
itemShortage: 'Not visible',
|
||||||
|
claim: 'Claim',
|
||||||
|
reserved: 'Reserved',
|
||||||
|
created: 'Created',
|
||||||
|
package: 'Package',
|
||||||
|
taxClass: 'Tax class',
|
||||||
|
services: 'Services',
|
||||||
|
changeState: 'Change state',
|
||||||
|
requester: 'Requester',
|
||||||
|
atender: 'Atender',
|
||||||
|
request: 'Request',
|
||||||
|
goTo: 'Go to'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
claim: {
|
claim: {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
|
@ -251,6 +294,50 @@ export default {
|
||||||
returnOfMaterial: 'Return of material authorization (RMA)',
|
returnOfMaterial: 'Return of material authorization (RMA)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
invoiceOut: {
|
||||||
|
pageTitles: {
|
||||||
|
invoiceOuts: 'InvoiceOuts',
|
||||||
|
list: 'List',
|
||||||
|
createInvoiceOut: 'Create invoice out',
|
||||||
|
summary: 'Summary',
|
||||||
|
basicData: 'Basic Data'
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
ref: 'Reference',
|
||||||
|
issued: 'Issued',
|
||||||
|
amount: 'Amount',
|
||||||
|
client: 'Client',
|
||||||
|
created: 'Created',
|
||||||
|
company: 'Company',
|
||||||
|
dued: 'Due date'
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
issued: 'Issued',
|
||||||
|
amount: 'Amount',
|
||||||
|
client: 'Client',
|
||||||
|
company: 'Company',
|
||||||
|
customerCard: 'Customer card',
|
||||||
|
ticketList: 'Ticket List'
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
issued: 'Issued',
|
||||||
|
created: 'Created',
|
||||||
|
dued: 'Due',
|
||||||
|
booked: 'Booked',
|
||||||
|
company: 'Company',
|
||||||
|
taxBreakdown: 'Tax breakdown',
|
||||||
|
type: 'Type',
|
||||||
|
taxableBase: 'Taxable base',
|
||||||
|
rate: 'Rate',
|
||||||
|
fee: 'Fee',
|
||||||
|
tickets: 'Tickets',
|
||||||
|
ticketId: 'Ticket id',
|
||||||
|
nickname: 'Alias',
|
||||||
|
shipped: 'Shipped',
|
||||||
|
totalWithVat: 'Amount',
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
topbar: {},
|
topbar: {},
|
||||||
userPanel: {
|
userPanel: {
|
||||||
|
|
|
@ -186,6 +186,49 @@ export default {
|
||||||
selectVideo: 'Seleccionar vídeo:',
|
selectVideo: 'Seleccionar vídeo:',
|
||||||
notFound: 'No hay vídeos disponibles',
|
notFound: 'No hay vídeos disponibles',
|
||||||
},
|
},
|
||||||
|
summary: {
|
||||||
|
state: 'Estado',
|
||||||
|
salesPerson: 'Comercial',
|
||||||
|
agency: 'Agencia',
|
||||||
|
zone: 'Zona',
|
||||||
|
warehouse: 'Almacén',
|
||||||
|
route: 'Ruta',
|
||||||
|
invoice: 'Factura',
|
||||||
|
shipped: 'Enviado',
|
||||||
|
landed: 'Entregado',
|
||||||
|
packages: 'Bultos',
|
||||||
|
consigneePhone: 'Tel. consignatario',
|
||||||
|
consigneeMobile: 'Móv. consignatario',
|
||||||
|
clientPhone: 'Tel. cliente',
|
||||||
|
clientMobile: 'Móv. cliente',
|
||||||
|
consignee: 'Consignatario',
|
||||||
|
subtotal: 'Subtotal',
|
||||||
|
vat: 'IVA',
|
||||||
|
total: 'Total',
|
||||||
|
saleLines: 'Líneas del pedido',
|
||||||
|
item: 'Artículo',
|
||||||
|
visible: 'Visible',
|
||||||
|
available: 'Disponible',
|
||||||
|
quantity: 'Cantidad',
|
||||||
|
description: 'Descripción',
|
||||||
|
price: 'Precio',
|
||||||
|
discount: 'Descuento',
|
||||||
|
amount: 'Importe',
|
||||||
|
packing: 'Encajado',
|
||||||
|
hasComponentLack: 'Faltan componentes',
|
||||||
|
itemShortage: 'No visible',
|
||||||
|
claim: 'Reclamación',
|
||||||
|
reserved: 'Reservado',
|
||||||
|
created: 'Fecha creación',
|
||||||
|
package: 'Embalaje',
|
||||||
|
taxClass: 'Tipo IVA',
|
||||||
|
services: 'Servicios',
|
||||||
|
changeState: 'Cambiar estado',
|
||||||
|
requester: 'Solicitante',
|
||||||
|
atender: 'Comprador',
|
||||||
|
request: 'Petición de compra',
|
||||||
|
goTo: 'Ir a'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
claim: {
|
claim: {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
|
@ -250,6 +293,50 @@ export default {
|
||||||
returnOfMaterial: 'Autorización de retorno de materiales (RMA)',
|
returnOfMaterial: 'Autorización de retorno de materiales (RMA)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
invoiceOut: {
|
||||||
|
pageTitles: {
|
||||||
|
invoiceOuts: 'Fact. emitidas',
|
||||||
|
list: 'Listado',
|
||||||
|
createInvoiceOut: 'Crear fact. emitida',
|
||||||
|
summary: 'Resumen',
|
||||||
|
basicData: 'Datos básicos'
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
ref: 'Referencia',
|
||||||
|
issued: 'Fecha emisión',
|
||||||
|
amount: 'Importe',
|
||||||
|
client: 'Cliente',
|
||||||
|
created: 'Fecha creación',
|
||||||
|
company: 'Empresa',
|
||||||
|
dued: 'Fecha vencimineto'
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
issued: 'Fecha emisión',
|
||||||
|
amount: 'Importe',
|
||||||
|
client: 'Cliente',
|
||||||
|
company: 'Empresa',
|
||||||
|
customerCard: 'Ficha del cliente',
|
||||||
|
ticketList: 'Listado de tickets'
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
issued: 'Fecha',
|
||||||
|
created: 'Fecha creación',
|
||||||
|
dued: 'Vencimiento',
|
||||||
|
booked: 'Contabilizada',
|
||||||
|
company: 'Empresa',
|
||||||
|
taxBreakdown: 'Desglose impositivo',
|
||||||
|
type: 'Tipo',
|
||||||
|
taxableBase: 'Base imp.',
|
||||||
|
rate: 'Tarifa',
|
||||||
|
fee: 'Cuota',
|
||||||
|
tickets: 'Tickets',
|
||||||
|
ticketId: 'Id ticket',
|
||||||
|
nickname: 'Alias',
|
||||||
|
shipped: 'F. envío',
|
||||||
|
totalWithVat: 'Importe',
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
topbar: {},
|
topbar: {},
|
||||||
userPanel: {
|
userPanel: {
|
||||||
|
|
|
@ -19,3 +19,11 @@ const { dialogRef, onDialogHide } = useDialogPluginComponent();
|
||||||
<claim-summary v-if="$props.id" :id="$props.id" />
|
<claim-summary v-if="$props.id" :id="$props.id" />
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.q-dialog .summary .header {
|
||||||
|
position: sticky;
|
||||||
|
z-index: $z-max;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -19,3 +19,11 @@ const { dialogRef, onDialogHide } = useDialogPluginComponent();
|
||||||
<customer-summary v-if="$props.id" :id="$props.id" />
|
<customer-summary v-if="$props.id" :id="$props.id" />
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.q-dialog .summary .header {
|
||||||
|
position: sticky;
|
||||||
|
z-index: $z-max;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<script setup>
|
||||||
|
import { useState } from 'src/composables/useState';
|
||||||
|
import InvoiceOutDescriptor from './InvoiceOutDescriptor.vue';
|
||||||
|
|
||||||
|
const state = useState();
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="500">
|
||||||
|
<q-scroll-area class="fit">
|
||||||
|
<InvoiceOutDescriptor />
|
||||||
|
</q-scroll-area>
|
||||||
|
</q-drawer>
|
||||||
|
<q-page-container>
|
||||||
|
<q-page class="q-pa-md">
|
||||||
|
<router-view></router-view>
|
||||||
|
</q-page>
|
||||||
|
</q-page-container>
|
||||||
|
</template>
|
|
@ -0,0 +1,103 @@
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref, computed } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
|
import axios from 'axios';
|
||||||
|
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
||||||
|
import CustomerDescriptorPopover from 'src/pages/Customer/Card/CustomerDescriptorPopover.vue';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await fetch();
|
||||||
|
});
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const entityId = computed(() => {
|
||||||
|
return $props.id || route.params.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
const invoiceOut = ref();
|
||||||
|
async function fetch() {
|
||||||
|
const filter = {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'company',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'code'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'client',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'name', 'email'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = { params: { filter } };
|
||||||
|
const { data } = await axios.get(`InvoiceOuts/${entityId.value}`, options);
|
||||||
|
if (data) invoiceOut.value = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter = computed(() => {
|
||||||
|
return invoiceOut.value ? JSON.stringify({ refFk: invoiceOut.value.ref }) : null;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<card-descriptor v-if="invoiceOut" module="InvoiceOut" :data="invoiceOut" :description="invoiceOut.ref">
|
||||||
|
<template #body>
|
||||||
|
<q-list>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.card.issued') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(invoiceOut.issued) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.card.amount') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toCurrency(invoiceOut.amount) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section v-if="invoiceOut.company">
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.card.client') }}</q-item-label>
|
||||||
|
<q-item-label class="link">
|
||||||
|
{{ invoiceOut.client.name }}
|
||||||
|
<q-popup-proxy>
|
||||||
|
<customer-descriptor-popover :id="invoiceOut.client.id" />
|
||||||
|
</q-popup-proxy>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section v-if="invoiceOut.company">
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.card.company') }}</q-item-label>
|
||||||
|
<q-item-label>{{ invoiceOut.company.code }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
<q-card-actions>
|
||||||
|
<q-btn
|
||||||
|
size="md"
|
||||||
|
icon="vn:client"
|
||||||
|
color="primary"
|
||||||
|
:to="{ name: 'CustomerCard', params: { id: invoiceOut.client.id } }"
|
||||||
|
>
|
||||||
|
<q-tooltip>{{ t('invoiceOut.card.customerCard') }}</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
<q-btn size="md" icon="vn:ticket" color="primary" :to="{ name: 'TicketList', params: { q: filter } }">
|
||||||
|
<q-tooltip>{{ t('invoiceOut.card.ticketList') }}</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</q-card-actions>
|
||||||
|
</template>
|
||||||
|
</card-descriptor>
|
||||||
|
</template>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<script setup>
|
||||||
|
import InvoiceOutDescriptor from './InvoiceOutDescriptor.vue';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<q-card>
|
||||||
|
<invoiceOut-descriptor v-if="$props.id" :id="$props.id" />
|
||||||
|
</q-card>
|
||||||
|
</template>
|
|
@ -0,0 +1,201 @@
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref, computed } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
|
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
|
||||||
|
onMounted(() => fetch());
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const entityId = computed(() => $props.id || route.params.id);
|
||||||
|
|
||||||
|
const invoiceOut = ref(null);
|
||||||
|
const tax = ref(null);
|
||||||
|
const tikets = ref(null);
|
||||||
|
|
||||||
|
function fetch() {
|
||||||
|
const id = entityId.value;
|
||||||
|
|
||||||
|
axios.get(`InvoiceOuts/${id}/summary`).then(({ data }) => {
|
||||||
|
invoiceOut.value = data.invoiceOut;
|
||||||
|
tax.value = data.invoiceOut.taxesBreakdown;
|
||||||
|
console.log('tax', tax);
|
||||||
|
});
|
||||||
|
|
||||||
|
axios.get(`InvoiceOuts/${id}/getTickets`).then(({ data }) => {
|
||||||
|
tikets.value = data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const taxColumns = ref([
|
||||||
|
{
|
||||||
|
name: 'item',
|
||||||
|
label: 'invoiceOut.summary.type',
|
||||||
|
field: (row) => row.name,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'landed',
|
||||||
|
label: 'invoiceOut.summary.taxableBase',
|
||||||
|
field: (row) => row.taxableBase,
|
||||||
|
format: (value) => toCurrency(value),
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'quantity',
|
||||||
|
label: 'invoiceOut.summary.rate',
|
||||||
|
field: (row) => row.rate,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'invoiceOuted',
|
||||||
|
label: 'invoiceOut.summary.fee',
|
||||||
|
field: (row) => row.vat,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const ticketsColumns = ref([
|
||||||
|
{
|
||||||
|
name: 'item',
|
||||||
|
label: 'invoiceOut.summary.ticketId',
|
||||||
|
field: (row) => row.id,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'quantity',
|
||||||
|
label: 'invoiceOut.summary.nickname',
|
||||||
|
field: (row) => row.nickname,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'landed',
|
||||||
|
label: 'invoiceOut.summary.shipped',
|
||||||
|
field: (row) => row.shipped,
|
||||||
|
format: (value) => toDate(value),
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'landed',
|
||||||
|
label: 'invoiceOut.summary.totalWithVat',
|
||||||
|
field: (row) => row.totalWithVat,
|
||||||
|
format: (value) => toCurrency(value),
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="summary container">
|
||||||
|
<q-card>
|
||||||
|
<skeleton-summary v-if="!invoiceOut" />
|
||||||
|
<template v-if="invoiceOut">
|
||||||
|
<div class="header bg-primary q-pa-sm q-mb-md">
|
||||||
|
{{ invoiceOut.ref }} - {{ invoiceOut.client.socialName }}
|
||||||
|
</div>
|
||||||
|
<q-list>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.summary.issued') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(invoiceOut.issued) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.summary.dued') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(invoiceOut.dued) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.summary.created') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(invoiceOut.created) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.summary.booked') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(invoiceOut.booked) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.summary.company') }}</q-item-label>
|
||||||
|
<q-item-label>{{ invoiceOut.company.code }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
<q-card-section class="q-pa-md">
|
||||||
|
<h6>{{ t('invoiceOut.summary.taxBreakdown') }}</h6>
|
||||||
|
<q-table :columns="taxColumns" :rows="tax" flat>
|
||||||
|
<template #header="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
||||||
|
{{ t(col.label) }}
|
||||||
|
</q-th>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section class="q-pa-md">
|
||||||
|
<h6>{{ t('invoiceOut.summary.tickets') }}</h6>
|
||||||
|
<q-table :columns="ticketsColumns" :rows="tikets" flat>
|
||||||
|
<template #header="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
||||||
|
{{ t(col.label) }}
|
||||||
|
</q-th>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</q-card-section>
|
||||||
|
</template>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-card {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 950px;
|
||||||
|
max-width: 950px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary {
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#slider-container {
|
||||||
|
max-width: 80%;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
.q-slider {
|
||||||
|
.q-slider__marker-labels:nth-child(1) {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
.q-slider__marker-labels:nth-child(2) {
|
||||||
|
transform: none;
|
||||||
|
left: auto !important;
|
||||||
|
right: 0%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-dialog .summary {
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<script setup>
|
||||||
|
import { useDialogPluginComponent } from 'quasar';
|
||||||
|
import InvoiceOutSummary from './InvoiceOutSummary.vue';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
defineEmits([...useDialogPluginComponent.emits]);
|
||||||
|
|
||||||
|
const { dialogRef, onDialogHide } = useDialogPluginComponent();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
||||||
|
<invoiceOut-summary v-if="$props.id" :id="$props.id" />
|
||||||
|
</q-dialog>
|
||||||
|
</template>
|
|
@ -0,0 +1,83 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
|
import Paginate from 'src/components/Paginate.vue';
|
||||||
|
import InvoiceOutSummaryDialog from './Card/InvoiceOutSummaryDialog.vue';
|
||||||
|
import { toDate, toCurrency } from 'src/filters/index';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const quasar = useQuasar();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
function navigate(id) {
|
||||||
|
router.push({ path: `/invoiceOut/${id}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewSummary(id) {
|
||||||
|
quasar.dialog({
|
||||||
|
component: InvoiceOutSummaryDialog,
|
||||||
|
componentProps: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-page class="q-pa-md">
|
||||||
|
<paginate url="/InvoiceOuts/filter" sort-by="issued DESC, id DESC" auto-load>
|
||||||
|
<template #body="{ rows }">
|
||||||
|
<q-card class="card" v-for="row of rows" :key="row.id">
|
||||||
|
<q-item class="q-pa-none items-start cursor-pointer q-hoverable" v-ripple clickable>
|
||||||
|
<q-item-section class="q-pa-md" @click="navigate(row.id)">
|
||||||
|
<div class="text-h6">{{ row.ref }}</div>
|
||||||
|
<q-item-label caption>#{{ row.id }}</q-item-label>
|
||||||
|
<q-list>
|
||||||
|
<q-item class="q-pa-none">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.list.issued') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(row.issued) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.list.amount') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toCurrency(row.amount) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="q-pa-none">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.list.client') }}</q-item-label>
|
||||||
|
<q-item-label>{{ row.clientSocialName }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.list.created') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(row.created) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="q-pa-none">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.list.company') }}</q-item-label>
|
||||||
|
<q-item-label>{{ row.companyCode }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('invoiceOut.list.dued') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(row.dued) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-item-section>
|
||||||
|
<q-separator vertical />
|
||||||
|
<q-card-actions vertical class="justify-between">
|
||||||
|
<q-btn flat round color="orange" icon="arrow_circle_right" @click="navigate(row.id)">
|
||||||
|
<q-tooltip>{{ t('components.smartCard.openCard') }}</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
<q-btn flat round color="grey-7" icon="preview" @click="viewSummary(row.id)">
|
||||||
|
<q-tooltip>{{ t('components.smartCard.openSummary') }}</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-item>
|
||||||
|
</q-card>
|
||||||
|
</template>
|
||||||
|
</paginate>
|
||||||
|
</q-page>
|
||||||
|
</template>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<script setup>
|
||||||
|
import { useState } from 'src/composables/useState';
|
||||||
|
import LeftMenu from 'src/components/LeftMenu.vue';
|
||||||
|
|
||||||
|
const state = useState();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-drawer v-model="state.drawer.value" show-if-above :width="256" :breakpoint="500">
|
||||||
|
<q-scroll-area class="fit text-grey-8">
|
||||||
|
<LeftMenu />
|
||||||
|
</q-scroll-area>
|
||||||
|
</q-drawer>
|
||||||
|
<q-page-container>
|
||||||
|
<router-view></router-view>
|
||||||
|
</q-page-container>
|
||||||
|
</template>
|
|
@ -0,0 +1,553 @@
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref, computed, onUpdated } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { dashIfEmpty, toDate, toCurrency } from 'src/filters';
|
||||||
|
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
import FetchedTags from 'components/ui/FetchedTags.vue';
|
||||||
|
|
||||||
|
onMounted(() => fetch());
|
||||||
|
onUpdated(() => fetch());
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const entityId = computed(() => $props.id || route.params.id);
|
||||||
|
|
||||||
|
const ticket = ref();
|
||||||
|
const salesLines = ref(null);
|
||||||
|
const editableStates = ref([]);
|
||||||
|
async function fetch() {
|
||||||
|
const { data } = await axios.get(`Tickets/${entityId.value}/summary`);
|
||||||
|
if (data) {
|
||||||
|
ticket.value = data;
|
||||||
|
salesLines.value = data.sales;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stateColor(state) {
|
||||||
|
if (state.code === 'OK') return 'text-green';
|
||||||
|
if (state.code === 'FREE') return 'text-blue-3';
|
||||||
|
if (state.alertLevel === 1) return 'text-primary';
|
||||||
|
if (state.alertLevel === 0) return 'text-red';
|
||||||
|
}
|
||||||
|
|
||||||
|
function formattedAddress() {
|
||||||
|
if (!ticket.value) return '';
|
||||||
|
|
||||||
|
const address = this.ticket.address;
|
||||||
|
const postcode = address.postalCode;
|
||||||
|
const province = address.province ? `(${address.province.name})` : '';
|
||||||
|
|
||||||
|
return `${address.street} - ${postcode} - ${address.city} ${province}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEditable() {
|
||||||
|
try {
|
||||||
|
return !this.ticket.ticketState.state.alertLevel;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changeState(value) {
|
||||||
|
if (!this.ticket.id) return;
|
||||||
|
|
||||||
|
const formData = {
|
||||||
|
ticketFk: this.ticket.id,
|
||||||
|
code: value,
|
||||||
|
};
|
||||||
|
|
||||||
|
await axios.post(`TicketTrackings/changeState`, formData);
|
||||||
|
await router.go(route.fullPath);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<fetch-data url="States/editableStates" @on-fetch="(data) => (editableStates = data)" auto-load />
|
||||||
|
<div class="summary container">
|
||||||
|
<q-card>
|
||||||
|
<skeleton-summary v-if="!ticket" />
|
||||||
|
<template v-if="ticket">
|
||||||
|
<div class="header bg-primary q-pa-sm q-mb-md">
|
||||||
|
<span>
|
||||||
|
Ticket #{{ ticket.id }} - {{ ticket.client.name }} ({{ ticket.client.id }}) -
|
||||||
|
{{ ticket.nickname }}
|
||||||
|
</span>
|
||||||
|
<q-btn-dropdown
|
||||||
|
side
|
||||||
|
top
|
||||||
|
color="orange-11"
|
||||||
|
text-color="black"
|
||||||
|
:label="t('ticket.summary.changeState')"
|
||||||
|
:disable="!isEditable()"
|
||||||
|
>
|
||||||
|
<q-list>
|
||||||
|
<q-virtual-scroll
|
||||||
|
style="max-height: 300px"
|
||||||
|
:items="editableStates"
|
||||||
|
separator
|
||||||
|
v-slot="{ item, index }"
|
||||||
|
>
|
||||||
|
<q-item :key="index" dense clickable v-close-popup @click="changeState(item.code)">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{ item.name }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-virtual-scroll>
|
||||||
|
</q-list>
|
||||||
|
</q-btn-dropdown>
|
||||||
|
</div>
|
||||||
|
<div class="row q-pa-md q-col-gutter-md q-mb-md">
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.state') }}</q-item-label>
|
||||||
|
<q-item-label :class="stateColor(ticket.ticketState.state)">
|
||||||
|
{{ ticket.ticketState.state.name }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.salesPerson') }}</q-item-label>
|
||||||
|
<q-item-label class="link">{{ ticket.client.salesPersonUser.name }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.agency') }}</q-item-label>
|
||||||
|
<q-item-label>{{ ticket.agencyMode.name }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.zone') }}</q-item-label>
|
||||||
|
<q-item-label class="link">{{ ticket.routeFk }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.warehouse') }}</q-item-label>
|
||||||
|
<q-item-label>{{ ticket.warehouse.name }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.invoice') }}</q-item-label>
|
||||||
|
<q-item-label v-if="ticket.refFk" class="link">{{ ticket.refFk }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.shipped') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(ticket.shipped) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.landed') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(ticket.landed) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.packages') }}</q-item-label>
|
||||||
|
<q-item-label>{{ ticket.packages }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.consigneePhone') }}</q-item-label>
|
||||||
|
<q-item-label>{{ ticket.address.phone }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.consigneeMobile') }}</q-item-label>
|
||||||
|
<q-item-label>{{ ticket.address.mobile }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.clientPhone') }}</q-item-label>
|
||||||
|
<q-item-label>{{ ticket.client.phone }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.clientMobile') }}</q-item-label>
|
||||||
|
<q-item-label>{{ ticket.client.mobile }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.consignee') }}</q-item-label>
|
||||||
|
<q-item-label>{{ formattedAddress() }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item v-for="note in ticket.notes" :key="note.id">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ note.observationType.description }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ note.description }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-list class="taxes">
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.subtotal') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toCurrency(ticket.totalWithoutVat) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.vat') }}</q-item-label>
|
||||||
|
<q-item-label>{{
|
||||||
|
toCurrency(ticket.totalWithVat - ticket.totalWithoutVat)
|
||||||
|
}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>{{ t('ticket.summary.total') }}</q-item-label>
|
||||||
|
<q-item-label>{{ toCurrency(ticket.totalWithVat) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row q-pa-md" v-if="salesLines.length > 0">
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('ticket.summary.saleLines') }}
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'TicketBasicData', params: { id: entityId } }"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<q-icon name="open_in_new" />
|
||||||
|
</router-link>
|
||||||
|
</q-item-label>
|
||||||
|
<q-table :rows="ticket.sales" flat>
|
||||||
|
<template #header="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-th auto-width></q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.item') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.visible') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.available') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.quantity') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.description') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.price') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.discount') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.amount') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.packing') }}</q-th>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
<template #body="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-td>
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
size="xs"
|
||||||
|
icon="vn:claims"
|
||||||
|
v-if="props.row.claim"
|
||||||
|
color="primary"
|
||||||
|
:to="{ name: 'ClaimCard', params: { id: props.row.claim.claimFk } }"
|
||||||
|
>
|
||||||
|
<q-tooltip
|
||||||
|
>{{ t('ticket.summary.claim') }}:
|
||||||
|
{{ props.row.claim.claimFk }}</q-tooltip
|
||||||
|
>
|
||||||
|
</q-btn>
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
size="xs"
|
||||||
|
icon="vn:claims"
|
||||||
|
v-if="props.row.claimBeginning"
|
||||||
|
color="primary"
|
||||||
|
:to="{
|
||||||
|
name: 'ClaimCard',
|
||||||
|
params: { id: props.row.claimBeginning.claimFk },
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<q-tooltip
|
||||||
|
>{{ t('ticket.summary.claim') }}:
|
||||||
|
{{ props.row.claimBeginning.claimFk }}</q-tooltip
|
||||||
|
>
|
||||||
|
</q-btn>
|
||||||
|
<q-icon
|
||||||
|
name="warning"
|
||||||
|
v-show="props.row.visible < 0"
|
||||||
|
size="xs"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<q-tooltip
|
||||||
|
>{{ t('ticket.summary.visible') }}:
|
||||||
|
{{ props.row.visible }}</q-tooltip
|
||||||
|
>
|
||||||
|
</q-icon>
|
||||||
|
<q-icon
|
||||||
|
name="vn:reserva"
|
||||||
|
v-show="props.row.reserved"
|
||||||
|
size="xs"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<q-tooltip>{{ t('ticket.summary.reserved') }}</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
|
<q-icon
|
||||||
|
name="vn:unavailable"
|
||||||
|
v-show="props.row.itemShortage"
|
||||||
|
size="xs"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<q-tooltip>{{ t('ticket.summary.itemShortage') }}</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
|
<q-icon
|
||||||
|
name="vn:components"
|
||||||
|
v-show="props.row.hasComponentLack"
|
||||||
|
size="xs"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<q-tooltip>{{ t('ticket.summary.hasComponentLack') }}</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
|
</q-td>
|
||||||
|
<q-td class="link">{{ props.row.itemFk }}</q-td>
|
||||||
|
<q-td>{{ props.row.visible }}</q-td>
|
||||||
|
<q-td>{{ props.row.available }}</q-td>
|
||||||
|
<q-td>{{ props.row.quantity }}</q-td>
|
||||||
|
<q-td>
|
||||||
|
<div class="fetched-tags">
|
||||||
|
<span>{{ props.row.item.name }}</span>
|
||||||
|
<span v-if="props.row.item.subName" class="subName">{{
|
||||||
|
props.row.item.subName
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
<fetched-tags :item="props.row.item" :max-length="5"></fetched-tags>
|
||||||
|
</q-td>
|
||||||
|
<q-td>{{ props.row.price }}</q-td>
|
||||||
|
<q-td>{{ props.row.discount }} %</q-td>
|
||||||
|
<q-td
|
||||||
|
>{{
|
||||||
|
toCurrency(
|
||||||
|
props.row.quantity *
|
||||||
|
props.row.price *
|
||||||
|
((100 - props.row.discount) / 100)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</q-td>
|
||||||
|
<q-td>{{ dashIfEmpty(props.row.item.itemPackingTypeFk) }}</q-td>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row q-pa-md" v-if="ticket.packagings.length > 0 || ticket.services.length > 0">
|
||||||
|
<div class="col" v-if="ticket.packagings.length > 0">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('ticket.summary.packages') }}
|
||||||
|
<q-icon name="open_in_new" />
|
||||||
|
</q-item-label>
|
||||||
|
<q-table :rows="ticket.packagings" flat>
|
||||||
|
<template #header="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.created') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.package') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.quantity') }}</q-th>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
<template #body="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-td>{{ toDate(props.row.created) }}</q-td>
|
||||||
|
<q-td>{{ props.row.packaging.item.name }}</q-td>
|
||||||
|
<q-td>{{ props.row.quantity }}</q-td>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col" v-if="ticket.services.length > 0">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('ticket.summary.services') }}
|
||||||
|
<q-icon name="open_in_new" />
|
||||||
|
</q-item-label>
|
||||||
|
<q-table :rows="ticket.services" flat>
|
||||||
|
<template #header="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.quantity') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.description') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.price') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.taxClass') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.amount') }}</q-th>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
<template #body="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-td>{{ props.row.quantity }}</q-td>
|
||||||
|
<q-td>{{ props.row.description }}</q-td>
|
||||||
|
<q-td>{{ toCurrency(props.row.price) }}</q-td>
|
||||||
|
<q-td>{{ props.row.taxClass.description }}</q-td>
|
||||||
|
<q-td>{{ toCurrency(props.row.quantity * props.row.price) }}</q-td>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row q-pa-md" v-if="ticket.requests.length > 0">
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('ticket.summary.request') }}
|
||||||
|
<q-icon name="open_in_new" />
|
||||||
|
</q-item-label>
|
||||||
|
<q-table :rows="ticket.requests" flat>
|
||||||
|
<template #header="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.description') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.created') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.requester') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.atender') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.quantity') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.price') }}</q-th>
|
||||||
|
<q-th auto-width>{{ t('ticket.summary.item') }}</q-th>
|
||||||
|
<q-th auto-width>Ok</q-th>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
<template #body="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-td>{{ props.row.description }}</q-td>
|
||||||
|
<q-td>{{ toDate(props.row.created) }}</q-td>
|
||||||
|
<q-td>{{ props.row.requester.user.name }}</q-td>
|
||||||
|
<q-td>{{ props.row.atender.user.name }}</q-td>
|
||||||
|
<q-td>{{ props.row.quantity }}</q-td>
|
||||||
|
<q-td>{{ toCurrency(props.row.price) }}</q-td>
|
||||||
|
<q-td v-if="!props.row.sale">-</q-td>
|
||||||
|
<q-td v-if="props.row.sale" class="link">{{ props.row.sale.itemFk }}</q-td>
|
||||||
|
<q-td><q-checkbox v-model="props.row.isOk" :disable="true" /></q-td>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-card {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary {
|
||||||
|
.q-list {
|
||||||
|
.q-item__label--header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fetched-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
& span {
|
||||||
|
flex-basis: 50%;
|
||||||
|
}
|
||||||
|
& span.subName {
|
||||||
|
flex-basis: 50%;
|
||||||
|
color: $secondary;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.q-table__container {
|
||||||
|
text-align: left;
|
||||||
|
.q-icon {
|
||||||
|
padding: 2%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.taxes {
|
||||||
|
border: $border-thin-light;
|
||||||
|
text-align: right;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.col {
|
||||||
|
min-width: 250px;
|
||||||
|
padding-left: 1.5%;
|
||||||
|
padding-right: 1.5%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
font-size: 18px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-btn {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.q-dialog .summary {
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<script setup>
|
||||||
|
import { useDialogPluginComponent } from 'quasar';
|
||||||
|
import TicketSummary from './TicketSummary.vue';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
defineEmits([...useDialogPluginComponent.emits]);
|
||||||
|
|
||||||
|
const { dialogRef, onDialogHide } = useDialogPluginComponent();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
||||||
|
<ticket-summary v-if="$props.id" :id="$props.id" />
|
||||||
|
</q-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.q-dialog .summary .header {
|
||||||
|
position: sticky;
|
||||||
|
z-index: $z-max;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,12 +1,13 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import Paginate from 'components/Paginate.vue';
|
import Paginate from 'components/Paginate.vue';
|
||||||
import { toDate, toCurrency } from 'src/filters/index';
|
import { toDate, toCurrency } from 'src/filters/index';
|
||||||
// import TicketSummary from './Card/TicketSummary.vue';
|
import TicketSummaryDialog from './Card/TicketSummaryDialog.vue';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const quasar = useQuasar();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
|
@ -48,15 +49,13 @@ function navigate(id) {
|
||||||
router.push({ path: `/ticket/${id}` });
|
router.push({ path: `/ticket/${id}` });
|
||||||
}
|
}
|
||||||
|
|
||||||
const preview = ref({
|
function viewSummary(id) {
|
||||||
shown: false,
|
quasar.dialog({
|
||||||
});
|
component: TicketSummaryDialog,
|
||||||
|
componentProps: {
|
||||||
function showPreview(id) {
|
id,
|
||||||
preview.value.shown = true;
|
},
|
||||||
preview.value.data = {
|
});
|
||||||
customerId: id,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -108,42 +107,16 @@ function showPreview(id) {
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-separator vertical />
|
<q-separator vertical />
|
||||||
<q-card-actions vertical class="justify-between">
|
<q-card-actions vertical class="justify-between">
|
||||||
<!-- <q-btn color="grey-7" round flat icon="more_vert">
|
|
||||||
<q-tooltip>{{ t('customer.list.moreOptions') }}</q-tooltip>
|
|
||||||
<q-menu cover auto-close>
|
|
||||||
<q-list>
|
|
||||||
<q-item clickable>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-icon name="add" />
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section>Add a note</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-icon name="history" />
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section>Display customer history</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-menu>
|
|
||||||
</q-btn> -->
|
|
||||||
|
|
||||||
<q-btn flat round color="orange" icon="arrow_circle_right" @click="navigate(row.id)">
|
<q-btn flat round color="orange" icon="arrow_circle_right" @click="navigate(row.id)">
|
||||||
<q-tooltip>{{ t('components.smartCard.openCard') }}</q-tooltip>
|
<q-tooltip>{{ t('components.smartCard.openCard') }}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-btn flat round color="grey-7" icon="preview" @click="showPreview(row.id)">
|
<q-btn flat round color="grey-7" icon="preview" @click="viewSummary(row.id)">
|
||||||
<q-tooltip>{{ t('components.smartCard.openSummary') }}</q-tooltip>
|
<q-tooltip>{{ t('components.smartCard.openSummary') }}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<!-- <q-btn flat round color="grey-7" icon="vn:ticket">
|
|
||||||
<q-tooltip>{{ t('customer.list.customerOrders') }}</q-tooltip>
|
|
||||||
</q-btn> -->
|
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-card>
|
</q-card>
|
||||||
</template>
|
</template>
|
||||||
</paginate>
|
</paginate>
|
||||||
</q-page>
|
</q-page>
|
||||||
<!-- <q-dialog v-model="preview.shown">
|
|
||||||
<customer-summary :customer-id="preview.data.customerId" />
|
|
||||||
</q-dialog> -->
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { i18n } from 'src/boot/i18n';
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
import { useSession } from 'src/composables/useSession';
|
import { useSession } from 'src/composables/useSession';
|
||||||
import { useRole } from 'src/composables/useRole';
|
import { useRole } from 'src/composables/useRole';
|
||||||
|
import { toLowerCamel } from 'src/filters';
|
||||||
|
|
||||||
const state = useState();
|
const state = useState();
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
|
@ -24,8 +25,8 @@ export default route(function (/* { store, ssrContext } */) {
|
||||||
const createHistory = process.env.SERVER
|
const createHistory = process.env.SERVER
|
||||||
? createMemoryHistory
|
? createMemoryHistory
|
||||||
: process.env.VUE_ROUTER_MODE === 'history'
|
: process.env.VUE_ROUTER_MODE === 'history'
|
||||||
? createWebHistory
|
? createWebHistory
|
||||||
: createWebHashHistory;
|
: createWebHashHistory;
|
||||||
|
|
||||||
const Router = createRouter({
|
const Router = createRouter({
|
||||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||||
|
@ -45,26 +46,14 @@ export default route(function (/* { store, ssrContext } */) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLoggedIn()) {
|
if (isLoggedIn()) {
|
||||||
// try {
|
|
||||||
const stateRoles = state.getRoles().value;
|
const stateRoles = state.getRoles().value;
|
||||||
if (stateRoles.length === 0) {
|
if (stateRoles.length === 0) {
|
||||||
await role.fetch();
|
await role.fetch();
|
||||||
}
|
}
|
||||||
// } catch (error) {
|
|
||||||
// Notify.create({
|
|
||||||
// message: t('errors.statusUnauthorized'),
|
|
||||||
// type: 'negative',
|
|
||||||
// });
|
|
||||||
|
|
||||||
// session.destroy();
|
|
||||||
// return next({ path: '/login' });
|
|
||||||
// }
|
|
||||||
|
|
||||||
const matches = to.matched;
|
const matches = to.matched;
|
||||||
const hasRequiredRoles = matches.every(route => {
|
const hasRequiredRoles = matches.every((route) => {
|
||||||
const meta = route.meta;
|
const meta = route.meta;
|
||||||
if (meta && meta.roles)
|
if (meta && meta.roles) return role.hasAny(meta.roles);
|
||||||
return role.hasAny(meta.roles)
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -84,7 +73,7 @@ export default route(function (/* { store, ssrContext } */) {
|
||||||
if (matches && matches.length > 1) {
|
if (matches && matches.length > 1) {
|
||||||
const module = matches[1];
|
const module = matches[1];
|
||||||
const moduleTitle = module.meta && module.meta.title;
|
const moduleTitle = module.meta && module.meta.title;
|
||||||
moduleName = module.name.toLowerCase();
|
moduleName = toLowerCamel(module.name);
|
||||||
if (moduleTitle) {
|
if (moduleTitle) {
|
||||||
title = t(`${moduleName}.pageTitles.${moduleTitle}`);
|
title = t(`${moduleName}.pageTitles.${moduleTitle}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import Customer from './customer';
|
import Customer from './customer';
|
||||||
import Ticket from './ticket';
|
import Ticket from './ticket';
|
||||||
import Claim from './claim';
|
import Claim from './claim';
|
||||||
|
import InvoiceOut from './invoiceOut';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
Customer,
|
Customer,
|
||||||
Ticket,
|
Ticket,
|
||||||
Claim
|
Claim,
|
||||||
|
InvoiceOut
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { RouterView } from 'vue-router';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
path: '/invoiceOut',
|
||||||
|
name: 'InvoiceOut',
|
||||||
|
meta: {
|
||||||
|
title: 'invoiceOuts',
|
||||||
|
icon: 'vn:invoice-out'
|
||||||
|
},
|
||||||
|
component: RouterView,
|
||||||
|
redirect: { name: 'InvoiceOutMain' },
|
||||||
|
menus: {
|
||||||
|
main: ['InvoiceOutList']
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: 'InvoiceOutMain',
|
||||||
|
component: () => import('src/pages/InvoiceOut/InvoiceOutMain.vue'),
|
||||||
|
redirect: { name: 'InvoiceOutList' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'list',
|
||||||
|
name: 'InvoiceOutList',
|
||||||
|
meta: {
|
||||||
|
title: 'list',
|
||||||
|
icon: 'view_list',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/InvoiceOut/InvoiceOutList.vue'),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'InvoiceOutCard',
|
||||||
|
path: ':id',
|
||||||
|
component: () => import('src/pages/InvoiceOut/Card/InvoiceOutCard.vue'),
|
||||||
|
redirect: { name: 'InvoiceOutSummary' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'InvoiceOutSummary',
|
||||||
|
path: 'summary',
|
||||||
|
meta: {
|
||||||
|
title: 'summary'
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/InvoiceOut/Card/InvoiceOutSummary.vue'),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
};
|
|
@ -1,6 +1,7 @@
|
||||||
import customer from './modules/customer';
|
import customer from './modules/customer';
|
||||||
import ticket from './modules/ticket';
|
import ticket from './modules/ticket';
|
||||||
import claim from './modules/claim';
|
import claim from './modules/claim';
|
||||||
|
import invoiceOut from './modules/invoiceOut';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
|
@ -25,6 +26,7 @@ const routes = [
|
||||||
customer,
|
customer,
|
||||||
ticket,
|
ticket,
|
||||||
claim,
|
claim,
|
||||||
|
invoiceOut,
|
||||||
{
|
{
|
||||||
path: '/:pathMatch(.*)*',
|
path: '/:pathMatch(.*)*',
|
||||||
name: 'NotFound',
|
name: 'NotFound',
|
||||||
|
@ -34,4 +36,4 @@ const routes = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export default routes;
|
export default routes;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { useRole } from 'src/composables/useRole';
|
||||||
import routes from 'src/router/modules';
|
import routes from 'src/router/modules';
|
||||||
|
|
||||||
export const useNavigationStore = defineStore('navigationStore', () => {
|
export const useNavigationStore = defineStore('navigationStore', () => {
|
||||||
const modules = ['customer', 'claim', 'ticket'];
|
const modules = ['customer', 'claim', 'ticket', 'invoiceOut'];
|
||||||
const pinnedModules = ref([]);
|
const pinnedModules = ref([]);
|
||||||
const role = useRole();
|
const role = useRole();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue