Merge branch 'dev' into 8217_mapper

This commit is contained in:
Javier Segarra 2025-05-07 20:22:37 +02:00
commit ef1732c6f2
147 changed files with 4987 additions and 811 deletions

View File

@ -26,7 +26,7 @@ if (branchName) {
const splitedMsg = msg.split(':');
if (splitedMsg.length > 1) {
const finalMsg = splitedMsg[0] + ': ' + referenceTag + splitedMsg.slice(1).join(':');
const finalMsg = `${splitedMsg[0]}: ${referenceTag}${splitedMsg.slice(1).join(':')}`;
writeFileSync(msgPath, finalMsg);
}
}

View File

@ -1,6 +1,9 @@
import { defineConfig } from 'cypress';
let urlHost, reporter, reporterOptions, timeouts;
let urlHost;
let reporter;
let reporterOptions;
let timeouts;
if (process.env.CI) {
urlHost = 'front';

View File

@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html>
<head>
<title><%= productName %></title>
@ -12,7 +12,12 @@
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>"
/>
<link rel="icon" type="image/png" sizes="128x128" href="icons/favicon-128x128.png" />
<link
rel="icon"
type="image/png"
sizes="128x128"
href="icons/favicon-128x128.png"
/>
<link rel="icon" type="image/png" sizes="96x96" href="icons/favicon-96x96.png" />
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png" />

View File

@ -1,4 +1,3 @@
/* eslint-disable */
// https://github.com/michael-ciniawsky/postcss-load-config
import autoprefixer from 'autoprefixer';

View File

@ -13,7 +13,7 @@ import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
import path from 'path';
const target = `http://${process.env.CI ? 'back' : 'localhost'}:3000`;
export default configure(function (/* ctx */) {
export default configure((/* ctx */) => {
return {
eslint: {
// fix: true,

View File

@ -1,8 +1,6 @@
{
"@quasar/testing-unit-vitest": {
"options": [
"scripts"
]
"options": ["scripts"]
},
"@quasar/qcalendar": {}
}

View File

@ -11,8 +11,8 @@ export default function (component, key, value) {
};
break;
case 'undefined':
throw new Error('unknown prop: ' + key);
throw new Error(`unknown prop: ${key}`);
default:
throw new Error('unhandled type: ' + typeof prop);
throw new Error(`unhandled type: ${typeof prop}`);
}
}

View File

@ -9,7 +9,7 @@ export default {
const keyBindingMap = routes
.filter((route) => route.meta.keyBinding)
.reduce((map, route) => {
map['Key' + route.meta.keyBinding.toUpperCase()] = route.path;
map[`Key${route.meta.keyBinding.toUpperCase()}`] = route.path;
return map;
}, {});

View File

@ -1,4 +1,3 @@
/* eslint-disable eslint/export */
export * from './defaults/qTable';
export * from './defaults/qInput';
export * from './defaults/qSelect';

View File

@ -24,12 +24,9 @@ export default boot(({ app }) => {
switch (response?.status) {
case 422:
if (error.name == 'ValidationError')
message +=
' "' +
responseError.details.context +
'.' +
Object.keys(responseError.details.codes).join(',') +
'"';
message += ` "${responseError.details.context}.${Object.keys(
responseError.details.codes,
).join(',')}"`;
break;
case 500:
message = 'errors.statusInternalServerError';

View File

@ -25,7 +25,7 @@ const autonomiesRef = ref([]);
const onDataSaved = (dataSaved, requestResponse) => {
requestResponse.autonomy = autonomiesRef.value.opts.find(
(autonomy) => autonomy.id == requestResponse.autonomyFk
(autonomy) => autonomy.id == requestResponse.autonomyFk,
);
emit('onDataSaved', dataSaved, requestResponse);
};

View File

@ -347,8 +347,16 @@ watch(formUrl, async () => {
<QBtnDropdown
v-if="$props.goTo && $props.defaultSave"
@click="onSubmitAndGo"
:label="tMobile('globals.saveAndContinue') + ' ' + t('globals.' + $props.goTo.split('/').pop())"
:title="t('globals.saveAndContinue') + ' ' + t('globals.' + $props.goTo.split('/').pop())"
:label="
tMobile('globals.saveAndContinue') +
' ' +
t('globals.' + $props.goTo.split('/').pop())
"
:title="
t('globals.saveAndContinue') +
' ' +
t('globals.' + $props.goTo.split('/').pop())
"
:disable="!hasChanges"
color="primary"
icon="save"

View File

@ -8,10 +8,8 @@ import '@quasar/quasar-ui-qcalendar/src/QCalendarVariables.scss';
import { useWeekdayStore } from 'src/stores/useWeekdayStore';
import useWeekdaysOrder from 'src/composables/getWeekdays';
const formatDate = (dateToFormat, format = 'YYYY-MM-DD') => (
date.formatDate(dateToFormat, format)
);
const formatDate = (dateToFormat, format = 'YYYY-MM-DD') =>
date.formatDate(dateToFormat, format);
const props = defineProps({
year: {
@ -67,7 +65,7 @@ const handleDateClick = (timestamp) => {
emit('onDateSelected', {
date,
isNewMode: !event,
event: event?.[0] || null
event: event?.[0] || null,
});
};
@ -107,7 +105,11 @@ defineExpose({ getEventByTimestamp, handleDateClick });
mini-mode
>
<template #day="{ scope: { timestamp } }">
<slot name="day" :timestamp="timestamp" :getEventAttrs="getEventAttrs">
<slot
name="day"
:timestamp="timestamp"
:getEventAttrs="getEventAttrs"
>
<QBtn
v-if="getEventByTimestamp(timestamp)"
v-bind="{ ...getEventAttrs(timestamp) }"

View File

@ -16,7 +16,7 @@ const props = defineProps({
additionalProps: {
type: Object,
default: () => ({}),
}
},
});
const stateStore = useStateStore();
@ -74,7 +74,7 @@ const date = computed({
const headerTitle = computed(() => {
if (!months.value?.length) return '';
const getMonthName = date =>
const getMonthName = (date) =>
`${weekdayStore.getLocaleMonths[date.getMonth()].locale} ${date.getFullYear()}`;
return `${getMonthName(months.value[0])} - ${getMonthName(months.value[months.value.length - 1])}`;
});
@ -87,7 +87,7 @@ const step = (direction) => {
defineExpose({
firstDay,
lastDay
lastDay,
});
</script>
@ -119,7 +119,7 @@ defineExpose({
:year="month.getFullYear()"
:month-date="month"
v-bind="additionalProps"
@on-date-selected="data => emit('onDateSelected', data)"
@on-date-selected="(data) => emit('onDateSelected', data)"
/>
</div>
</QCard>

View File

@ -398,8 +398,16 @@ defineExpose({
data-cy="saveAndContinueDefaultBtn"
v-if="$props.goTo"
@click="saveAndGo"
:label="tMobile('globals.saveAndContinue') + ' ' + t('globals.' + $props.goTo.split('/').pop())"
:title="t('globals.saveAndContinue') + ' ' + t('globals.' + $props.goTo.split('/').pop())"
:label="
tMobile('globals.saveAndContinue') +
' ' +
t('globals.' + $props.goTo.split('/').pop())
"
:title="
t('globals.saveAndContinue') +
' ' +
t('globals.' + $props.goTo.split('/').pop())
"
:disable="!hasChanges"
color="primary"
icon="save"

View File

@ -26,7 +26,7 @@ async function redirect() {
if (route?.params?.id)
return (window.location.href = await getUrl(
`${section}/${route.params.id}/summary`
`${section}/${route.params.id}/summary`,
));
return (window.location.href = await getUrl(section + '/index'));
}

View File

@ -55,7 +55,7 @@ const refund = async () => {
(data) => (
(rectificativeTypeOptions = data),
(invoiceParams.cplusRectificationTypeFk = data.filter(
(type) => type.description == 'I Por diferencias'
(type) => type.description == 'I Por diferencias',
)[0].id)
)
"
@ -68,7 +68,7 @@ const refund = async () => {
(data) => (
(siiTypeInvoiceOutsOptions = data),
(invoiceParams.siiTypeInvoiceOutFk = data.filter(
(type) => type.code == 'R4'
(type) => type.code == 'R4',
)[0].id)
)
"

View File

@ -52,7 +52,7 @@ watch(
} else filter.value.where = {};
await provincesFetchDataRef.value.fetch({});
emit('onProvinceFetched', provincesOptions.value);
}
},
);
</script>

View File

@ -6,7 +6,7 @@ export default function (initialFooter, data) {
});
return acc;
},
{ ...initialFooter }
{ ...initialFooter },
);
return footer;
}

View File

@ -142,14 +142,14 @@ describe('getRoutes', () => {
const fn = (props) => getRoutes(props, getMethodA, getMethodB);
it('should call getMethodB when source is card', () => {
let props = { source: 'methodB' };
const props = { source: 'methodB' };
fn(props);
expect(getMethodB).toHaveBeenCalled();
expect(getMethodA).not.toHaveBeenCalled();
});
it('should call getMethodA when source is main', () => {
let props = { source: 'methodA' };
const props = { source: 'methodA' };
fn(props);
expect(getMethodA).toHaveBeenCalled();
@ -157,7 +157,7 @@ describe('getRoutes', () => {
});
it('should call getMethodA when source is not exists or undefined', () => {
let props = { source: 'methodC' };
const props = { source: 'methodC' };
expect(() => fn(props)).toThrowError('Method not defined');
expect(getMethodA).not.toHaveBeenCalled();

View File

@ -15,7 +15,7 @@ let root = ref(null);
watchEffect(() => {
matched.value = currentRoute.value.matched.filter(
(matched) => !!matched?.meta?.title || !!matched?.meta?.icon
(matched) => !!matched?.meta?.title || !!matched?.meta?.icon,
);
breadcrumbs.value.length = 0;
if (!matched.value[0]) return;

View File

@ -2,7 +2,7 @@
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
const props = defineProps({
scrollTarget: { type: [String, Object], default: 'window' }
scrollTarget: { type: [String, Object], default: 'window' },
});
const scrollPosition = ref(0);
@ -39,7 +39,7 @@ const updateScrollContainer = (container) => {
};
defineExpose({
updateScrollContainer
updateScrollContainer,
});
const initScrollContainer = async () => {
@ -51,11 +51,10 @@ const initScrollContainer = async () => {
scrollContainer = window;
}
if (!scrollContainer) return
if (!scrollContainer) return;
scrollContainer.addEventListener('scroll', onScroll);
};
onMounted(() => {
initScrollContainer();
});
@ -97,4 +96,3 @@ onUnmounted(() => {
filter: brightness(0.8);
}
</style>

View File

@ -35,7 +35,7 @@ describe('VnSmsDialog', () => {
expect.objectContaining({
message: 'You must enter a new password',
type: 'negative',
})
}),
);
});
@ -47,7 +47,7 @@ describe('VnSmsDialog', () => {
expect.objectContaining({
message: `Passwords don't match`,
type: 'negative',
})
}),
);
});

View File

@ -25,6 +25,9 @@ describe('VnDmsList', () => {
deleteModel: 'WorkerDms',
downloadModel: 'WorkerDms',
},
global: {
stubs: ['VnUserLink'],
},
}).vm;
});

View File

@ -6,8 +6,8 @@ function buildComponent(data) {
return createWrapper(VnLocation, {
global: {
props: {
location: data
}
location: data,
},
},
}).vm;
}
@ -24,7 +24,7 @@ describe('formatLocation', () => {
postcode: '46680',
city: 'Algemesi',
province: { name: 'Valencia' },
country: { name: 'Spain' }
country: { name: 'Spain' },
};
});
@ -47,7 +47,12 @@ describe('formatLocation', () => {
});
it('should return the country', () => {
const location = { ...locationBase, postcode: undefined, city: undefined, province: undefined };
const location = {
...locationBase,
postcode: undefined,
city: undefined,
province: undefined,
};
const vm = buildComponent(location);
expect(vm.formatLocation(location)).toEqual('Spain');
});
@ -61,7 +66,7 @@ describe('showLabel', () => {
code: '46680',
town: 'Algemesi',
province: 'Valencia',
country: 'Spain'
country: 'Spain',
};
});
@ -84,7 +89,12 @@ describe('showLabel', () => {
});
it('should show the label with country', () => {
const location = { ...locationBase, code: undefined, town: undefined, province: undefined };
const location = {
...locationBase,
code: undefined,
town: undefined,
province: undefined,
};
const vm = buildComponent(location);
expect(vm.showLabel(location)).toEqual('Spain');
});

View File

@ -90,7 +90,7 @@ describe('VnLog', () => {
vm = createWrapper(VnLog, {
global: {
stubs: ['FetchData', 'vue-i18n'],
stubs: ['FetchData', 'vue-i18n', 'VnUserLink'],
mocks: {
fetch: vi.fn(),
},

View File

@ -2,13 +2,14 @@ import { createWrapper } from 'app/test/vitest/helper';
import VnSmsDialog from 'components/common/VnSmsDialog.vue';
import { vi, afterEach, beforeAll, describe, expect, it } from 'vitest';
describe('VnSmsDialog', () => {
let vm;
const orderId = 1;
const shipped = new Date();
const phone = '012345678';
const promise = (response) => {return response;};
const promise = (response) => {
return response;
};
const template = 'minAmount';
const locale = 'en';
@ -17,13 +18,13 @@ describe('VnSmsDialog', () => {
propsData: {
data: {
orderId,
shipped
shipped,
},
template,
locale,
phone,
promise
}
promise,
},
}).vm;
});
@ -35,7 +36,9 @@ describe('VnSmsDialog', () => {
it('should update the message value with the correct template and parameters', () => {
vm.updateMessage();
expect(vm.message).toEqual(`A minimum amount of 50€ (VAT excluded) is required for your order ${orderId} of ${shipped} to receive it without additional shipping costs.`);
expect(vm.message).toEqual(
`A minimum amount of 50€ (VAT excluded) is required for your order ${orderId} of ${shipped} to receive it without additional shipping costs.`,
);
});
});
@ -47,7 +50,7 @@ describe('VnSmsDialog', () => {
orderId,
shipped,
destination: phone,
message: vm.message
message: vm.message,
};
await vm.send();

View File

@ -17,7 +17,7 @@ const token = getTokenMultimedia();
const { t } = useI18n();
const src = computed(
() => `/api/Images/user/160x160/${$props.workerId}/download?access_token=${token}`
() => `/api/Images/user/160x160/${$props.workerId}/download?access_token=${token}`,
);
const title = computed(() => $props.title?.toUpperCase() || t('globals.system'));
const showLetter = ref(false);

View File

@ -13,7 +13,7 @@ const src = computed({
get() {
return new URL(
`../../assets/${$props.logo}${Dark.isActive ? '_dark' : ''}.svg`,
import.meta.url
import.meta.url,
).href;
},
});

View File

@ -1,6 +1,6 @@
<script setup>
import axios from 'axios';
import { ref, reactive, useAttrs, computed, onMounted, nextTick, } from 'vue';
import { ref, reactive, useAttrs, computed, onMounted, nextTick } from 'vue';
import { onBeforeRouteLeave, useRouter, useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
@ -34,7 +34,7 @@ const $props = defineProps({
addNote: { type: Boolean, default: false },
selectType: { type: Boolean, default: false },
justInput: { type: Boolean, default: false },
goTo: { type: String, default: '', },
goTo: { type: String, default: '' },
});
const { t } = useI18n();
@ -47,8 +47,8 @@ const newNote = reactive({ text: null, observationTypeFk: null });
const observationTypes = ref([]);
const vnPaginateRef = ref();
const defaultObservationType = computed(() =>
observationTypes.value.find(ot => ot.code === 'salesPerson')?.id
const defaultObservationType = computed(
() => observationTypes.value.find((ot) => ot.code === 'salesPerson')?.id,
);
let savedNote = false;
@ -137,7 +137,6 @@ const handleObservationTypes = (data) => {
}
};
onMounted(() => {
nextTick(() => (componentIsRendered.value = true));
});
@ -150,10 +149,26 @@ async function saveAndGo() {
}
</script>
<template>
<Teleport to="#st-actions" v-if="stateStore?.isSubToolbarShown() && componentIsRendered && $props.goTo && !route.path.includes('summary')">
<Teleport
to="#st-actions"
v-if="
stateStore?.isSubToolbarShown() &&
componentIsRendered &&
$props.goTo &&
!route.path.includes('summary')
"
>
<QBtn
:label="tMobile('globals.saveAndContinue') + ' ' + t('globals.' + $props.goTo.split('/').pop())"
:title="t('globals.saveAndContinue') + ' ' + t('globals.' + $props.goTo.split('/').pop())"
:label="
tMobile('globals.saveAndContinue') +
' ' +
t('globals.' + $props.goTo.split('/').pop())
"
:title="
t('globals.saveAndContinue') +
' ' +
t('globals.' + $props.goTo.split('/').pop())
"
color="primary"
icon="save"
@click="saveAndGo"
@ -234,9 +249,7 @@ async function saveAndGo() {
class="show"
v-bind="$attrs"
:search-url="false"
@on-fetch="
newNote.text = '';
"
@on-fetch="newNote.text = ''"
>
<template #body="{ rows }">
<TransitionGroup name="list" tag="div" class="column items-center full-width">

View File

@ -87,7 +87,7 @@ function formatNumber(number) {
<QItemLabel caption>{{
date.formatDate(
row.sms.created,
'YYYY-MM-DD HH:mm:ss'
'YYYY-MM-DD HH:mm:ss',
)
}}</QItemLabel>
<QItemLabel class="row center">

View File

@ -37,8 +37,7 @@ onBeforeUnmount(() => stateStore.toggleSubToolbar() && hasSubToolbar);
class="justify-end sticky"
>
<slot name="st-data">
<div id="st-data" :class="{ 'full-width': !actionsChildCount() }">
</div>
<div id="st-data" :class="{ 'full-width': !actionsChildCount() }"></div>
</slot>
<QSpace />
<slot name="st-actions">

View File

@ -1,18 +1,38 @@
<script setup>
import AccountDescriptorProxy from 'src/pages/Account/Card/AccountDescriptorProxy.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
defineProps({
import { ref, onMounted } from 'vue';
import axios from 'axios';
const $props = defineProps({
name: { type: String, default: null },
tag: { type: String, default: null },
workerId: { type: Number, default: null },
defaultName: { type: Boolean, default: false },
});
const isWorker = ref(false);
onMounted(async () => {
try {
const {
data: { exists },
} = await axios(`/Workers/${$props.workerId}/exists`);
isWorker.value = exists;
} catch (error) {
if (error.status === 403) return;
throw error;
}
});
</script>
<template>
<slot name="link">
<span :class="{ link: workerId }">
{{ defaultName ? name ?? $t('globals.system') : name }}
{{ defaultName ? (name ?? $t('globals.system')) : name }}
</span>
</slot>
<WorkerDescriptorProxy v-if="workerId" :id="workerId" />
<WorkerDescriptorProxy
v-if="isWorker"
:id="workerId"
@on-fetch="(data) => (isWorker = data?.workerId !== undefined)"
/>
<AccountDescriptorProxy v-else :id="workerId" />
</template>

View File

@ -12,12 +12,12 @@ function generateWrapper(storage = 'images') {
id: 123,
zoomResolution: '400x400',
storage,
}
},
});
wrapper = wrapper.wrapper;
vm = wrapper.vm;
vm.timeStamp = 'timestamp';
};
}
vi.mock('src/composables/useSession', () => ({
useSession: () => ({
@ -31,7 +31,6 @@ vi.mock('src/composables/useRole', () => ({
}),
}));
describe('VnImg', () => {
beforeEach(() => {
isEmployeeMock.mockReset();
@ -63,7 +62,9 @@ describe('VnImg', () => {
generateWrapper();
await vm.$nextTick();
const url = vm.getUrl();
expect(url).toBe('/api/images/catalog/200x200/123/download?access_token=token&timestamp');
expect(url).toBe(
'/api/images/catalog/200x200/123/download?access_token=token&timestamp',
);
});
it('should return /api/{storage}/{collection}/{curResolution}/{id}/download?access_token={token}&{timeStamp} when zoom is true and role is employee and storage is not dms', async () => {
@ -71,7 +72,9 @@ describe('VnImg', () => {
generateWrapper();
await vm.$nextTick();
const url = vm.getUrl(true);
expect(url).toBe('/api/images/catalog/400x400/123/download?access_token=token&timestamp');
expect(url).toBe(
'/api/images/catalog/400x400/123/download?access_token=token&timestamp',
);
});
});

View File

@ -53,26 +53,26 @@ describe('useAcl', () => {
expect(
acl.hasAny([
{ model: 'Worker', props: 'updateAttributes', accessType: 'WRITE' },
])
]),
).toBeFalsy();
});
it('should return false if no roles matched', async () => {
expect(
acl.hasAny([{ model: 'Worker', props: 'holidays', accessType: 'READ' }])
acl.hasAny([{ model: 'Worker', props: 'holidays', accessType: 'READ' }]),
).toBeTruthy();
});
describe('*', () => {
it('should return true if an acl matched', async () => {
expect(
acl.hasAny([{ model: 'Address', props: '*', accessType: 'WRITE' }])
acl.hasAny([{ model: 'Address', props: '*', accessType: 'WRITE' }]),
).toBeTruthy();
});
it('should return false if no acls matched', async () => {
expect(
acl.hasAny([{ model: 'Worker', props: '*', accessType: 'READ' }])
acl.hasAny([{ model: 'Worker', props: '*', accessType: 'READ' }]),
).toBeFalsy();
});
});
@ -80,13 +80,15 @@ describe('useAcl', () => {
describe('$authenticated', () => {
it('should return false if no acls matched', async () => {
expect(
acl.hasAny([{ model: 'Url', props: 'getByUser', accessType: '*' }])
acl.hasAny([{ model: 'Url', props: 'getByUser', accessType: '*' }]),
).toBeFalsy();
});
it('should return true if an acl matched', async () => {
expect(
acl.hasAny([{ model: 'Url', props: 'getByUser', accessType: 'READ' }])
acl.hasAny([
{ model: 'Url', props: 'getByUser', accessType: 'READ' },
]),
).toBeTruthy();
});
});
@ -96,7 +98,7 @@ describe('useAcl', () => {
expect(
acl.hasAny([
{ model: 'TpvTransaction', props: 'start', accessType: 'READ' },
])
]),
).toBeFalsy();
});
@ -104,7 +106,7 @@ describe('useAcl', () => {
expect(
acl.hasAny([
{ model: 'TpvTransaction', props: 'start', accessType: 'WRITE' },
])
]),
).toBeTruthy();
});
});

View File

@ -18,7 +18,7 @@ export async function downloadFile(id, model = 'dms', urlPath = '/downloadFile',
export async function downloadDocuware(url, params) {
const appUrl = await getAppUrl();
const response = await axios.get(`${appUrl}/api/` + url, {
const response = await axios.get(`${appUrl}/api/${url}`, {
responseType: 'blob',
params,
});

View File

@ -20,5 +20,5 @@ export function getColAlign(col) {
if (/^is[A-Z]/.test(col.name) || /^has[A-Z]/.test(col.name)) align = 'center';
return 'text-' + (align ?? 'center');
return `text-${align ?? 'center'}`;
}

View File

@ -1,10 +1,10 @@
export function getDateQBadgeColor(date) {
let today = Date.vnNew();
const today = Date.vnNew();
today.setHours(0, 0, 0, 0);
let timeTicket = new Date(date);
const timeTicket = new Date(date);
timeTicket.setHours(0, 0, 0, 0);
let comparation = today - timeTicket;
const comparation = today - timeTicket;
if (comparation == 0) return 'warning';
if (comparation < 0) return 'success';

View File

@ -2,9 +2,8 @@ import { ref } from 'vue';
import moment from 'moment';
export default function useWeekdaysOrder() {
const firstDay = moment().weekday(1).day();
const weekdays = [...Array(7).keys()].map(i => (i + firstDay) % 7);
const weekdays = [...Array(7).keys()].map((i) => (i + firstDay) % 7);
return ref(weekdays);
}

View File

@ -7,7 +7,7 @@ export async function beforeSave(data, getChanges, modelOrigin) {
const patchPromises = [];
for (const change of changes) {
let patchData = {};
const patchData = {};
if ('hasMinPrice' in change.data) {
patchData.hasMinPrice = change.data?.hasMinPrice;

View File

@ -3,5 +3,4 @@ import { useQuasar } from 'quasar';
export default function () {
const quasar = useQuasar();
return quasar.screen.gt.xs ? 'q-pa-md' : 'q-pa-xs';
}

View File

@ -6,7 +6,7 @@ export function djb2a(string) {
}
export function useColor(value) {
return '#' + colors[djb2a(value || '') % colors.length];
return `#${colors[djb2a(value || '') % colors.length]}`;
}
const colors = [

View File

@ -15,18 +15,16 @@ export function usePrintService() {
message: t('globals.notificationSent'),
type: 'positive',
icon: 'check',
})
}),
);
}
function openReport(path, params, isNewTab = '_self') {
if (typeof params === 'string') params = JSON.parse(params);
params = Object.assign(
{
params = {
access_token: getTokenMultimedia(),
},
params
);
...params,
};
const query = new URLSearchParams(params).toString();
window.open(`api/${path}?${query}`, isNewTab);

View File

@ -17,7 +17,7 @@ export function useSession() {
let intervalId = null;
function setSession(data) {
let keepLogin = data.keepLogin;
const keepLogin = data.keepLogin;
const storage = keepLogin ? localStorage : sessionStorage;
storage.setItem(TOKEN, data.token);
storage.setItem(TOKEN_MULTIMEDIA, data.tokenMultimedia);

View File

@ -8,7 +8,7 @@ export function useVnConfirm() {
message,
promise,
successFn,
customHTML = {}
customHTML = {},
) => {
const { component, props } = customHTML;
Dialog.create({
@ -19,7 +19,7 @@ export function useVnConfirm() {
message: message,
promise: promise,
},
{ customHTML: () => h(component, props) }
{ customHTML: () => h(component, props) },
),
}).onOk(async () => {
if (successFn) successFn();

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,8 @@
@font-face {
font-family: 'icon';
src: url('fonts/icon.eot?uocffs');
src: url('fonts/icon.eot?uocffs#iefix') format('embedded-opentype'),
src:
url('fonts/icon.eot?uocffs#iefix') format('embedded-opentype'),
url('fonts/icon.ttf?uocffs') format('truetype'),
url('fonts/icon.woff?uocffs') format('woff'),
url('fonts/icon.svg?uocffs#icon') format('svg');
@ -10,7 +11,8 @@
font-display: block;
}
[class^="icon-"], [class*=" icon-"] {
[class^='icon-'],
[class*=' icon-'] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'icon' !important;
speak: never;
@ -26,428 +28,428 @@
}
.icon-inactive-car:before {
content: "\e978";
content: '\e978';
}
.icon-hasItemLost:before {
content: "\e957";
content: '\e957';
}
.icon-hasItemDelay:before {
content: "\e96d";
content: '\e96d';
}
.icon-add_entries:before {
content: "\e953";
content: '\e953';
}
.icon-100:before {
content: "\e901";
content: '\e901';
}
.icon-Client_unpaid:before {
content: "\e98c";
content: '\e98c';
}
.icon-History:before {
content: "\e902";
content: '\e902';
}
.icon-Person:before {
content: "\e903";
content: '\e903';
}
.icon-accessory:before {
content: "\e904";
content: '\e904';
}
.icon-account:before {
content: "\e905";
content: '\e905';
}
.icon-actions:before {
content: "\e907";
content: '\e907';
}
.icon-addperson:before {
content: "\e908";
content: '\e908';
}
.icon-agencia_tributaria:before {
content: "\e948";
content: '\e948';
}
.icon-agency:before {
content: "\e92a";
content: '\e92a';
}
.icon-agency-term:before {
content: "\e909";
content: '\e909';
}
.icon-albaran:before {
content: "\e92c";
content: '\e92c';
}
.icon-anonymous:before {
content: "\e90b";
content: '\e90b';
}
.icon-apps:before {
content: "\e90c";
content: '\e90c';
}
.icon-artificial:before {
content: "\e90d";
content: '\e90d';
}
.icon-attach:before {
content: "\e90e";
content: '\e90e';
}
.icon-barcode:before {
content: "\e90f";
content: '\e90f';
}
.icon-basket:before {
content: "\e910";
content: '\e910';
}
.icon-basketadd:before {
content: "\e911";
content: '\e911';
}
.icon-bin:before {
content: "\e913";
content: '\e913';
}
.icon-botanical:before {
content: "\e914";
content: '\e914';
}
.icon-bucket:before {
content: "\e915";
content: '\e915';
}
.icon-buscaman:before {
content: "\e916";
content: '\e916';
}
.icon-buyrequest:before {
content: "\e917";
content: '\e917';
}
.icon-calc_volum .path1:before {
content: "\e918";
content: '\e918';
color: rgb(0, 0, 0);
}
.icon-calc_volum .path2:before {
content: "\e919";
content: '\e919';
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-calc_volum .path3:before {
content: "\e91c";
content: '\e91c';
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-calc_volum .path4:before {
content: "\e91d";
content: '\e91d';
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-calc_volum .path5:before {
content: "\e91e";
content: '\e91e';
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-calc_volum .path6:before {
content: "\e91f";
content: '\e91f';
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-calendar:before {
content: "\e920";
content: '\e920';
}
.icon-catalog:before {
content: "\e921";
content: '\e921';
}
.icon-claims:before {
content: "\e922";
content: '\e922';
}
.icon-client:before {
content: "\e923";
content: '\e923';
}
.icon-clone:before {
content: "\e924";
content: '\e924';
}
.icon-columnadd:before {
content: "\e925";
content: '\e925';
}
.icon-columndelete:before {
content: "\e926";
content: '\e926';
}
.icon-components:before {
content: "\e927";
content: '\e927';
}
.icon-consignatarios:before {
content: "\e928";
content: '\e928';
}
.icon-control:before {
content: "\e929";
content: '\e929';
}
.icon-credit:before {
content: "\e92b";
content: '\e92b';
}
.icon-defaulter:before {
content: "\e92d";
content: '\e92d';
}
.icon-deletedTicket:before {
content: "\e92e";
content: '\e92e';
}
.icon-deleteline:before {
content: "\e92f";
content: '\e92f';
}
.icon-delivery:before {
content: "\e930";
content: '\e930';
}
.icon-deliveryprices:before {
content: "\e932";
content: '\e932';
}
.icon-details:before {
content: "\e933";
content: '\e933';
}
.icon-dfiscales:before {
content: "\e934";
content: '\e934';
}
.icon-disabled:before {
content: "\e935";
content: '\e935';
}
.icon-doc:before {
content: "\e936";
content: '\e936';
}
.icon-entry:before {
content: "\e937";
content: '\e937';
}
.icon-entry_lastbuys:before {
content: "\e91a";
content: '\e91a';
}
.icon-exit:before {
content: "\e938";
content: '\e938';
}
.icon-eye:before {
content: "\e939";
content: '\e939';
}
.icon-fixedPrice:before {
content: "\e93a";
content: '\e93a';
}
.icon-flower:before {
content: "\e93b";
content: '\e93b';
}
.icon-frozen:before {
content: "\e93c";
content: '\e93c';
}
.icon-fruit:before {
content: "\e93d";
content: '\e93d';
}
.icon-funeral:before {
content: "\e93e";
content: '\e93e';
}
.icon-grafana:before {
content: "\e906";
content: '\e906';
}
.icon-greenery:before {
content: "\e93f";
content: '\e93f';
}
.icon-greuge:before {
content: "\e940";
content: '\e940';
}
.icon-grid:before {
content: "\e941";
content: '\e941';
}
.icon-handmade:before {
content: "\e942";
content: '\e942';
}
.icon-handmadeArtificial:before {
content: "\e943";
content: '\e943';
}
.icon-headercol:before {
content: "\e945";
content: '\e945';
}
.icon-info:before {
content: "\e946";
content: '\e946';
}
.icon-inventory:before {
content: "\e947";
content: '\e947';
}
.icon-invoice:before {
content: "\e968";
content: '\e968';
color: #5f5f5f;
}
.icon-invoice-in:before {
content: "\e949";
content: '\e949';
}
.icon-invoice-in-create:before {
content: "\e94a";
content: '\e94a';
}
.icon-invoice-out:before {
content: "\e94b";
content: '\e94b';
}
.icon-isTooLittle:before {
content: "\e94c";
content: '\e94c';
}
.icon-item:before {
content: "\e94d";
content: '\e94d';
}
.icon-languaje:before {
content: "\e970";
content: '\e970';
}
.icon-lines:before {
content: "\e94e";
content: '\e94e';
}
.icon-linesprepaired:before {
content: "\e94f";
content: '\e94f';
}
.icon-link-to-corrected:before {
content: "\e931";
content: '\e931';
}
.icon-link-to-correcting:before {
content: "\e944";
content: '\e944';
}
.icon-logout:before {
content: "\e973";
content: '\e973';
}
.icon-mana:before {
content: "\e950";
content: '\e950';
}
.icon-mandatory:before {
content: "\e951";
content: '\e951';
}
.icon-net:before {
content: "\e952";
content: '\e952';
}
.icon-newalbaran:before {
content: "\e954";
content: '\e954';
}
.icon-niche:before {
content: "\e955";
content: '\e955';
}
.icon-no036:before {
content: "\e956";
content: '\e956';
}
.icon-noPayMethod:before {
content: "\e958";
content: '\e958';
}
.icon-notes:before {
content: "\e959";
content: '\e959';
}
.icon-noweb:before {
content: "\e95a";
content: '\e95a';
}
.icon-onlinepayment:before {
content: "\e95b";
content: '\e95b';
}
.icon-package:before {
content: "\e95c";
content: '\e95c';
}
.icon-payment:before {
content: "\e95d";
content: '\e95d';
}
.icon-pbx:before {
content: "\e95e";
content: '\e95e';
}
.icon-pets:before {
content: "\e95f";
content: '\e95f';
}
.icon-photo:before {
content: "\e960";
content: '\e960';
}
.icon-plant:before {
content: "\e961";
content: '\e961';
}
.icon-polizon:before {
content: "\e962";
content: '\e962';
}
.icon-preserved:before {
content: "\e963";
content: '\e963';
}
.icon-recovery:before {
content: "\e964";
content: '\e964';
}
.icon-regentry:before {
content: "\e965";
content: '\e965';
}
.icon-reserva:before {
content: "\e966";
content: '\e966';
}
.icon-revision:before {
content: "\e967";
content: '\e967';
}
.icon-risk:before {
content: "\e969";
content: '\e969';
}
.icon-saysimple:before {
content: "\e912";
content: '\e912';
}
.icon-services:before {
content: "\e96a";
content: '\e96a';
}
.icon-settings:before {
content: "\e96b";
content: '\e96b';
}
.icon-shipment:before {
content: "\e96c";
content: '\e96c';
}
.icon-sign:before {
content: "\e90a";
content: '\e90a';
}
.icon-sms:before {
content: "\e96e";
content: '\e96e';
}
.icon-solclaim:before {
content: "\e96f";
content: '\e96f';
}
.icon-solunion:before {
content: "\e971";
content: '\e971';
}
.icon-splitline:before {
content: "\e972";
content: '\e972';
}
.icon-splur:before {
content: "\e974";
content: '\e974';
}
.icon-stowaway:before {
content: "\e975";
content: '\e975';
}
.icon-supplier:before {
content: "\e976";
content: '\e976';
}
.icon-supplierfalse:before {
content: "\e977";
content: '\e977';
}
.icon-tags:before {
content: "\e979";
content: '\e979';
}
.icon-tax:before {
content: "\e97a";
content: '\e97a';
}
.icon-thermometer:before {
content: "\e97b";
content: '\e97b';
}
.icon-ticket:before {
content: "\e97c";
content: '\e97c';
}
.icon-ticketAdd:before {
content: "\e97e";
content: '\e97e';
}
.icon-traceability:before {
content: "\e97f";
content: '\e97f';
}
.icon-transaction:before {
content: "\e91b";
content: '\e91b';
}
.icon-treatments:before {
content: "\e980";
content: '\e980';
}
.icon-trolley:before {
content: "\e900";
content: '\e900';
}
.icon-troncales:before {
content: "\e982";
content: '\e982';
}
.icon-unavailable:before {
content: "\e983";
content: '\e983';
}
.icon-visible_columns:before {
content: "\e984";
content: '\e984';
}
.icon-volume:before {
content: "\e985";
content: '\e985';
}
.icon-wand:before {
content: "\e986";
content: '\e986';
}
.icon-web:before {
content: "\e987";
content: '\e987';
}
.icon-wiki:before {
content: "\e989";
content: '\e989';
}
.icon-worker:before {
content: "\e98a";
content: '\e98a';
}
.icon-zone:before {
content: "\e98b";
content: '\e98b';
}

View File

@ -30,10 +30,12 @@ export function isValidDate(date) {
export function toDateFormat(date, locale = 'es-ES', opts = {}) {
if (!isValidDate(date)) return '';
const format = Object.assign(
{ year: 'numeric', month: '2-digit', day: '2-digit' },
opts
);
const format = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
...opts,
};
return new Date(date).toLocaleDateString(locale, format);
}
@ -104,17 +106,17 @@ export function secondsToHoursMinutes(seconds, includeHSuffix = true) {
const hours = Math.floor(seconds / 3600);
const remainingMinutes = seconds % 3600;
const minutes = Math.floor(remainingMinutes / 60);
const formattedHours = hours < 10 ? '0' + hours : hours;
const formattedMinutes = minutes < 10 ? '0' + minutes : minutes;
const formattedHours = hours < 10 ? `0${hours}` : hours;
const formattedMinutes = minutes < 10 ? `0${minutes}` : minutes;
// Append "h." if includeHSuffix is true
const suffix = includeHSuffix ? ' h.' : '';
// Return formatted string
return formattedHours + ':' + formattedMinutes + suffix;
return `${formattedHours}:${formattedMinutes}${suffix}`;
}
export function getTimeDifferenceWithToday(date) {
let today = Date.vnNew();
const today = Date.vnNew();
today.setHours(0, 0, 0, 0);
date = new Date(date);

View File

@ -5,12 +5,12 @@
* @return {Object} The fields as object
*/
function fieldsToObject(fields) {
let fieldsObj = {};
const fieldsObj = {};
if (Array.isArray(fields)) {
for (let field of fields) fieldsObj[field] = true;
for (const field of fields) fieldsObj[field] = true;
} else if (typeof fields == 'object') {
for (let field in fields) {
for (const field in fields) {
if (fields[field]) fieldsObj[field] = true;
}
}
@ -26,7 +26,7 @@ function fieldsToObject(fields) {
* @return {Array} The merged fields as an array
*/
function mergeFields(src, dst) {
let fields = {};
const fields = {};
Object.assign(fields, fieldsToObject(src), fieldsToObject(dst));
return Object.keys(fields);
}
@ -39,7 +39,7 @@ function mergeFields(src, dst) {
* @return {Array} The merged wheres
*/
function mergeWhere(src, dst) {
let and = [];
const and = [];
if (src) and.push(src);
if (dst) and.push(dst);
return simplifyOperation(and, 'and');
@ -53,7 +53,7 @@ function mergeWhere(src, dst) {
* @return {Object} The result filter
*/
function mergeFilters(src, dst) {
let res = Object.assign({}, dst);
const res = { ...dst };
if (!src) return res;
@ -80,12 +80,12 @@ function simplifyOperation(operation, operator) {
}
function buildFilter(params, builderFunc) {
let and = [];
const and = [];
for (let param in params) {
let value = params[param];
for (const param in params) {
const value = params[param];
if (value == null) continue;
let expr = builderFunc(param, value);
const expr = builderFunc(param, value);
if (expr) and.push(expr);
}
return simplifyOperation(and, 'and');

View File

@ -1,10 +1,10 @@
export default function toDateString(date) {
let day = date.getDate();
let month = date.getMonth() + 1;
let year = date.getFullYear();
const year = date.getFullYear();
if (day < 10) day = `0${day}`;
if (month < 10) month = `0${month}`;
return `${year}-${month}-${day}`
return `${year}-${month}-${day}`;
}

View File

@ -1,5 +1,5 @@
export default function toLowerCamel(value) {
if (!value) return;
if (typeof (value) !== 'string') return value;
if (typeof value !== 'string') return value;
return value.charAt(0).toLowerCase() + value.slice(1);
}

View File

@ -9,7 +9,7 @@ export default function formatDate(dateVal) {
const dateZeroTime = new Date(dateVal);
dateZeroTime.setHours(0, 0, 0, 0);
const diff = Math.trunc(
(today.getTime() - dateZeroTime.getTime()) / (1000 * 3600 * 24)
(today.getTime() - dateZeroTime.getTime()) / (1000 * 3600 * 24),
);
let format;
if (diff === 0) format = t('globals.today');

View File

@ -11,12 +11,12 @@ for (const file in files) {
translations[lang] = g.default;
})
.finally(() => {
const actualLang = lang + '.yml';
const actualLang = `${lang}.yml`;
for (const module in modules) {
if (!module.endsWith(actualLang)) continue;
modules[module]().then((t) => {
Object.assign(translations[lang], t.default);
})
});
}
});
}

View File

@ -80,7 +80,7 @@ const killSession = async ({ userId, created }) => {
openConfirmationModal(
t('Session will be killed'),
t('Are you sure you want to continue?'),
() => killSession(row)
() => killSession(row),
)
"
outline

View File

@ -57,7 +57,7 @@ watch(
store.url = urlPath.value;
store.filter = filter;
fetchAliases();
}
},
);
const fetchAliases = () => paginateRef.value.fetch();
@ -91,7 +91,7 @@ const fetchAliases = () => paginateRef.value.fetch();
openConfirmationModal(
t('User will be removed from alias'),
t('Are you sure you want to continue?'),
() => deleteAlias(row)
() => deleteAlias(row),
)
"
>

View File

@ -28,7 +28,7 @@ const loading = ref(false);
const hasDataChanged = computed(
() =>
formData.value.forwardTo !== initialData.value.forwardTo ||
initialData.value.hasData !== hasData.value
initialData.value.hasData !== hasData.value,
);
const fetchMailForwards = async () => {
@ -77,7 +77,7 @@ const setInitialData = async () => {
watch(
() => route.params.id,
() => setInitialData()
() => setInitialData(),
);
onMounted(async () => await setInitialData());

View File

@ -14,7 +14,7 @@ const rolesOptions = ref([]);
const formModelRef = ref();
watch(
() => route.params.id,
() => formModelRef.value.reset()
() => formModelRef.value.reset(),
);
</script>
<template>

View File

@ -44,7 +44,7 @@ watch(
store.filter = filter.value;
store.limit = 0;
fetchSubRoles();
}
},
);
const fetchSubRoles = () => paginateRef.value.fetch();

View File

@ -43,7 +43,7 @@ watch(
store.url = urlPath.value;
store.filter = filter.value;
fetchSubRoles();
}
},
);
const fetchSubRoles = () => paginateRef.value.fetch();

View File

@ -238,7 +238,9 @@ const columns = computed(() => [
<style lang="scss" scoped>
.grid-style-transition {
transition: transform 0.28s, background-color 0.28s;
transition:
transform 0.28s,
background-color 0.28s;
}
</style>

View File

@ -79,7 +79,7 @@ const columns = computed(() => [
field: ({ sale }) => sale.quantity,
sortable: true,
style: 'padding-right: 2%;',
headerStyle: 'padding-right: 2%;'
headerStyle: 'padding-right: 2%;',
},
{
name: 'claimed',
@ -113,7 +113,7 @@ const columns = computed(() => [
format: (value) => toCurrency(value),
sortable: true,
style: 'padding-right: 2%;',
headerStyle: 'padding-right: 2%;'
headerStyle: 'padding-right: 2%;',
},
]);
@ -160,7 +160,7 @@ function fillClaimedQuantities() {
const formData = claimLinesForm.value.formData;
let hasChanges = false;
const selectedRows = formData.filter(row => selected.value.includes(row));
const selectedRows = formData.filter((row) => selected.value.includes(row));
for (const row of selectedRows) {
if (row.quantity === 0 || row.quantity === null) {
@ -181,8 +181,6 @@ function fillClaimedQuantities() {
});
}
}
</script>
<template>
<Teleport to="#st-data" v-if="stateStore.isSubToolbarShown()">
@ -210,7 +208,6 @@ function fillClaimedQuantities() {
auto-load
/>
<div class="q-pa-md">
<CrudModel
data-key="claimLines"
ref="claimLinesForm"
@ -236,12 +233,7 @@ function fillClaimedQuantities() {
>
<template #body-cell-claimed="{ row }">
<QTd auto-width align="right" class="text-primary shrink">
<QInput
v-model.number="row.quantity"
type="number"
dense
/>
<QInput v-model.number="row.quantity" type="number" dense />
</QTd>
</template>
<template #body-cell-description="{ row, value }">
@ -297,7 +289,6 @@ function fillClaimedQuantities() {
type="number"
dense
autofocus
/>
</QItemLabel>
</template>

View File

@ -27,7 +27,7 @@ describe('ClaimDescriptorMenu', () => {
await vm.remove();
expect(vm.quasar.notify).toHaveBeenCalledWith(
expect.objectContaining({ type: 'positive' })
expect.objectContaining({ type: 'positive' }),
);
});
});

View File

@ -17,6 +17,7 @@ import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.v
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import VnSelect from 'components/common/VnSelect.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
const arrayData = useArrayData('Customer');
const { t } = useI18n();
@ -50,7 +51,7 @@ const columns = computed(() => [
label: t('globals.ticket'),
cardVisible: true,
columnFilter: {
inWhere: true,
name: 'ticketId',
},
},
{
@ -84,7 +85,8 @@ const columns = computed(() => [
label: t('globals.description'),
columnClass: 'expand',
columnFilter: {
inWhere: true,
name: 'description',
},
},
{
@ -92,17 +94,10 @@ const columns = computed(() => [
label: t('globals.quantity'),
cardVisible: true,
visible: true,
columnFilter: {
inWhere: true,
},
},
{
name: 'grouped',
label: t('Group by items'),
component: 'checkbox',
visible: false,
orderBy: false,
columnFilter: false
},
]);
onBeforeMount(async () => {
@ -218,9 +213,9 @@ const updateDateParams = (value, params) => {
<div v-if="row.subName" class="subName">
{{ row.subName }}
</div>
<FetchedTags :item="row" />
<FetchedTags :item="row" :columns="6"/>
</template>
<template #moreFilterPanel="{ params }">
<template #moreFilterPanel="{ params, searchFn}">
<div class="column no-wrap flex-center q-gutter-y-md q-mt-xs q-pr-xl">
<VnSelect
:filled="true"
@ -290,6 +285,13 @@ const updateDateParams = (value, params) => {
class="q-px-xs q-pt-none fit"
dense
/>
<VnCheckbox
v-model="params.grouped"
:label="t('Group by items')"
class="q-px-xs q-pt-none fit"
dense
@update:modelValue="() => searchFn()"
/>
</div>
</template>
</VnTable>

View File

@ -109,8 +109,6 @@ async function acceptPropagate({ isEqualizated }) {
option-value="id"
v-model="data.sageTaxTypeFk"
data-cy="sageTaxTypeFk"
:required="data.isTaxDataChecked"
:rules="[(val) => validations.required(data.isTaxDataChecked, val)]"
/>
<VnSelect
:label="t('Sage transaction type')"
@ -120,10 +118,6 @@ async function acceptPropagate({ isEqualizated }) {
option-value="id"
data-cy="sageTransactionTypeFk"
v-model="data.sageTransactionTypeFk"
:required="data.isTaxDataChecked"
:rules="[
(val) => validations.required(data.sageTransactionTypeFk, val),
]"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">

View File

@ -50,8 +50,11 @@ const filterClientFindOne = {
>
<template #form="{ data }">
<VnRow>
<QCheckbox :label="t('Unpaid client')" v-model="data.unpaid"
data-cy="UnpaidCheckBox" />
<QCheckbox
:label="t('Unpaid client')"
v-model="data.unpaid"
data-cy="UnpaidCheckBox"
/>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md" v-show="data.unpaid">

View File

@ -224,7 +224,7 @@ const toCustomerFileManagement = () => {
<QTooltip max-width="30rem">
{{
`${t(
'Allowed content types'
'Allowed content types',
)}: ${allowedContentTypes.join(', ')}`
}}
</QTooltip>

View File

@ -200,7 +200,7 @@ const toCustomerFileManagement = () => {
<QTooltip max-width="30rem">
{{
`${t(
'Allowed content types'
'Allowed content types',
)}: ${allowedContentTypes.join(', ')}`
}}
</QTooltip>

View File

@ -130,20 +130,22 @@ async function onDataSaved(formData, { id }) {
}
}
async function getSupplierClientReferences(value) {
if (!value) return (initialData.description = '');
const params = { bankAccount: value };
const { data } = await axios(`Clients/getClientOrSupplierReference`, { params });
if (!data.clientId) {
initialData.description = t('Supplier Compensation Reference', {
supplierId: data.supplierId,
supplierName: data.supplierName,
async function getSupplierClientReferences(data) {
if (!data) return (initialData.description = '');
const params = { bankAccount: data.compensationAccount };
const { data: reference } = await axios(`Clients/getClientOrSupplierReference`, {
params,
});
if (reference.supplierId) {
data.description = t('Supplier Compensation Reference', {
supplierId: reference.supplierId,
supplierName: reference.supplierName,
});
return;
}
initialData.description = t('Client Compensation Reference', {
clientId: data.clientId,
clientName: data.clientName,
data.description = t('Client Compensation Reference', {
clientId: reference.clientId,
clientName: reference.clientName,
});
}
@ -222,6 +224,7 @@ async function getAmountPaid() {
clearable
v-model.number="data.amountPaid"
data-cy="paymentAmount"
:positive="false"
/>
</VnRow>
<VnRow>
@ -251,7 +254,7 @@ async function getAmountPaid() {
:label="t('Compensation account')"
clearable
v-model="data.compensationAccount"
@blur="getSupplierClientReferences(data.compensationAccount)"
@blur="getSupplierClientReferences(data)"
/>
</VnRow>
</div>
@ -287,6 +290,9 @@ async function getAmountPaid() {
</template>
<i18n>
en:
Supplier Compensation Reference: ({supplierId}) Ntro Proveedor {supplierName}
Client Compensation Reference: ({clientId}) Ntro Cliente {clientName}
es:
New payment: Añadir pago
Date: Fecha

View File

@ -13,4 +13,4 @@ export async function getClient(clientId, _filter = {}) {
};
const params = { filter: JSON.stringify(filter) };
return await axios.get('Clients', { params });
};
}

View File

@ -123,3 +123,4 @@ customer:
ticketFk: Ticket Id
description: Description
quantity: Quantity
ticketId: Ticket

View File

@ -123,3 +123,4 @@ customer:
ticketFk: Id Ticket
description: Descripción
quantity: Cantidad
ticketId: Ticket

View File

@ -126,7 +126,7 @@ const fetchBuys = async (buys) => {
const params = { buys };
const { data } = await axios.post(
`Entries/${route.params.id}/importBuysPreview`,
params
params,
);
importData.value.buys = data;
};

View File

@ -3,7 +3,7 @@ import axios from 'axios';
export async function setRectificative(route) {
const card = route.matched.find((route) => route.name === 'InvoiceInCard');
const corrective = card.children.find(
(route) => route.name === 'InvoiceInCorrective'
(route) => route.name === 'InvoiceInCorrective',
);
corrective.meta.hidden = !(

View File

@ -37,7 +37,7 @@ async function onSubmit() {
await axios.post(
'VnUsers/reset-password',
{ newPassword: newPassword.value },
{ headers }
{ headers },
);
router.push('Login');
quasar.notify({

View File

@ -71,9 +71,7 @@ onMounted(async () => (stateStore.rightDrawer = false));
auto-load
/>
<QCard v-if="volumeSummary" class="order-volume-summary q-pa-lg">
<VnLv
:label="`${t('total')}: `"
:value="`${volumeSummary?.totalVolume} m³`" />
<VnLv :label="`${t('total')}: `" :value="`${volumeSummary?.totalVolume} m³`" />
<VnLv
:label="`${t('boxes')}: `"
:value="`${dashIfEmpty(volumeSummary?.totalBoxes)} U`"

View File

@ -3,5 +3,10 @@ import AgencyDescriptor from 'pages/Route/Agency/Card/AgencyDescriptor.vue';
import VnCard from 'src/components/common/VnCard.vue';
</script>
<template>
<VnCard data-key="Agency" url="Agencies" :descriptor="AgencyDescriptor" :filter="{ where: { id: $route.params.id } }" />
<VnCard
data-key="Agency"
url="Agencies"
:descriptor="AgencyDescriptor"
:filter="{ where: { id: $route.params.id } }"
/>
</template>

View File

@ -9,7 +9,7 @@ export async function getAgencies(formData, client, _filter = {}) {
};
let agency = null;
let params = {
const params = {
filter: JSON.stringify(filter),
warehouseFk: formData.warehouseId,
addressFk: formData.addressId,

View File

@ -23,7 +23,7 @@ async function openRouteReport() {
const token = getTokenMultimedia();
window.open(
`${url}/api/Routes/${routeId}/driver-route-pdf?access_token=${token}`,
'_blank'
'_blank',
);
}

View File

@ -106,8 +106,8 @@ const setTicketsRoute = async () => {
(selectedRows.value || [])
.filter((ticket) => ticket?.id)
.map((ticket) =>
axios.patch(`Routes/${$props.id}/insertTicket`, { ticketId: ticket.id })
)
axios.patch(`Routes/${$props.id}/insertTicket`, { ticketId: ticket.id }),
),
);
await axios.post(`Routes/${$props.id}/updateVolume`);
emit('ok');

View File

@ -72,13 +72,9 @@ const createVehicleEvent = async () => {
if (isNew.value) {
await axios.post(`VehicleEvents`, vehicleFormData.value);
} else {
await axios.patch(
`VehicleEvents/${props.event?.id}`,
vehicleFormData.value,
);
await axios.patch(`VehicleEvents/${props.event?.id}`, vehicleFormData.value);
}
await refetchEvents();
};
const deleteVehicleEvent = async () => {
@ -98,26 +94,24 @@ const refetchEvents = async () => {
{
or: [
{ started: { lte: props.lastDay?.toISOString() } },
{ started: null }
]
{ started: null },
],
},
{
or: [
{ finished: { gte: props.firstDay?.toISOString() } },
{ finished: null }
]
}
]
}
}
}
{ finished: null },
],
},
],
},
},
},
});
emit('refresh-events');
notify(t('globals.dataSaved'), 'positive');
emit('closeForm');
};
</script>
<template>

View File

@ -38,7 +38,6 @@ const onVehicleEventFormClose = () => {
showVehicleEventForm.value = false;
vehicleEventsFormProps.value = {};
};
</script>
<template>

View File

@ -63,18 +63,22 @@ const fetchData = async () => {
where: {
vehicleFk: route.params.id,
and: [
{ or: [
{
or: [
{ started: { lte: props.lastDay } },
{ started: null }
]},
{ or: [
{ started: null },
],
},
{
or: [
{ finished: { gte: props.firstDay } },
{ finished: null }
]}
]
}
}
}
{ finished: null },
],
},
],
},
},
},
});
emit('update:events', arrayData.store.data || []);
} catch (error) {
@ -95,7 +99,7 @@ watch(
(newEvents) => {
emit('update:events', newEvents);
},
{ deep: true }
{ deep: true },
);
const deleteEvent = async (id) => {
@ -119,9 +123,8 @@ onMounted(async () => {
});
defineExpose({
fetchData
fetchData,
});
</script>
<template>

View File

@ -2,12 +2,8 @@
import EntityCalendar from 'src/components/EntityCalendar.vue';
const emit = defineEmits(['onDateSelected']);
</script>
<template>
<EntityCalendar
v-bind="$props"
@onDateSelected="(e) => emit('onDateSelected', e)"
/>
<EntityCalendar v-bind="$props" @onDateSelected="(e) => emit('onDateSelected', e)" />
</template>

View File

@ -36,8 +36,8 @@ const refreshEvents = () => {
const eventStart = event.started ? new Date(event.started).getTime() : null;
const eventEnd = event.finished ? new Date(event.finished).getTime() : null;
let match = (!eventStart || stamp >= eventStart) &&
(!eventEnd || stamp <= eventEnd);
let match =
(!eventStart || stamp >= eventStart) && (!eventEnd || stamp <= eventEnd);
if (match) {
dayEvents.push(event);
@ -75,14 +75,19 @@ watch(
{ immediate: true },
);
watch(() => entityCalendarRef.value?.firstDay, (newVal) => {
watch(
() => entityCalendarRef.value?.firstDay,
(newVal) => {
if (newVal) firstDay.value = new Date(newVal);
});
},
);
watch(() => entityCalendarRef.value?.lastDay, (newVal) => {
watch(
() => entityCalendarRef.value?.lastDay,
(newVal) => {
if (newVal) lastDay.value = new Date(newVal);
});
},
);
</script>
<template>

View File

@ -76,7 +76,7 @@ const getUrl = (section) => `#/supplier/${entityId.value}/${section}`;
{{
dashIfEmpty(
supplier.companySize &&
t('globals.' + supplier.companySize)
t('globals.' + supplier.companySize),
)
}}
</span>

View File

@ -38,7 +38,7 @@ watch(
if (ticketData.value?.zone && ticketData.value?.zone?.isVolumetric)
getTicketVolume();
},
{ immediate: true }
{ immediate: true },
);
const salesFilter = computed(() => ({

View File

@ -46,7 +46,9 @@ async function getClaims() {
originalTicket.value = data[0]?.originalTicketFk;
}
async function getProblems() {
const { data } = await axios.get(`Tickets/getTicketProblems`, {params: { ids: [entityId.value] }});
const { data } = await axios.get(`Tickets/getTicketProblems`, {
params: { ids: [entityId.value] },
});
if (!data) return;
problems.value = data[0];
}

View File

@ -89,7 +89,7 @@ defineExpose({ save });
</div>
<div v-if="newPrice" class="column items-center q-mt-lg">
<span class="text-primary">{{ t('New price') }}</span>
<span class="text-primary">{{ t('basicData.newPrice') }}</span>
<span class="text-subtitle1">{{ toCurrency(newPrice) }}</span>
</div>
</div>
@ -135,3 +135,4 @@ defineExpose({ save });
min-width: 230px;
}
</style>
<

View File

@ -30,7 +30,7 @@ watch(
async (val) => {
crudModelFilter.where.ticketFk = val;
tableRef.value.reload();
}
},
);
const crudModelFilter = reactive({
@ -149,9 +149,9 @@ const columns = computed(() => [
openConfirmationModal(
t('You are going to delete this ticket purchase request'),
t(
'This ticket will be removed from ticket purchase requests! Continue anyway?'
'This ticket will be removed from ticket purchase requests! Continue anyway?',
),
() => removeLine(row.id)
() => removeLine(row.id),
),
},
],

View File

@ -314,7 +314,7 @@ const changePrice = async (sale) => {
const updatePrice = async (sale, newPrice) => {
try {
await axios.post(`Sales/${sale.id}/updatePrice`, {
newPrice: newPrice,
newPrice,
componentId: componentId.value,
});
notify('globals.dataSaved', 'positive');

View File

@ -41,7 +41,7 @@ const transferSales = async (ticketId) => {
const { data } = await axios.post(
`tickets/${$props.ticket.id}/transferSales`,
params
params,
);
if (data && data.id === $props.ticket.id) emit('refreshData');

View File

@ -50,7 +50,7 @@ describe('TicketBoxing', () => {
await vm.getVideoList(expeditionId, timed);
expect(vm.quasar.notify).toHaveBeenCalledWith(
expect.objectContaining({ type: 'negative' })
expect.objectContaining({ type: 'negative' }),
);
});
});

View File

@ -13,12 +13,14 @@ import { useArrayData } from 'composables/useArrayData';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
import VnTable from 'src/components/VnTable/VnTable.vue';
import FetchData from 'src/components/FetchData.vue';
const stateStore = useStateStore();
const { t } = useI18n();
const { notify } = useNotify();
const { openConfirmationModal } = useVnConfirm();
const allColumnNames = ref([]);
const agencies = ref([]);
const arrayData = useArrayData('WeeklyTickets');
const { store } = arrayData;
@ -51,11 +53,16 @@ const columns = computed(() => [
isTitle: true,
cardVisible: true,
component: 'select',
columnFilter: {
name: 'id',
component: 'select',
alias: 'c',
attrs: {
url: 'Clients',
optionLabel: 'name',
optionValue: 'id',
isWhere: true,
inWhere: true,
},
},
columnField: {
component: null,
@ -170,6 +177,11 @@ onMounted(async () => {
</script>
<template>
<FetchData
url="AgencyModes/isActive"
@on-fetch="(data) => (agencies = data)"
auto-load
/>
<VnSearchbar
data-key="WeeklyTickets"
:label="t('weeklyTickets.search')"
@ -203,7 +215,7 @@ onMounted(async () => {
</template>
<template #column-agencyModeFk="{ row }">
<VnSelectCache
url="AgencyModes/isActive"
:options="agencies"
:row="row"
:find="['agencyModeFk', 'agencyModeName']"
v-model="row.agencyModeFk"

View File

@ -70,7 +70,7 @@ watch(
await loadTrays();
}
},
{ deep: true }
{ deep: true },
);
</script>

View File

@ -81,7 +81,7 @@ function filterType(val, update) {
update(() => {
const needle = val.toLowerCase();
filteredWagonTypes.value = wagonTypes.filter(
(v) => v.name.toLowerCase().indexOf(needle) > -1
(v) => v.name.toLowerCase().indexOf(needle) > -1,
);
});
}

View File

@ -4,7 +4,8 @@ import { createWrapper } from 'app/test/vitest/helper';
import WagonCreate from 'pages/Wagon/WagonCreate.vue';
describe('WagonCreate', () => {
let vmEdit, vmCreate;
let vmEdit;
let vmCreate;
const entityId = 1;
beforeAll(() => {

View File

@ -41,7 +41,7 @@ async function toggleNotification(notification) {
quasar.notify({
type: 'positive',
message: t(
`worker.notificationsManager.${notification.active ? '' : 'un'}subscribed`
`worker.notificationsManager.${notification.active ? '' : 'un'}subscribed`,
),
});
} catch (e) {

View File

@ -95,12 +95,12 @@ watch(
() => {
getWorkWeekElements();
paintWorkWeeks();
}
},
);
const getWorkWeekElements = () => {
workWeeksElements.value = document.getElementsByClassName(
'q-calendar-month__workweek'
'q-calendar-month__workweek',
);
};

View File

@ -86,7 +86,7 @@ const showWorkerTimeForm = () => emit('showWorkerTimeForm');
openConfirmationModal(
t('This time entry will be deleted'),
t('Are you sure you want to delete this entry?'),
deleteHourEntry
deleteHourEntry,
)
"
/>

View File

@ -36,7 +36,12 @@ function openConfirmDialog(callback) {
}
</script>
<template>
<QItem @click="openConfirmDialog('remove')" v-ripple clickable data-cy="Delete_button">
<QItem
@click="openConfirmDialog('remove')"
v-ripple
clickable
data-cy="Delete_button"
>
<QItemSection avatar>
<QIcon name="delete" />
</QItemSection>

Some files were not shown because too many files have changed in this diff Show More