diff --git a/src/boot/vnDate.js b/src/boot/vnDate.js
index 33d5ac27f..8f18e2400 100644
--- a/src/boot/vnDate.js
+++ b/src/boot/vnDate.js
@@ -1,4 +1,6 @@
import { boot } from 'quasar/wrappers';
+import { date as quasarDate } from 'quasar';
+const { formatDate } = quasarDate;
export default boot(() => {
Date.vnUTC = () => {
@@ -25,4 +27,34 @@ export default boot(() => {
const date = new Date(Date.vnUTC());
return new Date(date.getFullYear(), date.getMonth() + 1, 0);
};
+
+ Date.getCurrentDateTimeFormatted = (
+ options = {
+ startOfDay: false,
+ endOfDay: true,
+ iso: true,
+ mask: 'DD-MM-YYYY HH:mm',
+ },
+ ) => {
+ const date = Date.vnUTC();
+ if (options.startOfDay) {
+ date.setHours(0, 0, 0);
+ }
+ if (options.endOfDay) {
+ date.setHours(23, 59, 0);
+ }
+ if (options.iso) {
+ return date.toISOString();
+ }
+ return formatDate(date, options.mask);
+ };
+
+ Date.convertToISODateTime = (dateTimeStr) => {
+ const [datePart, timePart] = dateTimeStr.split(' ');
+ const [day, month, year] = datePart.split('-');
+ const [hours, minutes] = timePart.split(':');
+
+ const isoDate = new Date(year, month - 1, day, hours, minutes);
+ return isoDate.toISOString();
+ };
});
diff --git a/src/components/EditPictureForm.vue b/src/components/EditPictureForm.vue
index 1f158e785..29377b559 100644
--- a/src/components/EditPictureForm.vue
+++ b/src/components/EditPictureForm.vue
@@ -140,7 +140,7 @@ const updatePhotoPreview = (value) => {
img.onerror = () => {
notify(
t("This photo provider doesn't allow remote downloads"),
- 'negative'
+ 'negative',
);
};
}
@@ -219,11 +219,7 @@ const makeRequest = async () => {
color="primary"
class="cursor-pointer"
@click="rotateLeft()"
- >
-
-
+ />
@@ -233,11 +229,7 @@ const makeRequest = async () => {
color="primary"
class="cursor-pointer"
@click="rotateRight()"
- >
-
-
+ />
@@ -265,7 +257,6 @@ const makeRequest = async () => {
class="cursor-pointer q-mr-sm"
@click="openInputFile()"
>
-
{{
diff --git a/src/components/common/VnAccountNumber.vue b/src/components/common/VnAccountNumber.vue
index 8bff3e261..5bce49459 100644
--- a/src/components/common/VnAccountNumber.vue
+++ b/src/components/common/VnAccountNumber.vue
@@ -8,7 +8,8 @@ const model = defineModel({ prop: 'modelValue' });
diff --git a/src/components/common/VnInputDateTime.vue b/src/components/common/VnInputDateTime.vue
new file mode 100644
index 000000000..b239d528a
--- /dev/null
+++ b/src/components/common/VnInputDateTime.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ es:
+ Open date: Abrir fecha
+
diff --git a/src/components/common/__tests__/VnInputDateTime.spec.js b/src/components/common/__tests__/VnInputDateTime.spec.js
new file mode 100644
index 000000000..23132d77d
--- /dev/null
+++ b/src/components/common/__tests__/VnInputDateTime.spec.js
@@ -0,0 +1,81 @@
+import { createWrapper } from 'app/test/vitest/helper.js';
+import { describe, it, expect, beforeAll } from 'vitest';
+import VnInputDateTime from 'components/common/VnInputDateTime.vue';
+import vnDateBoot from 'src/boot/vnDate';
+
+let vm;
+let wrapper;
+
+beforeAll(() => {
+ // Initialize the vnDate boot
+ vnDateBoot();
+});
+function generateWrapper(date, outlined, showEvent) {
+ wrapper = createWrapper(VnInputDateTime, {
+ props: {
+ modelValue: date,
+ isOutlined: outlined,
+ showEvent: showEvent,
+ },
+ });
+ wrapper = wrapper.wrapper;
+ vm = wrapper.vm;
+}
+
+describe('VnInputDateTime', () => {
+ describe('selectedDate', () => {
+ it('formats a valid datetime correctly', async () => {
+ generateWrapper('2023-12-25T10:30:00', false, true);
+ await vm.$nextTick();
+ expect(vm.selectedDate).toBe('25-12-2023 10:30');
+ });
+
+ it('handles null date value', async () => {
+ generateWrapper(null, false, true);
+ await vm.$nextTick();
+ expect(vm.selectedDate).toBeInstanceOf(Date);
+ });
+
+ it('updates the model value when a new datetime is set', async () => {
+ vm.selectedDate = '31-12-2023 15:45';
+ await vm.$nextTick();
+ expect(wrapper.emitted()['update:modelValue']).toBeTruthy();
+ });
+ });
+
+ describe('styleAttrs', () => {
+ it('should return empty styleAttrs when isOutlined is false', async () => {
+ generateWrapper('2023-12-25T10:30:00', false, true);
+ await vm.$nextTick();
+ expect(vm.styleAttrs).toEqual({});
+ });
+
+ it('should set styleAttrs when isOutlined is true', async () => {
+ generateWrapper('2023-12-25T10:30:00', true, true);
+ await vm.$nextTick();
+ expect(vm.styleAttrs).toEqual({
+ dense: true,
+ outlined: true,
+ rounded: true,
+ });
+ });
+ });
+
+ describe('component rendering', () => {
+ it('should render date and time icons', async () => {
+ generateWrapper('2023-12-25T10:30:00', false, true);
+ await vm.$nextTick();
+ const icons = wrapper.findAllComponents({ name: 'QIcon' });
+ expect(icons.length).toBe(2);
+ expect(icons[0].props('name')).toBe('today');
+ expect(icons[1].props('name')).toBe('access_time');
+ });
+
+ it('should render popup proxies for date and time', async () => {
+ generateWrapper('2023-12-25T10:30:00', false, true);
+ await vm.$nextTick();
+ const popups = wrapper.findAllComponents({ name: 'QPopupProxy' });
+ expect(popups.length).toBe(2);
+ });
+ });
+});
diff --git a/src/components/ui/EntityDescriptor.vue b/src/components/ui/EntityDescriptor.vue
index a5dced551..e6adaa5f7 100644
--- a/src/components/ui/EntityDescriptor.vue
+++ b/src/components/ui/EntityDescriptor.vue
@@ -44,7 +44,8 @@ onBeforeMount(async () => {
});
// It enables to load data only once if the module is the same as the dataKey
- if (!isSameDataKey.value || !route.params.id) await getData();
+ if (!isSameDataKey.value || !route.params.id || $props.id !== route.params.id)
+ await getData();
watch(
() => [$props.url, $props.filter],
async () => {
@@ -58,7 +59,8 @@ async function getData() {
store.filter = $props.filter ?? {};
isLoading.value = true;
try {
- const { data } = await arrayData.fetch({ append: false, updateRouter: false });
+ await arrayData.fetch({ append: false, updateRouter: false });
+ const { data } = store;
state.set($props.dataKey, data);
emit('onFetch', data);
} finally {
diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml
index 8d18cf648..de5a27ff2 100644
--- a/src/i18n/locale/en.yml
+++ b/src/i18n/locale/en.yml
@@ -20,6 +20,7 @@ globals:
logOut: Log out
date: Date
dataSaved: Data saved
+ openDetail: Open detail
dataDeleted: Data deleted
delete: Delete
search: Search
diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml
index 7822d8b80..84ba150c4 100644
--- a/src/i18n/locale/es.yml
+++ b/src/i18n/locale/es.yml
@@ -21,10 +21,11 @@ globals:
date: Fecha
dataSaved: Datos guardados
dataDeleted: Datos eliminados
+ dataCreated: Datos creados
+ openDetail: Ver detalle
delete: Eliminar
search: Buscar
changes: Cambios
- dataCreated: Datos creados
add: Añadir
create: Crear
edit: Modificar
diff --git a/src/pages/Item/components/ItemProposal.vue b/src/pages/Item/components/ItemProposal.vue
index edff4f394..bd0fdc0c2 100644
--- a/src/pages/Item/components/ItemProposal.vue
+++ b/src/pages/Item/components/ItemProposal.vue
@@ -6,10 +6,12 @@ import { toCurrency } from 'filters/index';
import VnStockValueDisplay from 'src/components/ui/VnStockValueDisplay.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
import axios from 'axios';
-import notifyResults from 'src/utils/notifyResults';
+import { displayResults } from 'src/pages/Ticket/Negative/composables/notifyResults';
import FetchData from 'components/FetchData.vue';
+import { useState } from 'src/composables/useState';
const MATCH = 'match';
+const { notifyResults } = displayResults();
const { t } = useI18n();
const $props = defineProps({
@@ -18,14 +20,20 @@ const $props = defineProps({
required: true,
default: () => {},
},
+ filter: {
+ type: Object,
+ required: true,
+ default: () => {},
+ },
replaceAction: {
type: Boolean,
- required: false,
+ required: true,
default: false,
},
+
sales: {
type: Array,
- required: false,
+ required: true,
default: () => [],
},
});
@@ -36,6 +44,8 @@ const proposalTableRef = ref(null);
const sale = computed(() => $props.sales[0]);
const saleFk = computed(() => sale.value.saleFk);
const filter = computed(() => ({
+ where: $props.filter,
+
itemFk: $props.itemLack.itemFk,
sales: saleFk.value,
}));
diff --git a/src/pages/Item/components/ItemProposalProxy.vue b/src/pages/Item/components/ItemProposalProxy.vue
index 7da0ce398..27edd3670 100644
--- a/src/pages/Item/components/ItemProposalProxy.vue
+++ b/src/pages/Item/components/ItemProposalProxy.vue
@@ -1,13 +1,17 @@
diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
index f7389b592..30024fb26 100644
--- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
@@ -28,6 +28,7 @@ const props = defineProps({
onMounted(() => {
restoreTicket();
+ hasDocuware();
});
watch(
diff --git a/src/pages/Ticket/Card/TicketDescriptorProxy.vue b/src/pages/Ticket/Card/TicketDescriptorProxy.vue
index ba8367e81..8b872733d 100644
--- a/src/pages/Ticket/Card/TicketDescriptorProxy.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorProxy.vue
@@ -1,7 +1,6 @@
-
+