{{ row.item.name }}
{{ row.item.subName }}
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index 28c6fcf15..fdc75abda 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
@@ -12,6 +12,7 @@ import VnInputTime from 'components/common/VnInputTime.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
+import { useValidator } from 'src/composables/useValidator';
import { toTimeFormat } from 'filters/date.js';
const $props = defineProps({
@@ -23,7 +24,7 @@ const $props = defineProps({
});
const emit = defineEmits(['updateForm']);
-
+const { validate } = useValidator();
const { notify } = useNotify();
const router = useRouter();
const { t } = useI18n();
@@ -51,18 +52,18 @@ const agencyByWarehouseFilter = computed(() => ({
},
}));
-const zonesFilter = computed(() => ({
- fields: ['id', 'name'],
- order: 'name ASC',
- where: formData.value?.agencyModeFk
- ? {
- shipped: formData.value?.shipped,
- addressFk: formData.value?.addressFk,
- agencyModeFk: formData.value?.agencyModeFk,
- warehouseFk: formData.value?.warehouseFk,
- }
- : {},
-}));
+function zoneWhere() {
+ if (formData?.value?.agencyModeFk) {
+ return formData.value?.agencyModeFk
+ ? {
+ shipped: formData.value?.shipped,
+ addressFk: formData.value?.addressFk,
+ agencyModeFk: formData.value?.agencyModeFk,
+ warehouseFk: formData.value?.warehouseFk,
+ }
+ : {};
+ }
+}
const getLanded = async (params) => {
try {
@@ -293,13 +294,6 @@ onMounted(() => onFormModelInit());
@on-fetch="(data) => (agenciesOptions = data)"
auto-load
/>
-
(zonesOptions = data)"
- auto-load
- />
onFormModelInit());
hide-selected
map-options
:required="true"
+ :rules="validate('basicData.client')"
>
@@ -333,6 +328,7 @@ onMounted(() => onFormModelInit());
hide-selected
map-options
:required="true"
+ :rules="validate('basicData.warehouse')"
/>
@@ -345,6 +341,7 @@ onMounted(() => onFormModelInit());
hide-selected
map-options
:required="true"
+ :rules="validate('basicData.address')"
>
@@ -392,6 +389,7 @@ onMounted(() => onFormModelInit());
:label="t('basicData.alias')"
v-model="formData.nickname"
:required="true"
+ :rules="validate('basicData.alias')"
/>
@@ -404,6 +402,7 @@ onMounted(() => onFormModelInit());
hide-selected
map-options
:required="true"
+ :rules="validate('basicData.company')"
/>
onFormModelInit());
hide-selected
map-options
@focus="agencyFetchRef.fetch()"
+ :rules="validate('basicData.agency')"
/>
@@ -444,16 +448,19 @@ onMounted(() => onFormModelInit());
:label="t('basicData.shipped')"
v-model="formData.shipped"
:required="true"
+ :rules="validate('basicData.shipped')"
/>
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
index af47761a2..92640f898 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue
@@ -3,7 +3,7 @@ import { ref, onBeforeMount } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
-import BasicDataTable from './BasicDataTable.vue';
+import TicketBasicData from './TicketBasicData.vue';
import TicketBasicDataForm from './TicketBasicDataForm.vue';
import { useVnConfirm } from 'composables/useVnConfirm';
@@ -158,7 +158,10 @@ onBeforeMount(async () => await getTicketData());
color="primary"
animated
keep-alive
- style="max-width: 800px; margin: auto"
+ style="margin: auto"
+ :style="{
+ 'max-width': step > 1 ? 'none' : '800px',
+ }"
>
await getTicketData());
/>
- (formData = $event)"
diff --git a/src/pages/Ticket/Card/ExpeditionNewTicket.vue b/src/pages/Ticket/Card/ExpeditionNewTicket.vue
index 55ca700bc..9183ae405 100644
--- a/src/pages/Ticket/Card/ExpeditionNewTicket.vue
+++ b/src/pages/Ticket/Card/ExpeditionNewTicket.vue
@@ -31,6 +31,7 @@ const router = useRouter();
const { notify } = useNotify();
const newTicketFormData = reactive({});
+const date = new Date();
const createTicket = async () => {
try {
@@ -64,7 +65,11 @@ const createTicket = async () => {
>
-
+
[
name: 'item',
align: 'left',
},
+ {
+ align: 'left',
+ label: t('lines.image'),
+ name: 'image',
+ columnField: {
+ component: VnImg,
+ attrs: (id) => {
+ return {
+ id,
+ width: '50px',
+ };
+ },
+ },
+ columnFilter: false,
+ },
{
label: t('ticketComponents.description'),
name: 'description',
align: 'left',
+ columnClass: 'expand',
},
{
label: t('ticketComponents.quantity'),
name: 'quantity',
field: 'quantity',
align: 'left',
- format: (val) => dashIfEmpty(val),
+ format: (row) => dashIfEmpty(row.quantity),
},
{
label: t('ticketComponents.serie'),
name: 'serie',
align: 'left',
+ format: (row) => dashIfEmpty(row.serie),
},
{
label: t('ticketComponents.components'),
@@ -174,181 +192,166 @@ onUnmounted(() => (stateStore.rightDrawer = false));
@on-fetch="(data) => (components = data)"
auto-load
/>
-
-
-
+
+
+
+ {{ t('ticketComponents.total') }}
+
+
+
+ {{ t('ticketComponents.baseToCommission') }}:
+
+ {{ toCurrency(getBase) }}
+
+
+ {{ t('ticketComponents.totalWithoutVat') }}:
+
+ {{ toCurrency(getTotal) }}
+
+
+
+
+
+ {{ t('ticketComponents.components') }}
+
+
+
-
-
- {{ t('ticketComponents.total') }}
-
-
-
- {{ t('ticketComponents.baseToCommission') }}:
-
- {{ toCurrency(getBase) }}
-
-
- {{ t('ticketComponents.totalWithoutVat') }}:
-
- {{ toCurrency(getTotal) }}
-
-
-
-
-
- {{ t('ticketComponents.components') }}
-
-
-
-
- {{ component.name }}:
-
- {{
- toCurrency(component.value, 'EUR', 3)
- }}
-
-
-
-
-
- {{ t('ticketComponents.zoneBreakdown') }}
-
-
-
-
- {{ t('ticketComponents.price') }}:
-
- {{ toCurrency(ticketData?.zonePrice, 'EUR', 2) }}
-
-
-
- {{ t('ticketComponents.bonus') }}:
-
- {{ toCurrency(ticketData?.zoneBonus, 'EUR', 2) }}
-
-
-
- {{ t('ticketComponents.zone') }}:
-
-
- {{ dashIfEmpty(ticketData?.zone?.name) }}
-
-
-
-
-
- {{ t('ticketComponents.volume') }}:
-
- {{ ticketVolume }}
-
-
-
- {{ t('ticketComponents.packages') }}:
-
- {{ dashIfEmpty(ticketData?.packages) }}
-
-
-
-
-
- {{ t('ticketComponents.theoricalCost') }}
-
-
-
-
- {{ t('ticketComponents.totalPrice') }}:
-
- {{ toCurrency(theoricalCost, 'EUR', 2) }}
-
-
-
-
-
+ {{ component.name }}:
+
+ {{
+ toCurrency(component.value, 'EUR', 3)
+ }}
+
+
+
+
+
+ {{ t('ticketComponents.zoneBreakdown') }}
+
+
+
+
+ {{ t('ticketComponents.price') }}:
+
+ {{ toCurrency(ticketData?.zonePrice, 'EUR', 2) }}
+
+
+
+ {{ t('ticketComponents.bonus') }}:
+
+ {{ toCurrency(ticketData?.zoneBonus, 'EUR', 2) }}
+
+
+
+ {{ t('ticketComponents.zone') }}:
+
+
+ {{ dashIfEmpty(ticketData?.zone?.name) }}
+
+
+
+
+
+ {{ t('ticketComponents.volume') }}:
+
+ {{ ticketVolume }}
+
+
+
+ {{ t('ticketComponents.packages') }}:
+
+ {{ dashIfEmpty(ticketData?.packages) }}
+
+
+
+
+
+ {{ t('ticketComponents.theoricalCost') }}
+
+
+
+
+ {{ t('ticketComponents.totalPrice') }}:
+
+ {{ toCurrency(theoricalCost, 'EUR', 2) }}
+
+
+
+
-
-
-
- {{ row.itemFk }}
-
-
-
+
+
+ {{ row.itemFk }}
+
+
-
-
-
- {{ row.item.name }}
- {{ row.item.subName }}
-
-
-
+
+
+
+
-
-
-
-
- {{ saleComponent.component?.componentType?.name }}
-
-
-
+
+
+ {{ row.item.name }}
+ {{ row.item.subName }}
+
+
-
-
-
-
- {{ saleComponent.component?.name }}
-
-
-
+
+
+
+ {{ saleComponent.component?.componentType?.name }}
+
+
-
-
-
-
+
+
+
+ {{ saleComponent.component?.name }}
+
+
+
+
+
+
+ {{ toCurrency(saleComponent.value, 'EUR', 3) }}
+
+
+
+
+
+
+ {{ toCurrency(saleComponent.value * row.quantity, 'EUR', 3) }}
+
+
+
-
-
-
-
- {{ toCurrency(saleComponent.value * row.quantity, 'EUR', 3) }}
-
-
-
-
-
+
+
+
diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue
index f68c897db..70fd9ab1e 100644
--- a/src/pages/Ticket/Card/TicketDescriptor.vue
+++ b/src/pages/Ticket/Card/TicketDescriptor.vue
@@ -2,13 +2,13 @@
import { ref, computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
-import { toDate } from 'src/filters';
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
+import { toDateTimeFormat } from 'src/filters/date';
const $props = defineProps({
id: {
@@ -30,13 +30,24 @@ const filter = {
{
relation: 'address',
scope: {
- fields: ['id', 'name', 'mobile', 'phone'],
+ fields: ['id', 'name', 'mobile', 'phone', 'incotermsFk'],
},
},
{
relation: 'client',
scope: {
- fields: ['id', 'name', 'salesPersonFk', 'phone', 'mobile', 'email'],
+ fields: [
+ 'id',
+ 'name',
+ 'salesPersonFk',
+ 'phone',
+ 'mobile',
+ 'email',
+ 'isActive',
+ 'isFreezed',
+ 'isTaxDataChecked',
+ 'hasElectronicInvoice',
+ ],
include: [
{
relation: 'user',
@@ -87,6 +98,10 @@ const filter = {
};
const data = ref(useCardDescription());
+
+function ticketFilter(ticket) {
+ return JSON.stringify({ clientFk: ticket.clientFk });
+}
@@ -128,7 +143,10 @@ const data = ref(useCardDescription());
/>
-
+
-
+
+
+ {{ t('Client inactive') }}
+
+
+ {{ t('Client Frozen') }}
+
+
+ {{ t('Client has debt') }}
+
+
+ {{ t('Client not checked') }}
+
{{ t('ticket.card.customerCard') }}
+
+ {{ t('ticket.card.ticketList') }}
+
+
+ {{ t('ticket.card.newOrder') }}
+
@@ -168,4 +239,8 @@ const data = ref(useCardDescription());
es:
This ticket is deleted: Este ticket está eliminado
Go to module index: Ir al índice del modulo
+ Client inactive: Cliente inactivo
+ Client not checked: Cliente no verificado
+ Client has debt: Cliente con deuda
+ Client Frozen: Cliente congelado
diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
index 4cf4e633f..12e03551b 100644
--- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
@@ -1,6 +1,6 @@
+
+
+
+
+
+ {{ t('Transfer client') }}
+
+
+
+
+
+
+
+
+
+ {{ `#${scope.opt.id} - ` }}
+ {{ scope.opt.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('addTurn') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- {{ t('Open Delivery Note...') }}
+ {{ t('Show Delivery Note...') }}
- {{ t('With prices') }}
+ {{ t('as PDF') }}
- {{ t('Without prices') }}
+ {{ t('as PDF without prices') }}
- {{ t('As CSV') }}
+ {{ t('as CSV') }}
@@ -220,21 +484,21 @@ function openConfirmDialog(callback) {
v-ripple
clickable
>
- {{ t('With prices') }}
+ {{ t('Send PDF') }}
- {{ t('Without prices') }}
+ {{ t('Send PDF to tablet') }}
- {{ t('As CSV') }}
+ {{ t('Send CSV') }}
@@ -243,8 +507,26 @@ function openConfirmDialog(callback) {
- {{ t('Open Proforma Invoice') }}
+ {{ t('Show Proforma') }}
+
+
+
+
+ {{ t('Change shipped hour') }}
+
+
+
+
+
+
+
+
@@ -259,24 +541,72 @@ function openConfirmDialog(callback) {
{{ t('Pending payment') }}
- {{ t('Minimum amount') }}
+ {{ t('Minimum import') }}
- {{ t('Order changes') }}
+ {{ t('Notify changes') }}
+
+
+
+
+ {{ t('Make invoice') }}
+
+
+
+
+
+ {{
+ hasPdf ? t('Regenerate PDF invoice') : t('Generate PDF invoice')
+ }}
+
{{ t('To clone ticket') }}
+
+
+
+
+ {{ t('Recalculate components') }}
+
+
+
+
+
+ {{ t('Refund all...') }}
+
+
+
+
+
+
+
+ {{ t('with warehouse') }}
+
+
+
+
+ {{ t('without warehouse') }}
+
+
+
+
+
@@ -307,29 +637,61 @@ function openConfirmDialog(callback) {
+
+
en:
+ addTurn: Add turn
invoiceIds: "Invoices have been generated with the following ids: {invoiceIds}"
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
+ 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
+ Generate PDF invoice: Generar PDF factura
+ Regenerate PDF invoice: Regenerar PDF factura
+ The invoice PDF document has been regenerated: El documento PDF de la factura ha sido regenerado
+ Transfer client: Transferir cliente
+ Client: Cliente
+ addTurn: Añadir a turno
+ What is the day of receipt of the ticket?: ¿Cuál es el día de preparación del pedido?
+ Current ticket deleted and added to shift: Ticket actual eliminado y añadido al turno
+ Refund all...: Abonar todo...
+ with warehouse: con almacén
+ without warehouse: sin almacén
+ Make invoice: Crear factura
+ Change shipped hour: Cambiar hora de envío
+ Shipped hour: Hora de envío
+ Recalculate components: Recalcular componentes
+ Are you sure you want to recalculate components?: ¿Seguro que quieres recalcular los componentes?
+ Data saved: Datos guardados
+ Are you sure you want to invoice this ticket?: ¿Seguro que quieres facturar este ticket?
+ You are going to invoice this ticket: Vas a facturar este ticket
+ Ticket invoiced: Ticket facturado
Set weight: Establecer peso
Weight set: Peso establecido
This ticket may be invoiced, do you want to continue?: Es posible que se facture este ticket, desea continuar?
invoiceIds: "Se han generado las facturas con los siguientes ids: {invoiceIds}"
+ This ticket will be removed from current route! Continue anyway?: ¡Se eliminará el ticket de la ruta actual! ¿Continuar de todas formas?
+ You are going to delete this ticket: Vas a eliminar este ticket
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index c4ab63b39..4becb3db3 100644
--- a/src/pages/Ticket/Card/TicketExpedition.vue
+++ b/src/pages/Ticket/Card/TicketExpedition.vue
@@ -1,39 +1,35 @@
@@ -73,13 +85,14 @@ watch(
:label="t('ticketNotes.description')"
v-model="row.description"
class="col"
+ @keyup.enter="handleSave"
/>
{{ t('ticketNotes.removeNote') }}
diff --git a/src/pages/Ticket/Card/TicketPackage.vue b/src/pages/Ticket/Card/TicketPackage.vue
index c071d4f7f..c0418bcf6 100644
--- a/src/pages/Ticket/Card/TicketPackage.vue
+++ b/src/pages/Ticket/Card/TicketPackage.vue
@@ -10,6 +10,7 @@ import FetchData from 'components/FetchData.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import { useArrayData } from 'src/composables/useArrayData';
+import VnRow from 'src/components/ui/VnRow.vue';
const route = useRoute();
const { t } = useI18n();
diff --git a/src/pages/Ticket/Card/TicketPurchaseRequest.vue b/src/pages/Ticket/Card/TicketPurchaseRequest.vue
index 8d84e2b46..d0af9efd0 100644
--- a/src/pages/Ticket/Card/TicketPurchaseRequest.vue
+++ b/src/pages/Ticket/Card/TicketPurchaseRequest.vue
@@ -1,27 +1,35 @@
-
-
-
- redirectToTicketSummary(row.ticketFk)"
- >
-
-
-
-
-
-
-
-
- {{ row.requester?.user?.nickname }}
-
-
-
-
-
-
-
- {{ row.atender?.user?.nickname }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ row.sale.itemFk }}
-
-
-
-
-
-
-
-
- {{ t('globals.delete') }}
-
-
-
-
-
-
-
-
-
-
-
- (attendersOptions = data)"
+ />
+
+
+
+
+
+
+ {{ row.requester?.user?.nickname }}
+
+
+
+
+
+ {{ row.atender?.user?.nickname }}
+
+
+
+
+
+
+
+
+
+ {{ row.price }}
+
+
+
+
+
+
+ {{ dashIfEmpty(row.sale?.itemFk) }}
+
+
+
+ {{ t(getRequestState(row.isOk)) }}
+
+
+
+
-
- {{ t('purchaseRequest.newRequest') }}
-
-
-
+
+
+
+
+
+
es:
New: Nueva
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index f86863f05..d87f6c402 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -16,11 +16,12 @@ import TicketSaleMoreActions from './TicketSaleMoreActions.vue';
import TicketTransfer from './TicketTransfer.vue';
import { useStateStore } from 'stores/useStateStore';
-import { toCurrency, toPercentage, dashIfEmpty } from 'src/filters';
+import { toCurrency, toPercentage } from 'src/filters';
import { useArrayData } from 'composables/useArrayData';
import { useVnConfirm } from 'composables/useVnConfirm';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
+import VnTable from 'src/components/VnTable/VnTable.vue';
const route = useRoute();
const router = useRouter();
@@ -33,7 +34,8 @@ const stateBtnDropdownRef = ref(null);
const arrayData = useArrayData('ticketData');
const { store } = arrayData;
-
+const selectedRows = ref([]);
+const hasSelectedRows = computed(() => selectedRows.value.length > 0);
const ticketConfig = ref(null);
const isLocked = ref(false);
const isTicketEditable = ref(false);
@@ -47,6 +49,7 @@ const transfer = ref({
lastActiveTickets: [],
sales: [],
});
+const tableRef = ref([]);
watch(
() => route.params.id,
@@ -55,86 +58,89 @@ watch(
const columns = computed(() => [
{
- label: '',
+ align: 'left',
name: 'statusIcons',
- align: 'left',
},
{
- label: '',
- name: 'picture',
- align: 'left',
+ align: 'center',
+ label: t('lines.image'),
+ name: 'image',
+ columnField: {
+ component: VnImg,
+ attrs: (id) => {
+ return {
+ id,
+ width: '50px',
+ };
+ },
+ },
+ columnFilter: false,
},
{
+ align: 'left',
label: t('ticketSale.visible'),
name: 'visible',
- field: 'visible',
- align: 'left',
- sortable: true,
+ format: (row, dashIfEmpty) => dashIfEmpty(row.visible),
},
{
+ align: 'left',
label: t('ticketSale.available'),
name: 'available',
- field: 'available',
- align: 'left',
- sortable: true,
+ format: (row, dashIfEmpty) => dashIfEmpty(row.available),
},
{
+ align: 'left',
label: t('ticketSale.id'),
name: 'itemFk',
- field: 'itemFk',
- align: 'left',
- sortable: true,
},
{
+ align: 'left',
label: t('ticketSale.quantity'),
name: 'quantity',
- field: 'quantity',
- align: 'left',
- sortable: true,
+ format: (row) => toCurrency(row.quantity),
},
{
+ align: 'left',
label: t('ticketSale.item'),
name: 'item',
- field: 'item',
- align: 'left',
- sortable: true,
+ format: (row) => row?.item?.name,
+ columnClass: 'expand',
},
{
+ align: 'left',
label: t('ticketSale.price'),
name: 'price',
- field: 'price',
- align: 'left',
- sortable: true,
- format: (val) => toCurrency(val),
+ format: (row) => toCurrency(row.price),
},
{
+ align: 'left',
label: t('ticketSale.discount'),
name: 'discount',
- field: 'discount',
- align: 'left',
- sortable: true,
+ format: (row) => toPercentage(row.discount),
},
{
+ align: 'left',
label: t('ticketSale.amount'),
name: 'amount',
- field: 'amount',
- align: 'left',
- sortable: true,
- format: (val) => toCurrency(val),
+ format: (row) => parseInt(row.amount * row.quantity),
},
{
+ align: 'left',
label: t('ticketSale.packaging'),
name: 'itemPackingTypeFk',
- field: 'item',
- align: 'left',
- sortable: true,
- format: (val) => dashIfEmpty(val?.itemPackingTypeFk),
+ format: (row, dashIfEmpty) => dashIfEmpty(row?.item?.itemPackingTypeFk),
},
{
- label: '',
- name: 'history',
- align: 'left',
- columnFilter: null,
+ align: 'right',
+ name: 'tableActions',
+ actions: [
+ {
+ title: t('ticketSale.history'),
+ icon: 'history',
+ isPrimary: true,
+ action: (row) => goToLog(row.id),
+ },
+ ],
},
]);
@@ -210,6 +216,7 @@ const addSale = async (sale) => {
sale.item = newSale.item;
notify('globals.dataSaved', 'positive');
+ window.location.reload();
} catch (err) {
console.error('Error adding sale', err);
}
@@ -259,7 +266,7 @@ const getMana = async () => {
const selectedValidSales = computed(() => {
if (!sales.value) return;
- return selectedSales.value.filter((sale) => sale.id != undefined);
+ return [...selectedRows.value];
});
const onOpenEditPricePopover = async (sale) => {
@@ -374,7 +381,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);
});
@@ -382,19 +389,29 @@ const removeSelectedSales = () => {
const removeSales = async () => {
try {
- const params = { sales: selectedValidSales.value, ticketId: store.data.id };
+ const params = {
+ sales: selectedRows.value.filter((sale) => sale.id),
+ ticketId: store.data.id,
+ };
+ selectedRows.value
+ .filter((sale) => !sale.id)
+ .forEach((sale) =>
+ tableRef.value.CrudModelRef.formData.splice(sale.$index, 1)
+ );
+
+ if (params.sales.length == 0) return;
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 {
+ selectedSales.value = selectedValidSales.value;
const checkedSales = JSON.parse(JSON.stringify(selectedSales.value));
transfer.value = {
lastActiveTickets: [],
@@ -418,9 +435,70 @@ onMounted(async () => {
stateStore.rightDrawer = true;
getConfig();
getSales();
+ getItems();
});
onUnmounted(() => (stateStore.rightDrawer = false));
+
+const items = ref([]);
+const newRow = ref({});
+
+async function getItems() {
+ const { data } = await axios.get(`Items/withName`);
+ items.value = data;
+}
+
+const updateItem = (row) => {
+ const selectedItem = items.value.find((item) => item.id === row.itemFk);
+ if (selectedItem) {
+ row.item = selectedItem;
+ row.itemFk = selectedItem.id;
+ row.price = selectedItem.price;
+ row.discount = 0;
+ row.quantity = 0;
+ row.amount = row.price * row.quantity;
+ }
+ endNewRow(selectedItem);
+};
+
+function handleOnDataSave({ CrudModelRef }) {
+ const { copy } = addRow(CrudModelRef.formData);
+ CrudModelRef.insert(copy);
+}
+
+const addRow = (original = null) => {
+ let copy = null;
+ if (!original) {
+ copy = { isNew: true };
+ } else {
+ copy = {
+ itemFk: original.itemFk,
+ item: original.item,
+ quantity: original.quantity,
+ price: original.price,
+ discount: original.discount,
+ amount: original.amount,
+ isNew: true,
+ };
+ }
+ newRow.value = copy;
+ return { original, copy };
+};
+
+const endNewRow = (row) => {
+ if (row.itemFk && row.quantity) {
+ row.isNew = false;
+ }
+};
+
+watch(
+ () => newRow.value.itemFk,
+ (newItemFk) => {
+ if (newItemFk) {
+ updateItem(newRow.value);
+ }
+ }
+);
@@ -471,7 +549,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
:ticket="store.data"
:is-ticket-editable="isTicketEditable"
:sales="selectedValidSales"
- :disable="!selectedSales.length"
+ :disable="!hasSelectedRows"
:mana="mana"
:ticket-config="ticketConfig"
@get-mana="getMana()"
@@ -480,7 +558,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
(stateStore.rightDrawer = false));
{{ t('Transfer lines') }}
@@ -507,246 +585,214 @@ onUnmounted(() => (stateStore.rightDrawer = false));
-
+
-
+
{{ t('ticketSale.subtotal') }}:
{{ toCurrency(store.data?.totalWithoutVat) }}
-
+
{{ t('ticketSale.tax') }}:
{{
toCurrency(store.data?.totalWithVat - store.data?.totalWithoutVat)
}}
-
+
{{ t('ticketSale.total') }}:
{{ toCurrency(store.data?.totalWithVat) }}
-
-
-
-
-
-
- {{ t('ticketSale.claim') }}:
- {{ row.claim?.claimFk }}
-
-
-
-
+
+
+
- {{ t('ticketSale.visible') }}: {{ row.visible || 0 }}
+ {{ t('ticketSale.claim') }}:
+ {{ row.claim?.claimFk }}
-
-
- {{ t('ticketSale.reserved') }}
-
-
-
-
- {{ t('ticketSale.noVisible') }}
-
-
-
-
- {{ t('ticketSale.hasComponentLack') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ row.visible }}
-
-
-
-
-
-
- {{ row.available }}
-
-
-
-
-
-
-
- {{ row.itemFk }}
-
-
-
-
-
-
-
- #{{ scope.opt?.id }}
- {{ scope.opt?.name }}
-
-
-
-
-
-
-
-
-
- {{ row.quantity }}
-
-
-
-
-
- {{ row.concept }}
- {{ row.item?.subName }}
-
-
-
-
-
-
-
-
-
-
-
- {{ toCurrency(row.price) }}
-
-
-
-
-
- {{ toCurrency(row.price) }}
-
-
-
-
-
-
- {{ toPercentage(row.discount / 100) }}
-
-
-
-
-
- {{ toPercentage(row.discount / 100) }}
-
-
-
-
-
-
- {{ t('ticketSale.history') }}
-
-
-
-
-
-
+
+
+ {{ t('ticketSale.visible') }}: {{ row.visible || 0 }}
+
+
+
+
+ {{ t('ticketSale.reserved') }}
+
+
+
- {{ t('Add item') }}
+ {{ t('ticketSale.noVisible') }}
-
+
+
+
+ {{ t('ticketSale.hasComponentLack') }}
+
+
-
+
+
+
+
+
+
+
+ {{ row.visible }}
+
+
+
+
+ {{ row.available }}
+
+
+
+
+
+
+
+
+ {{ scope.opt?.id }} - {{ scope.opt?.name }}
+
+
+
+
+
+ {{ row?.itemFk }}
+
+
+
+
+
+ {{ row?.item?.name }}
+
+ {{ row?.item?.subName.toUpperCase() }}
+
+
+
+
+
+
+
+
+
+
+ {{ row.quantity }}
+
+
+
+
+ {{ toCurrency(row.price) }}
+
+
+
+
+
+ {{ toCurrency(row.price) }}
+
+
+
+
+ {{ toPercentage(row.discount / 100) }}
+
+
+
+
+
+ {{ toPercentage(row.discount / 100) }}
+
+
+ {{ toCurrency(row.quantity * row.price) }}
+
+
-
+
{{ t('Add item to basket') }}
@@ -754,6 +800,18 @@ onUnmounted(() => (stateStore.rightDrawer = false));
+
+
es:
New item: Nuevo artículo
diff --git a/src/pages/Ticket/Card/TicketSaleTracking.vue b/src/pages/Ticket/Card/TicketSaleTracking.vue
index 6978d92c8..e7830bf37 100644
--- a/src/pages/Ticket/Card/TicketSaleTracking.vue
+++ b/src/pages/Ticket/Card/TicketSaleTracking.vue
@@ -25,7 +25,7 @@ const saleTrackingFetchDataRef = ref(null);
const sales = ref([]);
const saleTrackings = ref([]);
-const itemShelvignsSales = ref([]);
+const itemShelvingsSales = ref([]);
const saleTrackingUrl = computed(() => `SaleTrackings/${route.params.id}/filter`);
const oldQuantity = ref(null);
@@ -88,7 +88,7 @@ const logTableColumns = computed(() => [
label: t('ticketSaleTracking.original'),
name: 'original',
field: 'originalQuantity',
- align: 'original',
+ align: 'left',
sortable: true,
},
{
@@ -177,7 +177,7 @@ const getItemShelvingSales = async (sale) => {
const { data } = await axios.get(`ItemShelvingSales/filter`, {
params: { filter: JSON.stringify(filter) },
});
- itemShelvignsSales.value = data;
+ itemShelvingsSales.value = data;
} catch (error) {
console.error(error);
}
@@ -337,7 +337,7 @@ const qCheckBoxController = (sale, action) => {
:no-data-label="t('globals.noResults')"
>
-
+
{
-
+
-
- {{ row.itemFk }}
-
-
+
+
+ {{ row.itemFk }}
+
+
+
@@ -416,8 +418,18 @@ const qCheckBoxController = (sale, action) => {
+
+
+ {{ row.quantity }}
+
+
+
+
+ {{ dashIfEmpty(row.parkingFk) }}
+
+
-
+
{
data-key="saleTrackingLog"
:rows="saleTrackings"
:columns="logTableColumns"
- class="q-pa-sm"
+ class="q-pa-sm full-width"
>
-
- {{ row.name }}
-
+
+
+ {{ row.name }}
+
+
@@ -469,12 +483,12 @@ const qCheckBoxController = (sale, action) => {
>
-
+
{
-
- {{ row.name }}
-
+
+
+ {{ row.name }}
+
+
-
+
{
-
+
div {
+ max-width: 900px;
+ }
+}
diff --git a/src/pages/Ticket/Card/TicketService.vue b/src/pages/Ticket/Card/TicketService.vue
index 873051676..45a870f7f 100644
--- a/src/pages/Ticket/Card/TicketService.vue
+++ b/src/pages/Ticket/Card/TicketService.vue
@@ -25,7 +25,7 @@ const { notify } = useNotify();
const selected = ref([]);
const defaultTaxClass = ref(null);
-
+const isSaving = ref(false);
const crudModelFilter = computed(() => ({
where: { ticketFk: route.params.id },
}));
@@ -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,
};
@@ -104,7 +104,31 @@ const columns = computed(() => [
sortable: true,
align: 'left',
},
+ {
+ label: '',
+ name: 'actions',
+ align: 'left',
+ columnFilter: null,
+ },
]);
+
+async function deleteService(row) {
+ const serviceId = row.id;
+ if (!row.id) ticketServiceCrudRef.value.reset();
+ else {
+ const { data } = await axios.delete(`TicketServices/${serviceId}`);
+ if (data) notify('Service deleted successfully', 'positive');
+ ticketServiceCrudRef.value.reload();
+ }
+}
+
+async function handleSave() {
+ if (!isSaving.value) {
+ isSaving.value = true;
+ await ticketServiceCrudRef.value?.saveChanges();
+ isSaving.value = false;
+ }
+}
@@ -123,6 +147,8 @@ const columns = computed(() => [
:data-required="crudModelRequiredData"
auto-load
v-model:selected="selected"
+ :order="['description ASC']"
+ :default-remove="false"
>
[
v-model.number="row.price"
type="number"
min="0"
+ @keyup.enter="handleSave"
/>
+
+
+
+
+ {{ t('globals.delete') }}
+
+
+
+
@@ -193,3 +235,4 @@ const columns = computed(() => [
/>
+ñ
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index 6af782173..b6a60122c 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -1,4 +1,5 @@
(editableStates = data)"
+ :filter="{ fields: ['code', 'name', 'id', 'alertLevel'], order: 'name ASC' }"
auto-load
+ @on-fetch="(data) => (editableStates = data)"
/>
-
-
-
-
- {{ item.name }}
-
-
-
-
+
-
+
-
- {{ entity.ticketState?.state?.name }}
-
+
+ {{ entity.ticketState.state.name }}
+
@@ -148,7 +169,14 @@ async function changeState(value) {
:label="t('ticket.summary.agency')"
:value="entity.agencyMode?.name"
/>
-
+
+
+
+ {{ entity?.zone?.name }}
+
+
+
+
-
+
+
+
+ {{ entity.routeFk }}
+
+
+
+
@@ -185,9 +220,9 @@ async function changeState(value) {
:value="dashIfEmpty(entity.weight)"
/>
-
+
@@ -246,6 +281,7 @@ async function changeState(value) {
type="textarea"
class="notes"
readonly
+ autogrow
/>
@@ -263,13 +299,14 @@ async function changeState(value) {
/>