fix: refs #7553 & #7356 migration
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
This commit is contained in:
parent
954a6ff6c0
commit
4a57c53c3d
|
@ -49,6 +49,10 @@ const $props = defineProps({
|
|||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
bottom: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
cardClass: {
|
||||
type: String,
|
||||
default: 'flex-one',
|
||||
|
@ -388,6 +392,11 @@ defineExpose({
|
|||
@click="stateStore.toggleRightDrawer()"
|
||||
/>
|
||||
</template>
|
||||
<template #top>
|
||||
<div class="full-width-slot">
|
||||
<slot name="before-header" />
|
||||
</div>
|
||||
</template>
|
||||
<template #header-cell="{ col }">
|
||||
<QTh v-if="col.visible ?? true">
|
||||
<div
|
||||
|
@ -482,6 +491,9 @@ defineExpose({
|
|||
/>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #bottom v-if="bottom">
|
||||
<slot name="bottom-table" />
|
||||
</template>
|
||||
<template #item="{ row, colsMap }">
|
||||
<component
|
||||
:is="$props.redirect ? 'router-link' : 'span'"
|
||||
|
@ -780,4 +792,13 @@ es:
|
|||
cursor: text;
|
||||
user-select: all;
|
||||
}
|
||||
|
||||
.full-width-slot {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
color: var(--vn-text-color);
|
||||
margin-bottom: -1%;
|
||||
background-color: var(--vn-header-color);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -28,7 +28,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
delete params.filter;
|
||||
store.userParams = { ...params, ...store.userParams };
|
||||
store.userFilter = { ...filter, ...store.userFilter };
|
||||
if (filter.order) store.order = filter.order;
|
||||
if (filter?.order) store.order = filter.order;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -578,6 +578,8 @@ ticket:
|
|||
warehouse: Warehouse
|
||||
customerCard: Customer card
|
||||
alias: Alias
|
||||
ticketList: Ticket List
|
||||
newOrder: New Order
|
||||
boxing:
|
||||
expedition: Expedition
|
||||
item: Item
|
||||
|
@ -628,6 +630,11 @@ ticket:
|
|||
weight: Weight
|
||||
goTo: Go to
|
||||
summaryAmount: Summary
|
||||
purchaseRequest: Purchase request
|
||||
service: Service
|
||||
description: Description
|
||||
attender: Attender
|
||||
ok: Ok
|
||||
create:
|
||||
client: Client
|
||||
address: Address
|
||||
|
@ -651,7 +658,6 @@ invoiceOut:
|
|||
client: Client
|
||||
company: Company
|
||||
customerCard: Customer card
|
||||
ticketList: Ticket List
|
||||
summary:
|
||||
issued: Issued
|
||||
created: Created
|
||||
|
|
|
@ -584,6 +584,8 @@ ticket:
|
|||
warehouse: Almacén
|
||||
customerCard: Ficha del cliente
|
||||
alias: Alias
|
||||
ticketList: Listado de tickets
|
||||
newOrder: Nuevo pedido
|
||||
boxing:
|
||||
expedition: Expedición
|
||||
item: Artículo
|
||||
|
@ -634,6 +636,10 @@ ticket:
|
|||
weight: Peso
|
||||
goTo: Ir a
|
||||
summaryAmount: Resumen
|
||||
purchaseRequest: Petición de compra
|
||||
service: Servicio
|
||||
description: Descripción
|
||||
attender: Comprador
|
||||
create:
|
||||
client: Cliente
|
||||
address: Dirección
|
||||
|
|
|
@ -87,6 +87,11 @@ const filter = {
|
|||
};
|
||||
|
||||
const data = ref(useCardDescription());
|
||||
|
||||
function ticketFilter(ticket) {
|
||||
console.log('ticket: ', ticket);
|
||||
return JSON.stringify({ clientFk: ticket.clientFk });
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -159,6 +164,22 @@ const data = ref(useCardDescription());
|
|||
>
|
||||
<QTooltip>{{ t('ticket.card.customerCard') }}</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
size="md"
|
||||
icon="vn:ticket"
|
||||
color="primary"
|
||||
:to="{ name: 'TicketList', query: { table: ticketFilter(entity) } }"
|
||||
>
|
||||
<QTooltip>{{ t('ticket.card.ticketList') }}</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
size="md"
|
||||
icon="vn:basketadd"
|
||||
color="primary"
|
||||
:to="{ name: 'OrderList' }"
|
||||
>
|
||||
<QTooltip>{{ t('ticket.card.newOrder') }}</QTooltip>
|
||||
</QBtn>
|
||||
</QCardActions>
|
||||
</template>
|
||||
</CardDescriptor>
|
||||
|
|
|
@ -24,6 +24,7 @@ const { openReport, sendEmail } = usePrintService();
|
|||
|
||||
const ticket = ref(props.ticket);
|
||||
const ticketId = currentRoute.value.params.id;
|
||||
const showWeightDialog = ref(false);
|
||||
const actions = {
|
||||
clone: async () => {
|
||||
const opts = { message: t('Ticket cloned'), type: 'positive' };
|
||||
|
@ -153,30 +154,66 @@ function openConfirmDialog(callback) {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
function createPdfDialog() {
|
||||
dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
promise: createPdfInvoice,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function createPdfInvoice() {
|
||||
const { data } = await axios.get('invoiceOuts', {
|
||||
params: {
|
||||
filter: JSON.stringify({
|
||||
where: { ref: ticket.value.refFk },
|
||||
}),
|
||||
},
|
||||
});
|
||||
const invoiceId = data[0].id;
|
||||
const { response } = await axios.post(`InvoiceOuts/${invoiceId}/createPdf`);
|
||||
if (!response) {
|
||||
notify({
|
||||
message: 'The invoice PDF document has been regenerated',
|
||||
type: 'positive',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setWeightToTicket(weight) {
|
||||
console.log('weight: ', weight);
|
||||
const { data } = axios.patch(`Tickets/${ticketId}`, {
|
||||
weight: weight,
|
||||
});
|
||||
console.log('data: ', data);
|
||||
if (data) window.location.reload();
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<QItem v-ripple clickable>
|
||||
<QItemSection avatar>
|
||||
<QIcon name="picture_as_pdf" />
|
||||
</QItemSection>
|
||||
<QItemSection>{{ t('Open Delivery Note...') }}</QItemSection>
|
||||
<QItemSection>{{ t('Show Delivery Note...') }}</QItemSection>
|
||||
<QItemSection side>
|
||||
<QIcon name="keyboard_arrow_right" />
|
||||
</QItemSection>
|
||||
<QMenu anchor="top end" self="top start" auto-close bordered>
|
||||
<QList>
|
||||
<QItem @click="openDeliveryNote('deliveryNote')" v-ripple clickable>
|
||||
<QItemSection>{{ t('With prices') }}</QItemSection>
|
||||
<QItemSection>{{ t('as PDF') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem @click="openDeliveryNote('withoutPrices')" v-ripple clickable>
|
||||
<QItemSection>{{ t('Without prices') }}</QItemSection>
|
||||
<QItemSection>{{ t('as PDF without prices') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
@click="openDeliveryNote('deliveryNote', 'csv')"
|
||||
v-ripple
|
||||
clickable
|
||||
>
|
||||
<QItemSection>{{ t('As CSV') }}</QItemSection>
|
||||
<QItemSection>{{ t('as CSV') }}</QItemSection>
|
||||
</QItem>
|
||||
</QList>
|
||||
</QMenu>
|
||||
|
@ -196,21 +233,21 @@ function openConfirmDialog(callback) {
|
|||
v-ripple
|
||||
clickable
|
||||
>
|
||||
<QItemSection>{{ t('With prices') }}</QItemSection>
|
||||
<QItemSection>{{ t('Send PDF') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
@click="sendDeliveryNoteConfirmation('withoutPrices')"
|
||||
v-ripple
|
||||
clickable
|
||||
>
|
||||
<QItemSection>{{ t('Without prices') }}</QItemSection>
|
||||
<QItemSection>{{ t('Send PDF to tablet') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
@click="sendDeliveryNoteConfirmation('deliveryNote', 'csv')"
|
||||
v-ripple
|
||||
clickable
|
||||
>
|
||||
<QItemSection>{{ t('As CSV') }}</QItemSection>
|
||||
<QItemSection>{{ t('Send CSV') }}</QItemSection>
|
||||
</QItem>
|
||||
</QList>
|
||||
</QMenu>
|
||||
|
@ -219,7 +256,7 @@ function openConfirmDialog(callback) {
|
|||
<QItemSection avatar>
|
||||
<QIcon name="receipt" />
|
||||
</QItemSection>
|
||||
<QItemSection>{{ t('Open Proforma Invoice') }}</QItemSection>
|
||||
<QItemSection>{{ t('Show Proforma') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-ripple clickable>
|
||||
<QItemSection avatar>
|
||||
|
@ -235,24 +272,54 @@ function openConfirmDialog(callback) {
|
|||
<QItemSection>{{ t('Pending payment') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem @click="showSmsDialog('minAmount')" v-ripple clickable>
|
||||
<QItemSection>{{ t('Minimum amount') }}</QItemSection>
|
||||
<QItemSection>{{ t('Minimum import') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
@click="showSmsDialogWithChanges('orderChanges')"
|
||||
v-ripple
|
||||
clickable
|
||||
>
|
||||
<QItemSection>{{ t('Order changes') }}</QItemSection>
|
||||
<QItemSection>{{ t('Notify changes') }}</QItemSection>
|
||||
</QItem>
|
||||
</QList>
|
||||
</QMenu>
|
||||
</QItem>
|
||||
<QItem @click="createPdfDialog()" v-ripple clickable>
|
||||
<QItemSection avatar>
|
||||
<QIcon name="picture_as_pdf" />
|
||||
</QItemSection>
|
||||
<QItemSection>{{ t('Regenerate PDF invoice') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem @click="openConfirmDialog('clone')" v-ripple clickable>
|
||||
<QItemSection avatar>
|
||||
<QIcon name="content_copy" />
|
||||
</QItemSection>
|
||||
<QItemSection>{{ t('To clone ticket') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem @click="showWeightDialog = !showWeightDialog" v-ripple clickable>
|
||||
<QItemSection avatar>
|
||||
<QIcon name="content_paste" />
|
||||
</QItemSection>
|
||||
<QItemSection>{{ t('Set ticket weight') }}</QItemSection>
|
||||
</QItem>
|
||||
<QDialog v-model="showWeightDialog" transition-show="scale" transition-hide="scale">
|
||||
<QCard>
|
||||
<QCardSection>
|
||||
<QInput
|
||||
v-model="weight"
|
||||
type="number"
|
||||
:label="t('Weight')"
|
||||
@update:model-value="setWeightToTicket"
|
||||
/>
|
||||
<QBtn flat v-close-popup class="text-primary">
|
||||
{{ t('Close') }}
|
||||
</QBtn>
|
||||
<QBTn flat @click="setWeightToTicket" class="text-primary">
|
||||
{{ t('Save') }}
|
||||
</QBTn>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
</QDialog>
|
||||
<template v-if="!ticket.isDeleted">
|
||||
<QSeparator />
|
||||
<QItem @click="openConfirmDialog('remove')" v-ripple clickable>
|
||||
|
@ -266,20 +333,26 @@ function openConfirmDialog(callback) {
|
|||
|
||||
<i18n>
|
||||
es:
|
||||
Open Delivery Note...: Abrir albarán...
|
||||
Show Delivery Note...: Ver albarán...
|
||||
Send Delivery Note...: Enviar albarán...
|
||||
With prices: Con precios
|
||||
Without prices: Sin precios
|
||||
As CSV: Como CSV
|
||||
Open Proforma Invoice: Abrir factura proforma
|
||||
as PDF: como PDF
|
||||
as PDF without prices: como PDF sin precios
|
||||
as CSV: Como CSV
|
||||
Send PDF: Enviar PDF
|
||||
Send PDF to tablet: Enviar PDF a tablet
|
||||
Send CSV: Enviar CSV
|
||||
Show Proforma: Ver proforma
|
||||
Delete ticket: Eliminar ticket
|
||||
Send SMS...: Enviar SMS
|
||||
Pending payment: Pago pendiente
|
||||
Minimum amount: Importe mínimo
|
||||
Order changes: Cambios del pedido
|
||||
Minimum import: Importe mínimo
|
||||
Notify changes: Notificar cambios
|
||||
Ticket deleted: Ticket eliminado
|
||||
You can undo this action within the first hour: Puedes deshacer esta acción dentro de la primera hora
|
||||
To clone ticket: Clonar ticket
|
||||
Ticket cloned: Ticked clonado
|
||||
It was not able to clone the ticket: No se pudo clonar el ticket
|
||||
Regenerate PDF invoice: Regenerar PDF factura
|
||||
The invoice PDF document has been regenerated: El documento PDF de la factura ha sido regenerado
|
||||
Set ticket weight: Establecer peso al ticket
|
||||
</i18n>
|
||||
|
|
|
@ -22,6 +22,7 @@ import { useVnConfirm } from 'composables/useVnConfirm';
|
|||
import useNotify from 'src/composables/useNotify.js';
|
||||
import axios from 'axios';
|
||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
import FormModelPopup from 'src/components/FormModelPopup.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
@ -50,6 +51,9 @@ const transfer = ref({
|
|||
lastActiveTickets: [],
|
||||
sales: [],
|
||||
});
|
||||
const tableRef = ref([]);
|
||||
const formModelPopupRef = ref();
|
||||
const showForm = ref(false);
|
||||
|
||||
watch(
|
||||
() => route.params.id,
|
||||
|
@ -395,7 +399,7 @@ const changeTicketState = async (val) => {
|
|||
};
|
||||
|
||||
const removeSelectedSales = () => {
|
||||
selectedSales.value.forEach((sale) => {
|
||||
selectedRows.value.forEach((sale) => {
|
||||
const index = sales.value.indexOf(sale);
|
||||
sales.value.splice(index, 1);
|
||||
});
|
||||
|
@ -403,17 +407,16 @@ const removeSelectedSales = () => {
|
|||
|
||||
const removeSales = async () => {
|
||||
try {
|
||||
const params = { sales: selectedValidSales.value, ticketId: store.data.id };
|
||||
const params = { sales: selectedRows.value, ticketId: store.data.id };
|
||||
await axios.post('Sales/deleteSales', params);
|
||||
removeSelectedSales();
|
||||
notify('globals.dataSaved', 'positive');
|
||||
window.location.reload();
|
||||
} catch (err) {
|
||||
console.error('Error deleting sales', err);
|
||||
}
|
||||
};
|
||||
|
||||
const insertRow = () => sales.value.push({ ...DEFAULT_EDIT });
|
||||
|
||||
const setTransferParams = async () => {
|
||||
try {
|
||||
const checkedSales = JSON.parse(JSON.stringify(selectedSales.value));
|
||||
|
@ -442,6 +445,15 @@ onMounted(async () => {
|
|||
});
|
||||
|
||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
||||
|
||||
async function save(item) {
|
||||
const { data } = await axios.post(`Tickets/${route.params.id}/addSale`, {
|
||||
id: route.params.id,
|
||||
barcode: item.itemFk,
|
||||
quantity: parseInt(item.quantity),
|
||||
});
|
||||
if (data) window.location.reload();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -455,12 +467,6 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
|||
auto-load
|
||||
@on-fetch="(data) => (isLocked = data)"
|
||||
/>
|
||||
<FetchData
|
||||
url="Items/withName"
|
||||
:filter="{ fields: ['id', 'name'], order: 'id DESC' }"
|
||||
auto-load
|
||||
@on-fetch="(data) => (itemsWithNameOptions = data)"
|
||||
/>
|
||||
<FetchData
|
||||
url="States/editableStates"
|
||||
:filter="{ fields: ['code', 'name', 'id', 'alertLevel'], order: 'name ASC' }"
|
||||
|
@ -560,13 +566,13 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
|||
</QCardSection>
|
||||
</div></QDrawer
|
||||
>
|
||||
<!-- TODO: el botón de añadir filas como está en salix-->
|
||||
<VnTable
|
||||
ref="tableRef"
|
||||
data-key="TicketSales"
|
||||
:url="`Tickets/${route.params.id}/getSales`"
|
||||
:columns="columns"
|
||||
v-model:selected="selectedRows"
|
||||
:bottom="true"
|
||||
:table="{
|
||||
'row-key': 'id',
|
||||
selection: 'multiple',
|
||||
|
@ -625,7 +631,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
|||
</div>
|
||||
</template>
|
||||
<template #column-visible="{ row }">
|
||||
<QBadge :color="row.available < 0 ? 'alert' : 'transparent'" dense>
|
||||
<QBadge :color="row.visible < 0 ? 'alert' : 'transparent'" dense>
|
||||
{{ row.visible }}
|
||||
</QBadge>
|
||||
</template>
|
||||
|
@ -667,7 +673,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
|||
<template #column-price="{ row }">
|
||||
<QTd>
|
||||
<template v-if="isTicketEditable && row.id">
|
||||
<QBtn flat color="primary" dense @click="onOpenEditPricePopover(row)">
|
||||
<QBtn flat class="link" dense @click="onOpenEditPricePopover(row)">
|
||||
{{ toCurrency(row.price) }}
|
||||
</QBtn>
|
||||
<TicketEditManaProxy
|
||||
|
@ -689,12 +695,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
|||
<template #column-discount="{ row }">
|
||||
<QTd>
|
||||
<template v-if="!isLocked && row.id">
|
||||
<QBtn
|
||||
flat
|
||||
color="primary"
|
||||
dense
|
||||
@click="onOpenEditDiscountPopover(row)"
|
||||
>
|
||||
<QBtn flat class="link" dense @click="onOpenEditDiscountPopover(row)">
|
||||
{{ toPercentage(row.discount / 100) }}
|
||||
</QBtn>
|
||||
<TicketEditManaProxy
|
||||
|
@ -715,21 +716,54 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
|||
<template #column-amount="{ row }">
|
||||
{{ toCurrency(row.quantity * row.price) }}
|
||||
</template>
|
||||
<template #bottom-row>
|
||||
<QBtn
|
||||
class="cursor-pointer fill-icon q-ml-md q-my-lg"
|
||||
<template #bottom-table v-if="isTicketEditable">
|
||||
<QIcon
|
||||
@click="showForm = !showForm"
|
||||
class="fill-icon-on-hover"
|
||||
color="primary"
|
||||
icon="add_circle"
|
||||
size="md"
|
||||
round
|
||||
flat
|
||||
:disable="!isTicketEditable"
|
||||
@click="insertRow()"
|
||||
name="add_circle"
|
||||
size="sm"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('Add item') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</QIcon>
|
||||
<QDialog v-model="showForm" transition-show="scale" transition-hide="scale">
|
||||
<FormModelPopup
|
||||
ref="formModelPopupRef"
|
||||
:url-create="`Tickets/${route.params.id}/addSale`"
|
||||
:title="t('New item')"
|
||||
:form-initial-data="{
|
||||
price: 0,
|
||||
discount: 0,
|
||||
visible: 0,
|
||||
available: 0,
|
||||
packaging: null,
|
||||
}"
|
||||
:save-fn="save"
|
||||
>
|
||||
<template #form-inputs="{ data }">
|
||||
<VnSelect
|
||||
url="Items/withName"
|
||||
:option-filter="{
|
||||
order: 'id DESC',
|
||||
}"
|
||||
:fields="['id', 'name']"
|
||||
:label="t('Items')"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
:options="itemsWithNameOptions"
|
||||
hide-selected
|
||||
v-model="data.itemFk"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.quantity"
|
||||
:label="t('Quantity')"
|
||||
type="number"
|
||||
/>
|
||||
</template>
|
||||
</FormModelPopup>
|
||||
</QDialog>
|
||||
</template>
|
||||
</VnTable>
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ const createRefund = async () => {
|
|||
if (!selected.value.length) return;
|
||||
|
||||
const params = {
|
||||
servicesIds: selected.value.map((s) => +s.ticketFk),
|
||||
servicesIds: selected.value.map((s) => +s.id),
|
||||
withWarehouse: false,
|
||||
negative: true,
|
||||
};
|
||||
|
|
|
@ -425,7 +425,7 @@ async function changeState(value) {
|
|||
<VnTitle :url="ticketUrl + 'package'" :text="t('globals.packages')" />
|
||||
<QTable :rows="ticket.packagings" flat>
|
||||
<template #header="props">
|
||||
<QTr :props="props">
|
||||
<QTr class="tr-header" :props="props">
|
||||
<QTh auto-width>{{ t('ticket.summary.created') }}</QTh>
|
||||
<QTh auto-width>{{ t('ticket.summary.package') }}</QTh>
|
||||
<QTh auto-width>{{ t('ticket.summary.quantity') }}</QTh>
|
||||
|
@ -445,7 +445,7 @@ async function changeState(value) {
|
|||
/>
|
||||
<QTable :rows="ticket.services" flat>
|
||||
<template #header="props">
|
||||
<QTr :props="props">
|
||||
<QTr class="tr-header" :props="props">
|
||||
<QTh auto-width>{{ t('ticket.summary.quantity') }}</QTh>
|
||||
<QTh auto-width>{{ t('globals.description') }}</QTh>
|
||||
<QTh auto-width>{{ t('ticket.summary.price') }}</QTh>
|
||||
|
@ -466,6 +466,49 @@ async function changeState(value) {
|
|||
</template>
|
||||
</QTable>
|
||||
</QCard>
|
||||
<QCard class="vn-max" v-if="ticket.requests.length > 0">
|
||||
<VnTitle
|
||||
:url="ticketUrl + 'request'"
|
||||
:text="t('ticket.summary.purchaseRequest')"
|
||||
/>
|
||||
<QTable :rows="ticket.requests" flat>
|
||||
<template #header="props">
|
||||
<QTr class="tr-header" :props="props">
|
||||
<QTh auto-width>{{ t('ticket.summary.description') }}</QTh>
|
||||
<QTh auto-width>{{ t('ticket.summary.created') }}</QTh>
|
||||
<QTh auto-width>{{ t('ticket.summary.requester') }}</QTh>
|
||||
<QTh auto-width>{{ t('ticket.summary.attender') }}</QTh>
|
||||
<QTh auto-width>{{ t('ticket.summary.quantity') }}</QTh>
|
||||
<QTh auto-width>{{ t('ticket.summary.price') }}</QTh>
|
||||
<QTh auto-width>{{ t('ticket.summary.item') }}</QTh>
|
||||
<QTh auto-width>{{ t('ticket.summary.ok') }}</QTh>
|
||||
</QTr>
|
||||
</template>
|
||||
<template #body="props">
|
||||
<QTr :props="props">
|
||||
<QTd>{{ toDate(props.row.created) }}</QTd>
|
||||
<QTd>{{ props.row.description }}</QTd>
|
||||
<QTd>{{ props.row.requester?.user?.username }}</QTd>
|
||||
<QTd>{{ props.row.atender?.user?.username }}</QTd>
|
||||
<QTd>{{ props.row.quantity }}</QTd>
|
||||
<QTd>{{ toCurrency(props.row.price) }}</QTd>
|
||||
<QTd>
|
||||
<span class="link" v-if="props.row.isOk">
|
||||
{{ props.row.itemFk }}
|
||||
<ItemDescriptorProxy :id="props.row.itemFk" />
|
||||
</span>
|
||||
</QTd>
|
||||
<QTd>
|
||||
<QCheckbox
|
||||
v-model="props.row.isOk"
|
||||
disable
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
</QTd>
|
||||
</QTr>
|
||||
</template>
|
||||
</QTable>
|
||||
</QCard>
|
||||
</template>
|
||||
</CardSummary>
|
||||
</template>
|
||||
|
|
|
@ -94,13 +94,11 @@ const openCreateModal = () => createTrackingDialogRef.value.show();
|
|||
:no-data-label="t('globals.noResults')"
|
||||
>
|
||||
<template #body-cell-worker="{ row }">
|
||||
<QTd @click.stop>
|
||||
<span class="link">
|
||||
<QBtn flat>
|
||||
{{ row.user?.name }}
|
||||
<WorkerDescriptorProxy :id="row.user?.worker?.id" />
|
||||
</QBtn>
|
||||
</span>
|
||||
<QTd>
|
||||
<QBtn flat class="link" @click.stop>
|
||||
{{ row.user?.name }}
|
||||
<WorkerDescriptorProxy :id="row.user?.worker?.id" />
|
||||
</QBtn>
|
||||
</QTd>
|
||||
</template>
|
||||
</QTable>
|
||||
|
|
|
@ -134,12 +134,10 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
|||
>
|
||||
<template #body-cell-item="{ row }">
|
||||
<QTd>
|
||||
<span class="link">
|
||||
<QBtn flat>
|
||||
{{ row.itemFk }}
|
||||
<ItemDescriptorProxy :id="row.itemFk" />
|
||||
</QBtn>
|
||||
</span>
|
||||
<QBtn flat class="link" @click.stop>
|
||||
{{ row.itemFk }}
|
||||
<ItemDescriptorProxy :id="row.itemFk" />
|
||||
</QBtn>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-description="{ row }">
|
||||
|
|
|
@ -3,8 +3,8 @@ import { onMounted, ref, computed, reactive } from 'vue';
|
|||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
// import VnInput from 'src/components/common/VnInput.vue';
|
||||
// import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
|
||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||
|
@ -19,13 +19,14 @@ import useNotify from 'src/composables/useNotify.js';
|
|||
import { useState } from 'src/composables/useState';
|
||||
import { toDateFormat } from 'src/filters/date.js';
|
||||
import axios from 'axios';
|
||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
|
||||
const state = useState();
|
||||
const { t } = useI18n();
|
||||
const { openConfirmationModal } = useVnConfirm();
|
||||
const { notify } = useNotify();
|
||||
const user = state.getUser();
|
||||
|
||||
const tableRef = ref();
|
||||
const itemPackingTypesOptions = ref([]);
|
||||
const zonesOptions = ref([]);
|
||||
const selectedTickets = ref([]);
|
||||
|
@ -44,15 +45,14 @@ const exprBuilder = (param, value) => {
|
|||
case 'notMovableLines':
|
||||
case 'futureZoneFk':
|
||||
return { [param]: value };
|
||||
case 'iptColFilter':
|
||||
return { ipt: { like: `%${value}%` } };
|
||||
case 'futureIptColFilter':
|
||||
return { futureIpt: { like: `%${value}%` } };
|
||||
case 'ipt':
|
||||
return { [param]: { like: `%${value}%` } };
|
||||
case 'futureIpt':
|
||||
return { [param]: { like: `%${value}%` } };
|
||||
}
|
||||
};
|
||||
|
||||
const userParams = reactive({});
|
||||
|
||||
const arrayData = useArrayData('AdvanceTickets', {
|
||||
url: 'Tickets/getTicketsAdvance',
|
||||
userParams: userParams,
|
||||
|
@ -82,220 +82,123 @@ const getInputEvents = (col) => {
|
|||
};
|
||||
};
|
||||
|
||||
const ticketColumns = computed(() => [
|
||||
const columns = computed(() => [
|
||||
{
|
||||
label: '',
|
||||
name: 'icons',
|
||||
align: 'left',
|
||||
columnFilter: null,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
label: t('advanceTickets.ticketId'),
|
||||
name: 'ticketId',
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
filterParamKey: 'id',
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
label: t('advanceTickets.ticketId'),
|
||||
name: 'id',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.ipt'),
|
||||
name: 'ipt',
|
||||
field: 'ipt',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnSelect,
|
||||
filterParamKey: 'iptColFilter',
|
||||
type: 'select',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
component: 'select',
|
||||
attrs: {
|
||||
options: itemPackingTypesOptions.value,
|
||||
'option-value': 'code',
|
||||
'option-label': 'description',
|
||||
dense: true,
|
||||
url: 'itemPackingTypes',
|
||||
fields: ['code', 'description'],
|
||||
where: { isActive: true },
|
||||
optionValue: 'code',
|
||||
optionLabel: 'description',
|
||||
},
|
||||
},
|
||||
format: (val) => dashIfEmpty(val),
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.ipt),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.state'),
|
||||
name: 'state',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: null,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.liters'),
|
||||
name: 'liters',
|
||||
field: 'liters',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.lines'),
|
||||
name: 'lines',
|
||||
field: 'lines',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
format: (val) => dashIfEmpty(val),
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.lines),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.import'),
|
||||
field: 'import',
|
||||
name: 'import',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
name: 'totalWithVat',
|
||||
hidden: true,
|
||||
format: (row) => toCurrency(row.totalWithVat),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.futureId'),
|
||||
name: 'futureId',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
filterParamKey: 'futureId',
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.futureIpt'),
|
||||
name: 'futureIpt',
|
||||
field: 'futureIpt',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnSelect,
|
||||
filterParamKey: 'futureIptColFilter',
|
||||
type: 'select',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
component: 'select',
|
||||
attrs: {
|
||||
options: itemPackingTypesOptions.value,
|
||||
'option-value': 'code',
|
||||
'option-label': 'description',
|
||||
dense: true,
|
||||
url: 'itemPackingTypes',
|
||||
fields: ['code', 'description'],
|
||||
where: { isActive: true },
|
||||
optionValue: 'code',
|
||||
optionLabel: 'description',
|
||||
},
|
||||
},
|
||||
format: (val) => dashIfEmpty(val),
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.futureIpt),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.futureState'),
|
||||
name: 'futureState',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: null,
|
||||
format: (val) => dashIfEmpty(val),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.futureLiters'),
|
||||
name: 'futureLiters',
|
||||
field: 'futureLiters',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
format: (val) => dashIfEmpty(val),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.futureZone'),
|
||||
name: 'futureZoneName',
|
||||
field: 'futureZoneName',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
name: 'futureZoneFk',
|
||||
columnClass: 'expand',
|
||||
columnFilter: {
|
||||
component: VnSelect,
|
||||
type: 'select',
|
||||
filterValue: null,
|
||||
filterParamKey: 'futureZoneFk',
|
||||
event: getInputEvents,
|
||||
component: 'select',
|
||||
inWhere: true,
|
||||
attrs: {
|
||||
options: zonesOptions.value,
|
||||
'option-value': 'id',
|
||||
'option-label': 'name',
|
||||
dense: true,
|
||||
url: 'Zones',
|
||||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
format: (val) => dashIfEmpty(val),
|
||||
columnField: {
|
||||
component: null,
|
||||
},
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.futureZoneName),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.notMovableLines'),
|
||||
name: 'notMovableLines',
|
||||
field: 'notMovableLines',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
format: (val) => dashIfEmpty(val),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('advanceTickets.futureLines'),
|
||||
name: 'futureLines',
|
||||
field: 'futureLines',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
format: (val) => dashIfEmpty(val),
|
||||
},
|
||||
{
|
||||
label: t('advanceTickets.futureImport'),
|
||||
name: 'futureImport',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: null,
|
||||
label: t('advanceTickets.futureImport'),
|
||||
name: 'futureTotalWithVat',
|
||||
hidden: true,
|
||||
format: (row) => toCurrency(row.futureTotalWithVat),
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -457,6 +360,13 @@ onMounted(async () => {
|
|||
const filter = { limit: 0 };
|
||||
await arrayData.addFilter({ filter, userParams });
|
||||
});
|
||||
|
||||
const getColor = (row) => {
|
||||
return row?.classColor ? `bg-${row.classColor}` : 'bg-orange';
|
||||
};
|
||||
const getFutureColor = (row) => {
|
||||
return row?.futureClassColor ? `bg-${row.futureClassColor}` : 'bg-orange';
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -480,9 +390,9 @@ onMounted(async () => {
|
|||
@on-fetch="(data) => (zonesOptions = data)"
|
||||
/>
|
||||
<VnSearchbar
|
||||
data-key="WeeklyTickets"
|
||||
:label="t('weeklyTickets.search')"
|
||||
:info="t('weeklyTickets.searchInfo')"
|
||||
data-key="AdvanceTickets"
|
||||
:label="t('advanceTickets.search')"
|
||||
:info="t('advanceTickets.searchInfo')"
|
||||
/>
|
||||
<VnSubToolbar>
|
||||
<template #st-data>
|
||||
|
@ -531,73 +441,32 @@ onMounted(async () => {
|
|||
</template>
|
||||
</RightMenu>
|
||||
<QPage class="column items-center q-pa-md">
|
||||
<QTable
|
||||
:rows="tickets"
|
||||
:columns="ticketColumns"
|
||||
row-key="index"
|
||||
selection="multiple"
|
||||
<VnTable
|
||||
ref="tableRef"
|
||||
data-key="AdvanceTickets"
|
||||
url="TicketWeeklies/filter"
|
||||
:columns="columns"
|
||||
auto-load
|
||||
:right-search="false"
|
||||
:disable-option="{ card: true }"
|
||||
v-model:selected="selectedTickets"
|
||||
:pagination="{ rowsPerPage: 0 }"
|
||||
:no-data-label="t('globals.noResults')"
|
||||
style="max-width: 99%"
|
||||
:table="{
|
||||
'row-key': 'id',
|
||||
selection: 'multiple',
|
||||
}"
|
||||
>
|
||||
<template #header="props">
|
||||
<QTr :props="props">
|
||||
<QTh
|
||||
class="horizontal-separator text-uppercase color-vn-label"
|
||||
colspan="7"
|
||||
translate
|
||||
>
|
||||
{{ t('advanceTickets.destination') }}
|
||||
{{ toDateFormat(userParams.dateToAdvance) }}
|
||||
</QTh>
|
||||
<QTh
|
||||
class="horizontal-separator text-uppercase color-vn-label"
|
||||
colspan="9"
|
||||
translate
|
||||
>
|
||||
{{ t('advanceTickets.origin') }}
|
||||
{{ toDateFormat(userParams.dateFuture) }}
|
||||
</QTh>
|
||||
</QTr>
|
||||
<QTr>
|
||||
<QTh>
|
||||
<QCheckbox v-model="props.selected" />
|
||||
</QTh>
|
||||
<QTh
|
||||
v-for="(col, index) in ticketColumns"
|
||||
:key="index"
|
||||
:class="{ 'vertical-separator': col.name === 'futureId' }"
|
||||
>
|
||||
{{ col.label }}
|
||||
</QTh>
|
||||
</QTr>
|
||||
<!--TODO: arreglar estilos-->
|
||||
<template #before-header>
|
||||
<span class="horizontal-separator" translate>
|
||||
{{ t('advanceTickets.destination') }}
|
||||
{{ toDateFormat(userParams.dateToAdvance) }}
|
||||
</span>
|
||||
<span class="horizontal-separator" translate>
|
||||
{{ t('advanceTickets.origin') }}
|
||||
{{ toDateFormat(userParams.dateFuture) }}
|
||||
</span>
|
||||
</template>
|
||||
<template #top-row="{ cols }">
|
||||
<QTr>
|
||||
<QTd />
|
||||
<QTd
|
||||
v-for="(col, index) in cols"
|
||||
:key="index"
|
||||
style="max-width: 100px"
|
||||
>
|
||||
<component
|
||||
:is="col.columnFilter.component"
|
||||
v-if="col.columnFilter"
|
||||
v-model="col.columnFilter.filterValue"
|
||||
v-bind="col.columnFilter.attrs"
|
||||
v-on="col.columnFilter.event(col)"
|
||||
dense
|
||||
/>
|
||||
</QTd>
|
||||
</QTr>
|
||||
</template>
|
||||
<template #header-cell-availableLines="{ col }">
|
||||
<QTh class="vertical-separator">
|
||||
{{ col.label }}
|
||||
</QTh>
|
||||
</template>
|
||||
<template #body-cell-icons="{ row }">
|
||||
<template #column-icons="{ row }">
|
||||
<QTd class="q-gutter-x-xs">
|
||||
<QIcon
|
||||
v-if="row.futureAgency !== row.agency && row.agency"
|
||||
|
@ -624,73 +493,52 @@ onMounted(async () => {
|
|||
</QIcon>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-ticketId="{ row }">
|
||||
<QTd>
|
||||
<QBtn flat class="link">
|
||||
{{ row.id }}
|
||||
<TicketDescriptorProxy :id="row.id" />
|
||||
</QBtn>
|
||||
</QTd>
|
||||
<template #column-id="{ row }">
|
||||
<span class="link" @click.stop>
|
||||
{{ row.id }}
|
||||
<TicketDescriptorProxy :id="row.id" />
|
||||
</span>
|
||||
</template>
|
||||
<template #body-cell-state="{ row }">
|
||||
<QTd>
|
||||
<QBadge
|
||||
text-color="black"
|
||||
:color="row.classColor"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ row.state }}
|
||||
</QBadge>
|
||||
</QTd>
|
||||
<template #column-state="{ row }">
|
||||
<QChip :class="getColor(row)" dense square>
|
||||
{{ row.state }}
|
||||
</QChip>
|
||||
</template>
|
||||
<template #body-cell-import="{ row }">
|
||||
<QTd>
|
||||
<QBadge
|
||||
:text-color="isLessThan50(row.totalWithVat) ? 'black' : 'white'"
|
||||
:color="totalPriceColor(row.totalWithVat)"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ toCurrency(row.totalWithVat || 0) }}
|
||||
</QBadge>
|
||||
</QTd>
|
||||
<template #column-totalWithVat="{ row }">
|
||||
<QBadge
|
||||
:text-color="isLessThan50(row.totalWithVat) ? 'black' : 'white'"
|
||||
:color="totalPriceColor(row.totalWithVat)"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ toCurrency(row.totalWithVat || 0) }}
|
||||
</QBadge>
|
||||
</template>
|
||||
<template #body-cell-futureId="{ row }">
|
||||
<QTd class="vertical-separator">
|
||||
<QBtn flat class="link" dense>
|
||||
<template #column-futureId="{ row }">
|
||||
<!--TODO: arreglar estilos para que se muestre como antes, slot?-->
|
||||
<div class="vertical-separator">
|
||||
<span class="link" @click.stop>
|
||||
{{ row.futureId }}
|
||||
<TicketDescriptorProxy :id="row.futureId" />
|
||||
</QBtn>
|
||||
</QTd>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #body-cell-futureState="{ row }">
|
||||
<QTd>
|
||||
<QBadge
|
||||
text-color="black"
|
||||
:color="row.futureClassColor"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ row.futureState }}
|
||||
</QBadge>
|
||||
</QTd>
|
||||
<template #column-futureState="{ row }">
|
||||
<QChip :class="getFutureColor(row)" dense square>
|
||||
{{ row.futureState }}
|
||||
</QChip>
|
||||
</template>
|
||||
<template #body-cell-futureImport="{ row }">
|
||||
<QTd>
|
||||
<QBadge
|
||||
:text-color="
|
||||
isLessThan50(row.futureTotalWithVat) ? 'black' : 'white'
|
||||
"
|
||||
:color="totalPriceColor(row.futureTotalWithVat)"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ toCurrency(row.futureTotalWithVat || 0) }}
|
||||
</QBadge>
|
||||
</QTd>
|
||||
<template #column-futureTotalWithVat="{ row }">
|
||||
<QBadge
|
||||
:text-color="isLessThan50(row.futureTotalWithVat) ? 'black' : 'white'"
|
||||
:color="totalPriceColor(row.futureTotalWithVat)"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ toCurrency(row.futureTotalWithVat || 0) }}
|
||||
</QBadge>
|
||||
</template>
|
||||
</QTable>
|
||||
</VnTable>
|
||||
<VnProgress
|
||||
:progress="progressPercentage"
|
||||
:cancelled="cancelProgress"
|
||||
|
@ -714,6 +562,8 @@ onMounted(async () => {
|
|||
}
|
||||
|
||||
.horizontal-separator {
|
||||
border-bottom: 4px solid white !important;
|
||||
width: 100%;
|
||||
margin-top: 1%;
|
||||
border-bottom: 5px solid white !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
import axios from 'axios';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { toDate, toCurrency } from 'src/filters/index';
|
||||
import useNotify from 'src/composables/useNotify';
|
||||
import TicketSummary from './Card/TicketSummary.vue';
|
||||
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||
|
@ -10,14 +12,25 @@ import VnTable from 'src/components/VnTable/VnTable.vue';
|
|||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
import VnRow from 'src/components/ui/VnRow.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { viewSummary } = useSummaryDialog();
|
||||
const tableRef = ref();
|
||||
const quasar = useQuasar();
|
||||
const { notify } = useNotify();
|
||||
const clientsOptions = ref([]);
|
||||
const addressesOptions = ref([]);
|
||||
const agenciesOptions = ref([]);
|
||||
const selectedClient = ref();
|
||||
const selectedRows = ref([]);
|
||||
const hasSelectedRows = computed(() => selectedRows.value.length > 0);
|
||||
const showForm = ref(false);
|
||||
const dialogData = ref();
|
||||
const companiesOptions = ref([]);
|
||||
const accountingOptions = ref([]);
|
||||
const amountToReturn = ref();
|
||||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
|
@ -187,9 +200,158 @@ const fetchAddresses = async (formData) => {
|
|||
const getColor = (row) => {
|
||||
return row?.classColor ? `bg-${row.classColor}` : 'bg-orange';
|
||||
};
|
||||
|
||||
async function makeInvoice(ticket) {
|
||||
const ticketsIds = ticket.map((item) => item.id);
|
||||
const { data } = await axios.post(`Tickets/invoiceTicketsAndPdf`, { ticketsIds });
|
||||
const response = data;
|
||||
if (response)
|
||||
quasar.notify({
|
||||
message: t('globals.dataSaved'),
|
||||
type: 'positive',
|
||||
});
|
||||
}
|
||||
|
||||
async function sendDocuware(ticket) {
|
||||
try {
|
||||
let ticketIds = ticket.map((item) => item.id);
|
||||
|
||||
const { data } = await axios.post(`Docuwares/upload`, {
|
||||
fileCabinet: 'deliveryNote',
|
||||
ticketIds,
|
||||
});
|
||||
|
||||
for (let ticket of ticketIds) {
|
||||
ticket.stateFk = data.id;
|
||||
ticket.state = data.name;
|
||||
ticket.alertLevel = data.alertLevel;
|
||||
ticket.alertLevelCode = data.code;
|
||||
}
|
||||
notify('globals.dataSaved', 'positive');
|
||||
} catch (err) {
|
||||
console.log('err: ', err);
|
||||
}
|
||||
}
|
||||
|
||||
function openBalanceDialog(ticket) {
|
||||
const checkedTickets = ticket;
|
||||
const amountPaid = ref(0);
|
||||
const clientFk = ref(null);
|
||||
const description = ref([]);
|
||||
const firstTicketClientId = checkedTickets[0].clientFk;
|
||||
const isSameClient = checkedTickets.every(
|
||||
(ticket) => ticket.clientFk === firstTicketClientId
|
||||
);
|
||||
|
||||
if (!isSameClient) {
|
||||
throw new Error('You cannot make a payment on account from multiple clients');
|
||||
}
|
||||
|
||||
for (let ticketData of checkedTickets) {
|
||||
console.log('ticketData: ', ticketData);
|
||||
amountPaid.value += ticketData.totalWithVat;
|
||||
clientFk.value = ticketData.clientFk;
|
||||
description.value.push(ticketData.id);
|
||||
}
|
||||
|
||||
const balanceCreateDialog = ref({
|
||||
amountPaid: amountPaid.value,
|
||||
clientFk: clientFk.value,
|
||||
description: `Albaran: ${description.value.join(', ')}`,
|
||||
});
|
||||
dialogData.value = balanceCreateDialog;
|
||||
showForm.value = true;
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
const { data: email } = await axios.get('Clients', {
|
||||
params: {
|
||||
filter: JSON.stringify({ where: { id: dialogData.value.value.clientFk } }),
|
||||
},
|
||||
});
|
||||
|
||||
const { data } = await axios.post(
|
||||
`Clients/${dialogData.value.value.clientFk}/createReceipt`,
|
||||
{
|
||||
payed: dialogData.value.payed,
|
||||
companyFk: dialogData.value.companyFk,
|
||||
bankFk: dialogData.value.bankFk,
|
||||
amountPaid: dialogData.value.value.amountPaid,
|
||||
description: dialogData.value.value.description,
|
||||
clientFk: dialogData.value.value.clientFk,
|
||||
email: email[0].email,
|
||||
}
|
||||
);
|
||||
|
||||
if (data) notify('globals.dataSaved', 'positive');
|
||||
showForm.value = false;
|
||||
}
|
||||
|
||||
const setAmountToReturn = (newAmountGiven) => {
|
||||
const amountPaid = dialogData.value.value.amountPaid;
|
||||
|
||||
amountToReturn.value = newAmountGiven - amountPaid;
|
||||
};
|
||||
|
||||
function setReference(data) {
|
||||
console.log('entity: ', data);
|
||||
|
||||
let newDescription = '';
|
||||
|
||||
switch (data) {
|
||||
case 1:
|
||||
newDescription = `${t(
|
||||
'ticketList.creditCard'
|
||||
)}, ${dialogData.value.value.description.replace(
|
||||
/^(Credit Card, |Cash, |Transfers, )/,
|
||||
''
|
||||
)}`;
|
||||
break;
|
||||
case 2:
|
||||
newDescription = `${t(
|
||||
'ticketList.cash'
|
||||
)}, ${dialogData.value.value.description.replace(
|
||||
/^(Credit Card, |Cash, |Transfers, )/,
|
||||
''
|
||||
)}`;
|
||||
break;
|
||||
case 3:
|
||||
newDescription = `${newDescription.replace(
|
||||
/^(Credit Card, |Cash, |Transfers, )/,
|
||||
''
|
||||
)}`;
|
||||
break;
|
||||
case 4:
|
||||
newDescription = `${t(
|
||||
'ticketList.transfers'
|
||||
)}, ${dialogData.value.value.description.replace(
|
||||
/^(Credit Card, |Cash, |Transfers, )/,
|
||||
''
|
||||
)}`;
|
||||
break;
|
||||
case 3317:
|
||||
newDescription = '';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dialogData.value.value.description = newDescription;
|
||||
console.log('Updated description:', dialogData.value.value.description);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="Companies"
|
||||
@on-fetch="(data) => (companiesOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="Accountings"
|
||||
@on-fetch="(data) => (accountingOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<VnSearchbar
|
||||
data-key="Tickets"
|
||||
:label="t('Search ticket')"
|
||||
|
@ -209,6 +371,11 @@ const getColor = (row) => {
|
|||
:columns="columns"
|
||||
redirect="ticket"
|
||||
auto-load
|
||||
v-model:selected="selectedRows"
|
||||
:table="{
|
||||
'row-key': 'id',
|
||||
selection: 'multiple',
|
||||
}"
|
||||
>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<VnRow>
|
||||
|
@ -306,6 +473,135 @@ const getColor = (row) => {
|
|||
</QChip>
|
||||
</template>
|
||||
</VnTable>
|
||||
<QPageSticky :offset="[20, 80]" style="z-index: 2">
|
||||
<QBtn
|
||||
v-if="hasSelectedRows"
|
||||
@click="makeInvoice(selectedRows)"
|
||||
color="primary"
|
||||
fab
|
||||
icon="vn:invoice-in"
|
||||
/>
|
||||
<QTooltip>
|
||||
{{ t('ticketList.createInvoice') }}
|
||||
</QTooltip>
|
||||
</QPageSticky>
|
||||
<QPageSticky v-if="hasSelectedRows" :offset="[20, 140]" style="z-index: 2">
|
||||
<QBtn
|
||||
@click.stop="openBalanceDialog(selectedRows)"
|
||||
color="primary"
|
||||
fab
|
||||
icon="vn:recovery"
|
||||
/>
|
||||
<QTooltip>
|
||||
{{ t('ticketList.accountPayment') }}
|
||||
</QTooltip>
|
||||
</QPageSticky>
|
||||
<QDialog ref="dialogRef" v-model="showForm">
|
||||
<QCard class="q-pa-md q-mb-md">
|
||||
<QForm @submit="onSubmit()" class="q-pa-sm">
|
||||
{{ t('ticketList.addPayment') }}
|
||||
<VnRow>
|
||||
<VnInputDate
|
||||
:label="t('ticketList.date')"
|
||||
v-model="dialogData.payed"
|
||||
/>
|
||||
<VnSelect
|
||||
:label="t('ticketList.company')"
|
||||
v-model="dialogData.companyFk"
|
||||
:options="companiesOptions"
|
||||
option-value="id"
|
||||
option-label="code"
|
||||
hide-selected
|
||||
>
|
||||
</VnSelect>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('ticketList.bank')"
|
||||
v-model="dialogData.bankFk"
|
||||
:options="accountingOptions"
|
||||
option-value="id"
|
||||
option-label="bank"
|
||||
hide-selected
|
||||
@update:model-value="setReference"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('ticketList.amount')"
|
||||
v-model="dialogData.value.amountPaid"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow v-if="dialogData.bankFk === 2">
|
||||
<span>
|
||||
{{ t('ticketList.cash') }}
|
||||
</span>
|
||||
</VnRow>
|
||||
<VnRow v-if="dialogData.bankFk === 2">
|
||||
<VnInput
|
||||
:label="t('ticketList.deliveredAmount')"
|
||||
v-model="dialogData.value.amountGiven"
|
||||
@update:model-value="setAmountToReturn"
|
||||
type="number"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('ticketList.amountToReturn')"
|
||||
:model-value="amountToReturn"
|
||||
type="number"
|
||||
readonly
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow v-if="dialogData.bankFk === 3 || dialogData.bankFk === 3117">
|
||||
<VnInput
|
||||
:label="t('ticketList.compensation')"
|
||||
v-model="dialogData.value.compensation"
|
||||
type="text"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
:label="t('ticketList.reference')"
|
||||
v-model="dialogData.value.description"
|
||||
type="text"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow v-if="dialogData.bankFk === 2">
|
||||
<QCheckbox
|
||||
:label="t('ticketList.viewReceipt')"
|
||||
v-model="dialogData.value.viewReceipt"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
<QCheckbox
|
||||
:label="t('ticketList.sendEmail')"
|
||||
v-model="dialogData.value.senEmail"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
</VnRow>
|
||||
<div class="q-mt-lg row justify-end">
|
||||
<QBtn
|
||||
:label="t('globals.save')"
|
||||
color="primary"
|
||||
@click="onSubmit()"
|
||||
/>
|
||||
<QBtn
|
||||
flat
|
||||
:label="t('globals.close')"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
/>
|
||||
</div>
|
||||
</QForm>
|
||||
</QCard>
|
||||
</QDialog>
|
||||
<QPageSticky v-if="hasSelectedRows" :offset="[20, 200]" style="z-index: 2">
|
||||
<QBtn
|
||||
@click="sendDocuware(selectedRows)"
|
||||
color="primary"
|
||||
fab
|
||||
icon="install_mobile"
|
||||
/>
|
||||
<QTooltip>
|
||||
{{ t('ticketList.sendDocuware') }}
|
||||
</QTooltip>
|
||||
</QPageSticky>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
|
|
|
@ -66,6 +66,8 @@ advanceTickets:
|
|||
advanceWithoutNegativeTitle: Advance tickets (without negatives)
|
||||
advanceWithoutNegativeSubtitle: Advance {selectedTickets} tickets confirmation
|
||||
errorsList: Errors list
|
||||
search: Search advance tickets
|
||||
searchInfo: Search advance tickets by ID or client ID
|
||||
futureTickets:
|
||||
problems: Problems
|
||||
ticketId: ID
|
||||
|
@ -239,3 +241,20 @@ ticketList:
|
|||
summary: Summary
|
||||
client: Customer
|
||||
createTicket: Create ticket
|
||||
createInvoice: Create invoice
|
||||
accountPayment: Account payment
|
||||
sendDocuware: Set delivered and send delivery note(s) to the tablet
|
||||
addPayment: Add payment
|
||||
date: Date
|
||||
company: Company
|
||||
amount: Amount
|
||||
reference: Reference
|
||||
bank: Bank
|
||||
cash: Cash
|
||||
deliveredAmount: Delivered amount
|
||||
amountToReturn: Amount to return
|
||||
viewReceipt: View receipt
|
||||
sendEmail: Send email
|
||||
compensation: Compensation
|
||||
creditCard: Credit card
|
||||
transfers: Transfers
|
||||
|
|
|
@ -113,6 +113,8 @@ advanceTickets:
|
|||
advanceWithoutNegativeTitle: Adelantar tickets (sin negativos)
|
||||
advanceWithoutNegativeSubtitle: '¿Desea adelantar {selectedTickets} tickets?'
|
||||
errorsList: Lista de errores
|
||||
search: Buscar por tickets adelantados
|
||||
searchInfo: Buscar tickets adelantados por el identificador o el identificador del cliente
|
||||
futureTickets:
|
||||
problems: Problemas
|
||||
ticketId: ID
|
||||
|
@ -242,3 +244,20 @@ ticketList:
|
|||
summary: Resumen
|
||||
client: Cliente
|
||||
createTicket: Crear ticket
|
||||
createInvoice: Crear factura
|
||||
accountPayment: Pago a cuenta...
|
||||
sendDocuware: Marcar como servido/s y enviar albarán/es a la tablet
|
||||
addPayment: Añadir pago
|
||||
date: Fecha
|
||||
company: Empresa
|
||||
amount: Importe
|
||||
reference: Referencia
|
||||
bank: Caja
|
||||
cash: Efectivo
|
||||
deliveredAmount: Cantidad entregada
|
||||
amountToReturn: Cantidad a devolver
|
||||
viewReceipt: Ver recibido
|
||||
sendEmail: Enviar correo
|
||||
compensation: Compensación
|
||||
creditCard: Tarjeta de crédito
|
||||
transfers: Transferencias
|
||||
|
|
Loading…
Reference in New Issue