forked from verdnatura/salix-front
Merge branch 'dev' into 4833-new_module_invoiceOut
This commit is contained in:
commit
6c2a1d95b4
|
@ -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;
|
||||||
|
}
|
|
@ -2,10 +2,12 @@ import toLowerCase from './toLowerCase';
|
||||||
import toDate from './toDate';
|
import toDate from './toDate';
|
||||||
import toCurrency from './toCurrency';
|
import toCurrency from './toCurrency';
|
||||||
import toPercentage from './toPercentage';
|
import toPercentage from './toPercentage';
|
||||||
|
import dashIfEmpty from './dashIfEmpty';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
toLowerCase,
|
toLowerCase,
|
||||||
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: {
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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,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>
|
||||||
|
|
Loading…
Reference in New Issue