diff --git a/src/components/common/VnModule.vue b/src/components/common/VnModule.vue
index 038ee1d60..747a7c951 100644
--- a/src/components/common/VnModule.vue
+++ b/src/components/common/VnModule.vue
@@ -12,7 +12,7 @@ const $props = defineProps({
},
});
onMounted(
- () => (stateStore.leftDrawer = useQuasar().screen.gt.xs ? $props.leftDrawer : false)
+ () => (stateStore.leftDrawer = useQuasar().screen.gt.xs ? $props.leftDrawer : false),
);
const teleportRef = ref({});
@@ -35,8 +35,14 @@ onMounted(() => {
-
-
+
+
+
+
+
+
+
+
diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue
index 324da0771..c98bf1ffb 100644
--- a/src/pages/Customer/Card/CustomerSummary.vue
+++ b/src/pages/Customer/Card/CustomerSummary.vue
@@ -325,7 +325,7 @@ const sumRisk = ({ clientRisks }) => {
-
+
diff --git a/src/pages/Customer/components/CustomerSummaryTable.vue b/src/pages/Customer/components/CustomerSummaryTable.vue
index bb6f4442b..09c7e714c 100644
--- a/src/pages/Customer/components/CustomerSummaryTable.vue
+++ b/src/pages/Customer/components/CustomerSummaryTable.vue
@@ -20,7 +20,12 @@ const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const { viewSummary } = useSummaryDialog();
-
+const $props = defineProps({
+ id: {
+ type: Number,
+ default: null,
+ },
+});
const filter = {
include: [
{
@@ -43,7 +48,7 @@ const filter = {
},
},
],
- where: { clientFk: route.params.id },
+ where: { clientFk: $props.id ?? route.params.id },
order: ['shipped DESC', 'id'],
limit: 30,
};
diff --git a/src/pages/Customer/composables/__tests__/getAddresses.spec.js b/src/pages/Customer/composables/__tests__/getAddresses.spec.js
index 9e04a83cc..8c90bf281 100644
--- a/src/pages/Customer/composables/__tests__/getAddresses.spec.js
+++ b/src/pages/Customer/composables/__tests__/getAddresses.spec.js
@@ -17,9 +17,9 @@ describe('getAddresses', () => {
expect(axios.get).toHaveBeenCalledWith(`Clients/${clientId}/addresses`, {
params: {
filter: JSON.stringify({
- fields: ['nickname', 'street', 'city', 'id'],
+ fields: ['nickname', 'street', 'city', 'id', 'isActive'],
where: { isActive: true },
- order: 'nickname ASC',
+ order: ['isDefaultAddress DESC', 'isActive DESC', 'nickname ASC'],
}),
},
});
@@ -30,4 +30,4 @@ describe('getAddresses', () => {
expect(axios.get).not.toHaveBeenCalled();
});
-});
\ No newline at end of file
+});
diff --git a/src/pages/Customer/composables/getAddresses.js b/src/pages/Customer/composables/getAddresses.js
index e65e64455..5f18530e7 100644
--- a/src/pages/Customer/composables/getAddresses.js
+++ b/src/pages/Customer/composables/getAddresses.js
@@ -1,15 +1,15 @@
import axios from 'axios';
-export async function getAddresses(clientId, _filter = {}) {
+export async function getAddresses(clientId, _filter = {}) {
if (!clientId) return;
const filter = {
..._filter,
- fields: ['nickname', 'street', 'city', 'id'],
+ fields: ['nickname', 'street', 'city', 'id', 'isActive'],
where: { isActive: true },
- order: 'nickname ASC',
+ order: ['isDefaultAddress DESC', 'isActive DESC', 'nickname ASC'],
};
const params = { filter: JSON.stringify(filter) };
return await axios.get(`Clients/${clientId}/addresses`, {
params,
});
-};
\ No newline at end of file
+}
diff --git a/src/pages/Item/Card/ItemDiary.vue b/src/pages/Item/Card/ItemDiary.vue
index 83cd562a0..f839c1f71 100644
--- a/src/pages/Item/Card/ItemDiary.vue
+++ b/src/pages/Item/Card/ItemDiary.vue
@@ -158,15 +158,10 @@ const getBadgeAttrs = (_date) => {
const scrollToToday = async () => {
await nextTick();
- const todayCell = document.querySelector(`td[data-date="${today.toISOString()}"]`);
- if (todayCell) {
- todayCell.scrollIntoView({ behavior: 'smooth', block: 'center' });
- }
-};
-
-const formatDateForAttribute = (dateValue) => {
- if (dateValue instanceof Date) return date.formatDate(dateValue, 'YYYY-MM-DD');
- return dateValue;
+ const todayCell = document.querySelector(
+ `td[data-date="${date.formatDate(today, 'YYYY-MM-DD')}"]`,
+ );
+ if (todayCell) todayCell.scrollIntoView({ behavior: 'smooth', block: 'center' });
};
async function updateWarehouse(warehouseFk) {
@@ -242,7 +237,7 @@ async function updateWarehouse(warehouseFk) {
-
+
{
+onMounted(async () => {
stateStore.rightDrawer = true;
checkOrderConfirmation();
+
+ if (
+ arrayData.store.userParams &&
+ Object.keys(arrayData.store.userParams).some((key) => !key.startsWith('order'))
+ ) {
+ await arrayData.fetch({});
+ }
});
+onUnmounted(() => {
+ arrayData.destroy();
+});
+
+function exprBuilder(param, value) {
+ switch (param) {
+ case 'categoryFk':
+ case 'typeFk':
+ return { [param]: value };
+ case 'search':
+ if (/^\d+$/.test(value)) return { 'i.id': value };
+ else return { 'i.name': { like: `%${value}%` } };
+ }
+}
+
async function checkOrderConfirmation() {
const response = await axios.get(`Orders/${route.params.id}`);
if (response.data.isConfirmed === 1) {
@@ -96,6 +121,7 @@ watch(
:tag-value="tagValue"
:tags="tags"
:initial-catalog-params="catalogParams"
+ :arrayData
/>
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 76e608983..d16a92017 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -24,6 +24,10 @@ const props = defineProps({
type: Array,
required: true,
},
+ arrayData: {
+ type: Object,
+ required: true,
+ },
});
const { t } = useI18n();
@@ -74,17 +78,6 @@ const loadTypes = async (id) => {
typeList.value = data;
};
-function exprBuilder(param, value) {
- switch (param) {
- case 'categoryFk':
- case 'typeFk':
- return { [param]: value };
- case 'search':
- if (/^\d+$/.test(value)) return { 'i.id': value };
- else return { 'i.name': { like: `%${value}%` } };
- }
-}
-
const applyTags = (tagInfo, params, search) => {
if (!tagInfo || !tagInfo.values.length) {
params.tagGroups = null;
@@ -152,9 +145,8 @@ function addOrder(value, field, params) {
:data-key="props.dataKey"
:hidden-tags="['filter', 'orderFk', 'orderBy']"
:unremovable-params="['orderFk', 'orderBy']"
- :expr-builder="exprBuilder"
:custom-tags="['tagGroups', 'categoryFk']"
- :redirect="false"
+ :arrayData
>
diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue
index 40990f329..59ec37f98 100644
--- a/src/pages/Order/OrderList.vue
+++ b/src/pages/Order/OrderList.vue
@@ -155,11 +155,23 @@ onMounted(() => {
});
async function fetchClientAddress(id, formData = {}) {
- const { data } = await axios.get(
- `Clients/${id}/addresses?filter[order]=isActive DESC`
- );
+ const { data } = await axios.get(`Clients/${id}/addresses`, {
+ params: {
+ filter: JSON.stringify({
+ include: [
+ {
+ relation: 'client',
+ scope: {
+ fields: ['defaultAddressFk'],
+ },
+ },
+ ],
+ order: ['isActive DESC'],
+ }),
+ },
+ });
addressOptions.value = data;
- formData.addressId = data.defaultAddressFk;
+ formData.addressId = data[0].client.defaultAddressFk;
fetchAgencies(formData);
}
@@ -167,7 +179,13 @@ async function fetchAgencies({ landed, addressId }) {
if (!landed || !addressId) return (agencyList.value = []);
const { data } = await axios.get('Agencies/landsThatDay', {
- params: { addressFk: addressId, landed },
+ params: {
+ filter: JSON.stringify({
+ order: ['agencyMode DESC', 'agencyModeFk ASC'],
+ }),
+ addressFk: addressId,
+ landed,
+ },
});
agencyList.value = data;
}
@@ -258,6 +276,7 @@ const getDateColor = (date) => {
{
{{ scope.opt?.street }},
{{ scope.opt?.city }}
+
+ {{ `#${scope.opt?.id}` }}
+
diff --git a/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js b/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js
index ccf7872cb..99966569c 100644
--- a/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js
+++ b/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js
@@ -27,14 +27,17 @@ describe('getAgencies', () => {
landed: 'true',
};
const filter = {
- fields: ['nickname', 'street', 'city', 'id'],
+ fields: ['name', 'street', 'city', 'id'],
where: { isActive: true },
- order: 'nickname ASC',
+ order: ['name ASC'],
};
await getAgencies(formData, null, filter);
- expect(axios.get).toHaveBeenCalledWith('Agencies/getAgenciesWithWarehouse', generateParams(formData, filter));
+ expect(axios.get).toHaveBeenCalledWith(
+ 'Agencies/getAgenciesWithWarehouse',
+ generateParams(formData, filter),
+ );
});
it('should not call API when formData is missing required landed field', async () => {
@@ -64,19 +67,19 @@ describe('getAgencies', () => {
it('should return options and agency when default agency is found', async () => {
const formData = { warehouseId: '123', addressId: '456', landed: 'true' };
const client = { defaultAddress: { agencyModeFk: 'Agency1' } };
-
+
const { options, agency } = await getAgencies(formData, client);
-
+
expect(options).toEqual(response.data);
expect(agency).toEqual(response.data[0]);
- });
+ });
- it('should return options and agency when client is not provided', async () => {
+ it('should return options and agency when client is not provided', async () => {
const formData = { warehouseId: '123', addressId: '456', landed: 'true' };
-
+
const { options, agency } = await getAgencies(formData);
-
+
expect(options).toEqual(response.data);
expect(agency).toBeNull();
- });
+ });
});
diff --git a/src/pages/Route/Agency/composables/getAgencies.js b/src/pages/Route/Agency/composables/getAgencies.js
index 850f87456..180ac943e 100644
--- a/src/pages/Route/Agency/composables/getAgencies.js
+++ b/src/pages/Route/Agency/composables/getAgencies.js
@@ -1,14 +1,14 @@
import axios from 'axios';
-import agency from 'src/router/modules/agency';
export async function getAgencies(formData, client, _filter = {}) {
if (!formData.warehouseId || !formData.addressId || !formData.landed) return;
-
+
const filter = {
- ..._filter
+ ..._filter,
+ order: ['name ASC'],
};
- let defaultAgency = null;
+ let agency = null;
let params = {
filter: JSON.stringify(filter),
warehouseFk: formData.warehouseId,
@@ -16,11 +16,15 @@ export async function getAgencies(formData, client, _filter = {}) {
landed: formData.landed,
};
- const { data } = await axios.get('Agencies/getAgenciesWithWarehouse', { params });
+ const { data: options } = await axios.get('Agencies/getAgenciesWithWarehouse', {
+ params,
+ });
- if(data && client) {
- defaultAgency = data.find((agency) => agency.agencyModeFk === client.defaultAddress.agencyModeFk );
- };
-
- return {options: data, agency: defaultAgency}
+ if (options && client) {
+ agency = options.find(
+ ({ agencyModeFk }) => agencyModeFk === client.defaultAddress.agencyModeFk,
+ );
+ }
+
+ return { options, agency };
}
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index f8084ff2f..a41d492ed 100644
--- a/src/pages/Ticket/Card/TicketExpedition.vue
+++ b/src/pages/Ticket/Card/TicketExpedition.vue
@@ -105,6 +105,9 @@ const columns = computed(() => [
name: 'created',
align: 'left',
cardVisible: true,
+ columnFilter: {
+ component: 'date',
+ },
format: (row) => toDateTimeFormat(row.created),
},
{
@@ -201,7 +204,7 @@ const getExpeditionState = async (expedition) => {
const openGrafana = (expeditionFk) => {
useOpenURL(
- `https://grafana.verdnatura.es/d/de1njb6p5answd/control-de-expediciones?orgId=1&var-expeditionFk=${expeditionFk}`
+ `https://grafana.verdnatura.es/d/de1njb6p5answd/control-de-expediciones?orgId=1&var-expeditionFk=${expeditionFk}`,
);
};
@@ -287,7 +290,7 @@ onMounted(async () => {
openConfirmationModal(
'',
t('expedition.removeExpeditionSubtitle'),
- deleteExpedition
+ deleteExpedition,
)
"
>
@@ -302,7 +305,6 @@ onMounted(async () => {
url="Expeditions/filter"
search-url="expeditions"
:columns="columns"
- :filter="expeditionsFilter"
v-model:selected="selectedRows"
:table="{
'row-key': 'id',
@@ -316,6 +318,8 @@ onMounted(async () => {
return { id: value };
case 'packageItemName':
return { packagingItemFk: value };
+ case 'created':
+ return { 'e.created': { gte: value } };
}
}
"
diff --git a/src/pages/Ticket/Card/TicketService.vue b/src/pages/Ticket/Card/TicketService.vue
index 6ce69a6aa..1bd1548a4 100644
--- a/src/pages/Ticket/Card/TicketService.vue
+++ b/src/pages/Ticket/Card/TicketService.vue
@@ -121,6 +121,50 @@ async function handleSave() {
isSaving.value = false;
}
}
+function validateFields(item) {
+ // Only validate fields that are being updated
+ const shouldExist = (field) => !isUpdate || field in item;
+
+ if (!shouldExist('ticketServiceTypeFk') && !item.ticketServiceTypeFk) {
+ notify('Description is required', 'negative');
+ return false;
+ }
+
+ if (!shouldExist('quantity') && (!item.quantity || item.quantity <= 0)) {
+ notify('Quantity must be greater than 0', 'negative');
+ return false;
+ }
+
+ if (!shouldExist('price') && (!item.price || item.price < 0)) {
+ notify('Price must be valid', 'negative');
+ return false;
+ }
+
+ return true;
+}
+
+function beforeSave(data) {
+ const { creates = [], updates = [] } = data;
+ const validData = { creates: [], updates: [] };
+
+ // Validate creates
+ if (creates.length) {
+ for (const create of creates) {
+ create.ticketFk = route.params.id;
+ if (validateFields(create)) {
+ validData.creates.push(create);
+ }
+ }
+ }
+
+ // Validate updates
+ if (updates.length) {
+ for (const update of updates) {
+ validData.updates.push(update);
+ }
+ }
+ return validData;
+}
@@ -141,6 +185,7 @@ async function handleSave() {
v-model:selected="selected"
:order="['description ASC']"
:default-remove="false"
+ :beforeSaveFn="beforeSave"
>
@@ -196,6 +243,7 @@ async function handleSave() {
:label="col.label"
v-model.number="row.price"
type="number"
+ :required="true"
min="0"
@keyup.enter="handleSave"
/>
diff --git a/src/pages/Ticket/Card/TicketTransferProxy.vue b/src/pages/Ticket/Card/TicketTransferProxy.vue
index 3f3f018df..7d5d82f85 100644
--- a/src/pages/Ticket/Card/TicketTransferProxy.vue
+++ b/src/pages/Ticket/Card/TicketTransferProxy.vue
@@ -42,7 +42,7 @@ const transferRef = ref(null);
/>
-
+
(stateStore.rightDrawer = true));
{{ row.item.name }}
{{ row.item.subName }}
-
+
{{ packingTypeVolume?.[rowIndex]?.volume }}
diff --git a/src/pages/Ticket/TicketAdvance.vue b/src/pages/Ticket/TicketAdvance.vue
index 05bd14075..94b4623aa 100644
--- a/src/pages/Ticket/TicketAdvance.vue
+++ b/src/pages/Ticket/TicketAdvance.vue
@@ -456,6 +456,7 @@ watch(
:pagination="{ rowsPerPage: 0 }"
:no-data-label="t('globals.noResults')"
:right-search="false"
+ :order="['futureTotalWithVat ASC']"
auto-load
:disable-option="{ card: true }"
>
diff --git a/src/pages/Ticket/TicketFilter.vue b/src/pages/Ticket/TicketFilter.vue
index c82c0067f..5da2a858c 100644
--- a/src/pages/Ticket/TicketFilter.vue
+++ b/src/pages/Ticket/TicketFilter.vue
@@ -46,7 +46,12 @@ const getGroupedStates = (data) => {
"
auto-load
/>
- (agencies = data)" auto-load />
+ (agencies = data)"
+ auto-load
+ />
(warehouses = data)" auto-load />
@@ -74,10 +79,20 @@ const getGroupedStates = (data) => {
-
+
-
+
diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index 33b841d2d..c2d8f39f3 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -1,6 +1,6 @@
@@ -456,7 +495,7 @@ function setReference(data) {
urlCreate: 'Tickets/new',
title: t('ticketList.createTicket'),
onDataSaved: ({ id }) => tableRef.redirect(id),
- formInitialData: { clientId: null },
+ formInitialData,
}"
default-mode="table"
:columns="columns"
@@ -538,11 +577,9 @@ function setReference(data) {
:label="t('ticketList.client')"
v-model="data.clientId"
:options="clientsOptions"
- option-value="id"
- option-label="name"
hide-selected
required
- @update:model-value="(client) => onClientSelected(data)"
+ @update:model-value="() => onClientSelected(data)"
:sort-by="'id ASC'"
>
@@ -564,7 +601,6 @@ function setReference(data) {
:label="t('basicData.address')"
v-model="data.addressId"
:options="addressesOptions"
- option-value="id"
option-label="nickname"
hide-selected
map-options
@@ -610,6 +646,9 @@ function setReference(data) {
{{ scope.opt?.city }}
+
+ {{ `#${scope.opt?.id}` }}
+
@@ -633,8 +672,6 @@ function setReference(data) {
:label="t('globals.warehouse')"
v-model="data.warehouseId"
:options="warehousesOptions"
- option-value="id"
- option-label="name"
hide-selected
required
@update:model-value="() => fetchAvailableAgencies(data)"
@@ -694,7 +731,6 @@ function setReference(data) {
:label="t('ticketList.company')"
v-model="dialogData.companyFk"
:options="companiesOptions"
- option-value="id"
option-label="code"
hide-selected
>
@@ -705,7 +741,6 @@ function setReference(data) {
:label="t('ticketList.bank')"
v-model="dialogData.bankFk"
:options="accountingOptions"
- option-value="id"
option-label="bank"
hide-selected
@update:model-value="setReference"
diff --git a/src/pages/Worker/Card/WorkerBasicData.vue b/src/pages/Worker/Card/WorkerBasicData.vue
index 56a9548c6..a78983e5c 100644
--- a/src/pages/Worker/Card/WorkerBasicData.vue
+++ b/src/pages/Worker/Card/WorkerBasicData.vue
@@ -1,5 +1,5 @@