Merge branch 'test' of https://gitea.verdnatura.es/verdnatura/salix-front into 8246-UseAddressFk
This commit is contained in:
commit
f2335d7bda
|
@ -2,7 +2,6 @@
|
|||
import { reactive, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnSelectProvince from 'src/components/VnSelectProvince.vue';
|
||||
|
@ -21,14 +20,11 @@ const postcodeFormData = reactive({
|
|||
provinceFk: null,
|
||||
townFk: null,
|
||||
});
|
||||
const townsFetchDataRef = ref(false);
|
||||
const townFilter = ref({});
|
||||
|
||||
const countriesRef = ref(false);
|
||||
const provincesOptions = ref([]);
|
||||
const townsOptions = ref([]);
|
||||
const town = ref({});
|
||||
const countryFilter = ref({});
|
||||
|
||||
function onDataSaved(formData) {
|
||||
const newPostcode = {
|
||||
|
@ -51,7 +47,6 @@ async function setCountry(countryFk, data) {
|
|||
data.townFk = null;
|
||||
data.provinceFk = null;
|
||||
data.countryFk = countryFk;
|
||||
await fetchTowns();
|
||||
}
|
||||
|
||||
// Province
|
||||
|
@ -60,22 +55,11 @@ async function setProvince(id, data) {
|
|||
const newProvince = provincesOptions.value.find((province) => province.id == id);
|
||||
if (newProvince) data.countryFk = newProvince.countryFk;
|
||||
postcodeFormData.provinceFk = id;
|
||||
await fetchTowns();
|
||||
}
|
||||
|
||||
async function onProvinceCreated(data) {
|
||||
postcodeFormData.provinceFk = data.id;
|
||||
}
|
||||
function provinceByCountry(countryFk = postcodeFormData.countryFk) {
|
||||
return provincesOptions.value
|
||||
.filter((province) => province.countryFk === countryFk)
|
||||
.map(({ id }) => id);
|
||||
}
|
||||
|
||||
// Town
|
||||
async function handleTowns(data) {
|
||||
townsOptions.value = data;
|
||||
}
|
||||
function setTown(newTown, data) {
|
||||
town.value = newTown;
|
||||
data.provinceFk = newTown?.provinceFk ?? newTown;
|
||||
|
@ -88,18 +72,6 @@ async function onCityCreated(newTown, formData) {
|
|||
formData.townFk = newTown;
|
||||
setTown(newTown, formData);
|
||||
}
|
||||
async function fetchTowns(countryFk = postcodeFormData.countryFk) {
|
||||
if (!countryFk) return;
|
||||
const provinces = postcodeFormData.provinceFk
|
||||
? [postcodeFormData.provinceFk]
|
||||
: provinceByCountry();
|
||||
townFilter.value.where = {
|
||||
provinceFk: {
|
||||
inq: provinces,
|
||||
},
|
||||
};
|
||||
await townsFetchDataRef.value?.fetch();
|
||||
}
|
||||
|
||||
async function filterTowns(name) {
|
||||
if (name !== '') {
|
||||
|
@ -108,22 +80,11 @@ async function filterTowns(name) {
|
|||
like: `%${name}%`,
|
||||
},
|
||||
};
|
||||
await townsFetchDataRef.value?.fetch();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
ref="townsFetchDataRef"
|
||||
:sort-by="['name ASC']"
|
||||
:limit="30"
|
||||
:filter="townFilter"
|
||||
@on-fetch="handleTowns"
|
||||
auto-load
|
||||
url="Towns/location"
|
||||
/>
|
||||
|
||||
<FormModelPopup
|
||||
url-create="postcodes"
|
||||
model="postcode"
|
||||
|
@ -149,14 +110,13 @@ async function filterTowns(name) {
|
|||
@filter="filterTowns"
|
||||
:tooltip="t('Create city')"
|
||||
v-model="data.townFk"
|
||||
:options="townsOptions"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
url="Towns/location"
|
||||
:rules="validate('postcode.city')"
|
||||
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||
:emit-value="false"
|
||||
required
|
||||
data-cy="locationTown"
|
||||
sort-by="name ASC"
|
||||
>
|
||||
<template #option="{ itemProps, opt }">
|
||||
<QItem v-bind="itemProps">
|
||||
|
@ -197,16 +157,12 @@ async function filterTowns(name) {
|
|||
/>
|
||||
<VnSelect
|
||||
ref="countriesRef"
|
||||
:limit="30"
|
||||
:filter="countryFilter"
|
||||
:sort-by="['name ASC']"
|
||||
auto-load
|
||||
url="Countries"
|
||||
required
|
||||
:label="t('Country')"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
v-model="data.countryFk"
|
||||
:rules="validate('postcode.countryFk')"
|
||||
@update:model-value="(value) => setCountry(value, data)"
|
||||
|
|
|
@ -62,12 +62,9 @@ const where = computed(() => {
|
|||
auto-load
|
||||
:where="where"
|
||||
url="Autonomies/location"
|
||||
:sort-by="['name ASC']"
|
||||
:limit="30"
|
||||
sort-by="name ASC"
|
||||
:label="t('Autonomy')"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
v-model="data.autonomyFk"
|
||||
:rules="validate('province.autonomyFk')"
|
||||
>
|
||||
|
|
|
@ -42,7 +42,6 @@ const itemFilter = {
|
|||
const itemFilterParams = reactive({});
|
||||
const closeButton = ref(null);
|
||||
const isLoading = ref(false);
|
||||
const producersOptions = ref([]);
|
||||
const ItemTypesOptions = ref([]);
|
||||
const InksOptions = ref([]);
|
||||
const tableRows = ref([]);
|
||||
|
@ -121,23 +120,17 @@ const selectItem = ({ id }) => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="Producers"
|
||||
@on-fetch="(data) => (producersOptions = data)"
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="ItemTypes"
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }"
|
||||
order="name"
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC' }"
|
||||
order="name ASC"
|
||||
@on-fetch="(data) => (ItemTypesOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="Inks"
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }"
|
||||
order="name"
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC' }"
|
||||
order="name ASC"
|
||||
@on-fetch="(data) => (InksOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
|
@ -152,11 +145,11 @@ const selectItem = ({ id }) => {
|
|||
<VnInput :label="t('entry.buys.size')" v-model="itemFilterParams.size" />
|
||||
<VnSelect
|
||||
:label="t('globals.producer')"
|
||||
:options="producersOptions"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
v-model="itemFilterParams.producerFk"
|
||||
url="Producers"
|
||||
:fields="['id', 'name']"
|
||||
sort-by="name ASC"
|
||||
/>
|
||||
<VnSelect
|
||||
:label="t('globals.type')"
|
||||
|
|
|
@ -124,7 +124,7 @@ const selectTravel = ({ id }) => {
|
|||
<FetchData
|
||||
url="AgencyModes"
|
||||
@on-fetch="(data) => (agenciesOptions = data)"
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }"
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC' }"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
|
|
|
@ -97,7 +97,7 @@ const $props = defineProps({
|
|||
});
|
||||
const emit = defineEmits(['onFetch', 'onDataSaved']);
|
||||
const modelValue = computed(
|
||||
() => $props.model ?? `formModel_${route?.meta?.title ?? route.name}`
|
||||
() => $props.model ?? `formModel_${route?.meta?.title ?? route.name}`,
|
||||
).value;
|
||||
const componentIsRendered = ref(false);
|
||||
const arrayData = useArrayData(modelValue);
|
||||
|
@ -136,7 +136,8 @@ onMounted(async () => {
|
|||
|
||||
if (!$props.formInitialData) {
|
||||
if ($props.autoLoad && $props.url) await fetch();
|
||||
else if (arrayData.store.data) updateAndEmit('onFetch', arrayData.store.data);
|
||||
else if (arrayData.store.data)
|
||||
updateAndEmit('onFetch', { val: arrayData.store.data });
|
||||
}
|
||||
if ($props.observeFormChanges) {
|
||||
watch(
|
||||
|
@ -148,7 +149,7 @@ onMounted(async () => {
|
|||
JSON.stringify(newVal) !== JSON.stringify(originalData.value);
|
||||
isResetting.value = false;
|
||||
},
|
||||
{ deep: true }
|
||||
{ deep: true },
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -156,7 +157,7 @@ onMounted(async () => {
|
|||
if (!$props.url)
|
||||
watch(
|
||||
() => arrayData.store.data,
|
||||
(val) => updateAndEmit('onFetch', val)
|
||||
(val) => updateAndEmit('onFetch', { val }),
|
||||
);
|
||||
|
||||
watch(
|
||||
|
@ -165,7 +166,7 @@ watch(
|
|||
originalData.value = null;
|
||||
reset();
|
||||
await fetch();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
onBeforeRouteLeave((to, from, next) => {
|
||||
|
@ -194,7 +195,7 @@ async function fetch() {
|
|||
});
|
||||
if (Array.isArray(data)) data = data[0] ?? {};
|
||||
|
||||
updateAndEmit('onFetch', data);
|
||||
updateAndEmit('onFetch', { val: data });
|
||||
} catch (e) {
|
||||
state.set(modelValue, {});
|
||||
originalData.value = {};
|
||||
|
@ -222,7 +223,11 @@ async function save() {
|
|||
|
||||
if ($props.urlCreate) notify('globals.dataCreated', 'positive');
|
||||
|
||||
updateAndEmit('onDataSaved', formData.value, response?.data);
|
||||
updateAndEmit('onDataSaved', {
|
||||
val: formData.value,
|
||||
res: response?.data,
|
||||
old: originalData.value,
|
||||
});
|
||||
if ($props.reload) await arrayData.fetch({});
|
||||
hasChanges.value = false;
|
||||
} finally {
|
||||
|
@ -236,7 +241,7 @@ async function saveAndGo() {
|
|||
}
|
||||
|
||||
function reset() {
|
||||
updateAndEmit('onFetch', originalData.value);
|
||||
updateAndEmit('onFetch', { val: originalData.value });
|
||||
if ($props.observeFormChanges) {
|
||||
hasChanges.value = false;
|
||||
isResetting.value = true;
|
||||
|
@ -254,16 +259,16 @@ function filter(value, update, filterOptions) {
|
|||
(ref) => {
|
||||
ref.setOptionIndex(-1);
|
||||
ref.moveOptionSelection(1, true);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function updateAndEmit(evt, val, res) {
|
||||
function updateAndEmit(evt, { val, res, old } = { val: null, res: null, old: null }) {
|
||||
state.set(modelValue, val);
|
||||
originalData.value = val && JSON.parse(JSON.stringify(val));
|
||||
if (!$props.url) arrayData.store.data = val;
|
||||
|
||||
emit(evt, state.get(modelValue), res);
|
||||
emit(evt, state.get(modelValue), res, old);
|
||||
}
|
||||
|
||||
function trimData(data) {
|
||||
|
|
|
@ -121,23 +121,25 @@ const removeTag = (index, params, search) => {
|
|||
applyTags(params, search);
|
||||
};
|
||||
const setCategoryList = (data) => {
|
||||
categoryList.value = (data || [])
|
||||
.filter((category) => category.display)
|
||||
.map((category) => ({
|
||||
...category,
|
||||
icon: `vn:${(category.icon || '').split('-')[1]}`,
|
||||
}));
|
||||
categoryList.value = (data || []).map((category) => ({
|
||||
...category,
|
||||
icon: `vn:${(category.icon || '').split('-')[1]}`,
|
||||
}));
|
||||
fetchItemTypes();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData url="ItemCategories" limit="30" auto-load @on-fetch="setCategoryList" />
|
||||
<FetchData
|
||||
url="ItemCategories"
|
||||
auto-load
|
||||
@on-fetch="setCategoryList"
|
||||
:where="{ display: { neq: 0 } }"
|
||||
/>
|
||||
<FetchData
|
||||
url="Tags"
|
||||
:filter="{ fields: ['id', 'name', 'isFree'] }"
|
||||
auto-load
|
||||
limit="30"
|
||||
@on-fetch="(data) => (tagOptions = data)"
|
||||
/>
|
||||
<VnFilterPanel
|
||||
|
@ -195,8 +197,6 @@ const setCategoryList = (data) => {
|
|||
:label="t('components.itemsFilterPanel.typeFk')"
|
||||
v-model="params.typeFk"
|
||||
:options="itemTypesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
|
@ -234,7 +234,6 @@ const setCategoryList = (data) => {
|
|||
:label="t('globals.tag')"
|
||||
v-model="value.selectedTag"
|
||||
:options="tagOptions"
|
||||
option-label="name"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<script setup>
|
||||
import { toCurrency } from 'src/filters';
|
||||
|
||||
defineProps({ row: { type: Object, required: true } });
|
||||
</script>
|
||||
<template>
|
||||
|
@ -27,7 +29,8 @@ defineProps({ row: { type: Object, required: true } });
|
|||
size="xs"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ $t('salesTicketsTable.risk') }}: {{ row.risk - row.credit }}
|
||||
{{ $t('salesTicketsTable.risk') }}:
|
||||
{{ toCurrency(row.risk - row.credit) }}
|
||||
</QTooltip>
|
||||
</QIcon>
|
||||
<QIcon v-if="row.hasComponentLack" name="vn:components" color="primary" size="xs">
|
||||
|
|
|
@ -304,6 +304,10 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cardClick(_, row) {
|
||||
if ($props.redirect) router.push({ path: `/${$props.redirect}/${row.id}` });
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<QDrawer
|
||||
|
@ -494,18 +498,13 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
|
|||
</template>
|
||||
<template #item="{ row, colsMap }">
|
||||
<component
|
||||
:is="$props.redirect ? 'router-link' : 'span'"
|
||||
:to="`/${$props.redirect}/` + row.id"
|
||||
v-bind:is="'div'"
|
||||
@click="(event) => cardClick(event, row)"
|
||||
>
|
||||
<QCard
|
||||
bordered
|
||||
flat
|
||||
class="row no-wrap justify-between cursor-pointer q-pa-sm"
|
||||
@click="
|
||||
(_, row) => {
|
||||
$props.rowClick && $props.rowClick(row);
|
||||
}
|
||||
"
|
||||
style="height: 100%"
|
||||
>
|
||||
<QCardSection
|
||||
|
|
|
@ -49,12 +49,22 @@ onBeforeMount(async () => {
|
|||
|
||||
if (props.baseUrl) {
|
||||
onBeforeRouteUpdate(async (to, from) => {
|
||||
if (hasRouteParam(to.params)) {
|
||||
const { matched } = router.currentRoute.value;
|
||||
const { name } = matched.at(-3);
|
||||
if (name) {
|
||||
router.push({ name, params: to.params });
|
||||
}
|
||||
}
|
||||
if (to.params.id !== from.params.id) {
|
||||
arrayData.store.url = `${props.baseUrl}/${to.params.id}`;
|
||||
await arrayData.fetch({ append: false, updateRouter: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
function hasRouteParam(params, valueToCheck = ':addressId') {
|
||||
return Object.values(params).includes(valueToCheck);
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<Teleport to="#left-panel" v-if="stateStore.isHeaderMounted()">
|
||||
|
|
|
@ -85,6 +85,7 @@ const handleModelValue = (data) => {
|
|||
:tooltip="t('Create new location')"
|
||||
:rules="mixinRules"
|
||||
:lazy-rules="true"
|
||||
required
|
||||
>
|
||||
<template #form>
|
||||
<CreateNewPostcode
|
||||
|
|
|
@ -10,12 +10,7 @@ const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
|
|||
const $attrs = useAttrs();
|
||||
const { t } = useI18n();
|
||||
|
||||
const isRequired = computed(() => {
|
||||
return useRequired($attrs).isRequired;
|
||||
});
|
||||
const requiredFieldRule = computed(() => {
|
||||
return useRequired($attrs).requiredFieldRule;
|
||||
});
|
||||
const { isRequired, requiredFieldRule } = useRequired($attrs);
|
||||
|
||||
const $props = defineProps({
|
||||
modelValue: {
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { useRequired } from '../useRequired';
|
||||
|
||||
vi.mock('../useValidator', () => ({
|
||||
useValidator: () => ({
|
||||
validations: () => ({
|
||||
required: vi.fn((isRequired, val) => {
|
||||
if (!isRequired) return true;
|
||||
return val !== null && val !== undefined && val !== '';
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('useRequired', () => {
|
||||
it('should detect required when attr is boolean true', () => {
|
||||
const attrs = { required: true };
|
||||
const { isRequired } = useRequired(attrs);
|
||||
expect(isRequired).toBe(true);
|
||||
});
|
||||
|
||||
it('should detect required when attr is boolean false', () => {
|
||||
const attrs = { required: false };
|
||||
const { isRequired } = useRequired(attrs);
|
||||
expect(isRequired).toBe(false);
|
||||
});
|
||||
|
||||
it('should detect required when attr exists without value', () => {
|
||||
const attrs = { required: '' };
|
||||
const { isRequired } = useRequired(attrs);
|
||||
expect(isRequired).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when required attr does not exist', () => {
|
||||
const attrs = { someOtherAttr: 'value' };
|
||||
const { isRequired } = useRequired(attrs);
|
||||
expect(isRequired).toBe(false);
|
||||
});
|
||||
|
||||
describe('requiredFieldRule', () => {
|
||||
it('should validate required field with value', () => {
|
||||
const attrs = { required: true };
|
||||
const { requiredFieldRule } = useRequired(attrs);
|
||||
expect(requiredFieldRule('some value')).toBe(true);
|
||||
});
|
||||
|
||||
it('should validate required field with empty value', () => {
|
||||
const attrs = { required: true };
|
||||
const { requiredFieldRule } = useRequired(attrs);
|
||||
expect(requiredFieldRule('')).toBe(false);
|
||||
});
|
||||
|
||||
it('should pass validation when field is not required', () => {
|
||||
const attrs = { required: false };
|
||||
const { requiredFieldRule } = useRequired(attrs);
|
||||
expect(requiredFieldRule('')).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle null and undefined values', () => {
|
||||
const attrs = { required: true };
|
||||
const { requiredFieldRule } = useRequired(attrs);
|
||||
expect(requiredFieldRule(null)).toBe(false);
|
||||
expect(requiredFieldRule(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -11,6 +11,7 @@ export async function useCau(res, message) {
|
|||
const { config, headers, request, status, statusText, data } = res || {};
|
||||
const { params, url, method, signal, headers: confHeaders } = config || {};
|
||||
const { message: resMessage, code, name } = data?.error || {};
|
||||
delete confHeaders.Authorization;
|
||||
|
||||
const additionalData = {
|
||||
path: location.hash,
|
||||
|
@ -40,7 +41,7 @@ export async function useCau(res, message) {
|
|||
handler: async () => {
|
||||
const locale = i18n.global.t;
|
||||
const reason = ref(
|
||||
code == 'ACCESS_DENIED' ? locale('cau.askPrivileges') : ''
|
||||
code == 'ACCESS_DENIED' ? locale('cau.askPrivileges') : '',
|
||||
);
|
||||
openConfirmationModal(
|
||||
locale('cau.title'),
|
||||
|
@ -59,10 +60,9 @@ export async function useCau(res, message) {
|
|||
'onUpdate:modelValue': (val) => (reason.value = val),
|
||||
label: locale('cau.inputLabel'),
|
||||
class: 'full-width',
|
||||
required: true,
|
||||
autofocus: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -2,14 +2,10 @@ import { useValidator } from 'src/composables/useValidator';
|
|||
|
||||
export function useRequired($attrs) {
|
||||
const { validations } = useValidator();
|
||||
const hasRequired = Object.keys($attrs).includes('required');
|
||||
let isRequired = false;
|
||||
if (hasRequired) {
|
||||
const required = $attrs['required'];
|
||||
if (typeof required === 'boolean') {
|
||||
isRequired = required;
|
||||
}
|
||||
}
|
||||
const isRequired =
|
||||
typeof $attrs['required'] === 'boolean'
|
||||
? $attrs['required']
|
||||
: Object.keys($attrs).includes('required');
|
||||
const requiredFieldRule = (val) => validations().required(isRequired, val);
|
||||
|
||||
return {
|
||||
|
|
|
@ -652,6 +652,7 @@ supplier:
|
|||
verified: Verificado
|
||||
isActive: Está activo
|
||||
billingData: Forma de pago
|
||||
financialData: Datos financieros
|
||||
payDeadline: Plazo de pago
|
||||
payDay: Día de pago
|
||||
account: Cuenta
|
||||
|
|
|
@ -34,6 +34,12 @@ account.value.hasAccount = hasAccount.value;
|
|||
const entityId = computed(() => +route.params.id);
|
||||
const hasitManagementAccess = ref();
|
||||
const hasSysadminAccess = ref();
|
||||
const isHimself = computed(() => user.value.id === account.value.id);
|
||||
const url = computed(() =>
|
||||
isHimself.value
|
||||
? 'Accounts/change-password'
|
||||
: `Accounts/${entityId.value}/setPassword`
|
||||
);
|
||||
|
||||
async function updateStatusAccount(active) {
|
||||
if (active) {
|
||||
|
@ -106,11 +112,8 @@ onMounted(() => {
|
|||
:ask-old-pass="askOldPass"
|
||||
:submit-fn="
|
||||
async (newPassword, oldPassword) => {
|
||||
await axios.patch(`Accounts/change-password`, {
|
||||
userId: entityId,
|
||||
newPassword,
|
||||
oldPassword,
|
||||
});
|
||||
const body = isHimself ? { userId: entityId, oldPassword } : {};
|
||||
await axios.patch(url, { ...body, newPassword });
|
||||
}
|
||||
"
|
||||
/>
|
||||
|
@ -158,16 +161,10 @@ onMounted(() => {
|
|||
>
|
||||
<QItemSection>{{ t('globals.delete') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="hasSysadminAccess"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="user.id === account.id ? onChangePass(true) : onChangePass(false)"
|
||||
>
|
||||
<QItemSection v-if="user.id === account.id">
|
||||
{{ t('globals.changePass') }}
|
||||
<QItem v-if="hasSysadminAccess || isHimself" v-ripple clickable>
|
||||
<QItemSection @click="onChangePass(isHimself)">
|
||||
{{ isHimself ? t('globals.changePass') : t('globals.setPass') }}
|
||||
</QItemSection>
|
||||
<QItemSection v-else>{{ t('globals.setPass') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="!account.hasAccount && hasSysadminAccess"
|
||||
|
|
|
@ -57,7 +57,6 @@ function onFetch(rows, newRows) {
|
|||
const price = row.quantity * sale.price;
|
||||
const discount = (sale.discount * price) / 100;
|
||||
amountClaimed.value = amountClaimed.value + (price - discount);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +190,7 @@ async function saveWhenHasChanges() {
|
|||
ref="claimLinesForm"
|
||||
:url="`Claims/${route.params.id}/lines`"
|
||||
save-url="ClaimBeginnings/crud"
|
||||
:filter="linesFilter"
|
||||
:user-filter="linesFilter"
|
||||
@on-fetch="onFetch"
|
||||
v-model:selected="selected"
|
||||
:default-save="false"
|
||||
|
@ -208,7 +207,6 @@ async function saveWhenHasChanges() {
|
|||
selection="multiple"
|
||||
v-model:selected="selected"
|
||||
:grid="$q.screen.lt.md"
|
||||
|
||||
>
|
||||
<template #body-cell-claimed="{ row }">
|
||||
<QTd auto-width align="right" class="text-primary shrink">
|
||||
|
@ -330,9 +328,10 @@ async function saveWhenHasChanges() {
|
|||
width: 100%;
|
||||
}
|
||||
.grid-style-transition {
|
||||
transition: transform 0.28s, background-color 0.28s;
|
||||
transition:
|
||||
transform 0.28s,
|
||||
background-color 0.28s;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
|
|
|
@ -156,7 +156,6 @@ function onDrag() {
|
|||
url="Claims"
|
||||
:filter="claimDmsFilter"
|
||||
@on-fetch="([data]) => setClaimDms(data)"
|
||||
limit="20"
|
||||
auto-load
|
||||
ref="claimDmsRef"
|
||||
/>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||
import VnSelect from 'components/common/VnSelect.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
|
@ -14,15 +12,14 @@ const props = defineProps({
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
states: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const states = ref([]);
|
||||
|
||||
defineExpose({ states });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData url="ClaimStates" @on-fetch="(data) => (states = data)" auto-load />
|
||||
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
|
||||
<template #tags="{ tag, formatFn }">
|
||||
<div class="q-gutter-x-xs">
|
||||
|
|
|
@ -10,12 +10,13 @@ import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
|||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
import ZoneDescriptorProxy from '../Zone/Card/ZoneDescriptorProxy.vue';
|
||||
import VnSection from 'src/components/common/VnSection.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { viewSummary } = useSummaryDialog();
|
||||
const dataKey = 'ClaimList';
|
||||
|
||||
const claimFilterRef = ref();
|
||||
const states = ref([]);
|
||||
const columns = computed(() => [
|
||||
{
|
||||
align: 'left',
|
||||
|
@ -81,8 +82,7 @@ const columns = computed(() => [
|
|||
align: 'left',
|
||||
label: t('claim.state'),
|
||||
format: ({ stateCode }) =>
|
||||
claimFilterRef.value?.states.find(({ code }) => code === stateCode)
|
||||
?.description,
|
||||
states.value?.find(({ code }) => code === stateCode)?.description,
|
||||
name: 'stateCode',
|
||||
chip: {
|
||||
condition: () => true,
|
||||
|
@ -92,7 +92,7 @@ const columns = computed(() => [
|
|||
name: 'claimStateFk',
|
||||
component: 'select',
|
||||
attrs: {
|
||||
options: claimFilterRef.value?.states,
|
||||
options: states.value,
|
||||
optionLabel: 'description',
|
||||
},
|
||||
},
|
||||
|
@ -125,6 +125,7 @@ const STATE_COLOR = {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData url="ClaimStates" @on-fetch="(data) => (states = data)" auto-load />
|
||||
<VnSection
|
||||
:data-key="dataKey"
|
||||
:columns="columns"
|
||||
|
@ -135,7 +136,7 @@ const STATE_COLOR = {
|
|||
}"
|
||||
>
|
||||
<template #advanced-menu>
|
||||
<ClaimFilter data-key="ClaimList" ref="claimFilterRef" />
|
||||
<ClaimFilter :data-key ref="claimFilterRef" :states />
|
||||
</template>
|
||||
<template #body>
|
||||
<VnTable
|
||||
|
|
|
@ -117,7 +117,7 @@ const toCustomerAddressEdit = (addressId) => {
|
|||
data-key="CustomerAddresses"
|
||||
order="id DESC"
|
||||
ref="vnPaginateRef"
|
||||
:user-filter="addressFilter"
|
||||
:filter="addressFilter"
|
||||
:url="`Clients/${route.params.id}/addresses`"
|
||||
/>
|
||||
<div class="full-width flex justify-center">
|
||||
|
@ -189,11 +189,11 @@ const toCustomerAddressEdit = (addressId) => {
|
|||
|
||||
<QSeparator
|
||||
class="q-mx-lg"
|
||||
v-if="item.observations.length"
|
||||
v-if="item?.observations?.length"
|
||||
vertical
|
||||
/>
|
||||
|
||||
<div v-if="item.observations.length">
|
||||
<div v-if="item?.observations?.length">
|
||||
<div
|
||||
:key="obIndex"
|
||||
class="flex q-mb-sm"
|
||||
|
|
|
@ -17,8 +17,7 @@ const bankEntitiesRef = ref(null);
|
|||
|
||||
const filter = {
|
||||
fields: ['id', 'bic', 'name'],
|
||||
order: 'bic ASC',
|
||||
limit: 30,
|
||||
order: 'bic ASC'
|
||||
};
|
||||
|
||||
const getBankEntities = (data, formData) => {
|
||||
|
|
|
@ -2,16 +2,23 @@
|
|||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useQuasar } from 'quasar';
|
||||
import axios from 'axios';
|
||||
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import FormModel from 'components/FormModel.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnLocation from 'src/components/common/VnLocation.vue';
|
||||
import { getDifferences, getUpdatedValues } from 'src/filters';
|
||||
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
||||
|
||||
const quasar = useQuasar();
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const { notify } = useNotify();
|
||||
|
||||
const typesTaxes = ref([]);
|
||||
const typesTransactions = ref([]);
|
||||
|
@ -23,6 +30,37 @@ function handleLocation(data, location) {
|
|||
data.provinceFk = provinceFk;
|
||||
data.countryFk = countryFk;
|
||||
}
|
||||
function onBeforeSave(formData, originalData) {
|
||||
return getUpdatedValues(
|
||||
Object.keys(getDifferences(formData, originalData)),
|
||||
formData,
|
||||
);
|
||||
}
|
||||
|
||||
async function checkEtChanges(data, _, originalData) {
|
||||
const equalizatedHasChanged = originalData.isEqualizated != data.isEqualizated;
|
||||
const hasToInvoiceByAddress =
|
||||
originalData.hasToInvoiceByAddress || data.hasToInvoiceByAddress;
|
||||
if (equalizatedHasChanged && hasToInvoiceByAddress) {
|
||||
quasar.dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
title: t('You changed the equalization tax'),
|
||||
message: t('Do you want to spread the change?'),
|
||||
promise: () => acceptPropagate(data),
|
||||
},
|
||||
});
|
||||
} else if (equalizatedHasChanged) {
|
||||
await acceptPropagate(data);
|
||||
}
|
||||
}
|
||||
|
||||
async function acceptPropagate({ isEqualizated }) {
|
||||
await axios.patch(`Clients/${route.params.id}/addressesPropagateRe`, {
|
||||
isEqualizated,
|
||||
});
|
||||
notify(t('Equivalent tax spreaded'), 'warning');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -36,6 +74,9 @@ function handleLocation(data, location) {
|
|||
:url-update="`Clients/${route.params.id}/updateFiscalData`"
|
||||
auto-load
|
||||
model="customer"
|
||||
:mapper="onBeforeSave"
|
||||
observe-form-changes
|
||||
@on-data-saved="checkEtChanges"
|
||||
>
|
||||
<template #form="{ data, validate }">
|
||||
<VnRow>
|
||||
|
@ -180,6 +221,9 @@ es:
|
|||
whenActivatingIt: Al activarlo, no informar el código del país en el campo nif
|
||||
inOrderToInvoice: Para facturar no se consulta este campo, sino el RE de consignatario. Al modificar este campo si no esta marcada la casilla Facturar por consignatario, se propagará automaticamente el cambio a todos lo consignatarios, en caso contrario preguntará al usuario si quiere o no propagar
|
||||
Daily invoice: Facturación diaria
|
||||
Equivalent tax spreaded: Recargo de equivalencia propagado
|
||||
You changed the equalization tax: Has cambiado el recargo de equivalencia
|
||||
Do you want to spread the change?: ¿Deseas propagar el cambio a sus consignatarios?
|
||||
en:
|
||||
onlyLetters: Only letters, numbers and spaces can be used
|
||||
whenActivatingIt: When activating it, do not enter the country code in the ID field
|
||||
|
|
|
@ -270,7 +270,7 @@ const sumRisk = ({ clientRisks }) => {
|
|||
<VnTitle
|
||||
target="_blank"
|
||||
:url="`${grafanaUrl}/d/40buzE4Vk/comportamiento-pagos-clientes?orgId=1&var-clientFk=${entityId}`"
|
||||
:text="t('customer.summary.payMethodFk')"
|
||||
:text="t('customer.summary.financialData')"
|
||||
icon="vn:grafana"
|
||||
/>
|
||||
<VnLv
|
||||
|
|
|
@ -87,7 +87,7 @@ onMounted(async () => {
|
|||
<FetchData
|
||||
url="Campaigns/latest"
|
||||
@on-fetch="(data) => (campaignsOptions = data)"
|
||||
:filter="{ fields: ['id', 'code', 'dated'], order: 'code ASC', limit: 30 }"
|
||||
:filter="{ fields: ['id', 'code', 'dated'], order: 'code ASC' }"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
|
|
|
@ -98,7 +98,6 @@ function onAgentCreated({ id, fiscalName }, data) {
|
|||
:rules="validate('Worker.postcode')"
|
||||
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||
v-model="data.location"
|
||||
:required="true"
|
||||
@update:model-value="(location) => handleLocation(data, location)"
|
||||
/>
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ const getData = async (observations) => {
|
|||
notes.value = originalNotes
|
||||
.map((observation) => {
|
||||
const type = observationTypes.value.find(
|
||||
(type) => type.id === observation.observationTypeFk
|
||||
(type) => type.id === observation.observationTypeFk,
|
||||
);
|
||||
return type
|
||||
? {
|
||||
|
@ -96,11 +96,11 @@ const updateObservations = async (payload) => {
|
|||
await axios.post('AddressObservations/crud', payload);
|
||||
notes.value = [];
|
||||
deletes.value = [];
|
||||
toCustomerAddress();
|
||||
};
|
||||
async function updateAll({ data, payload }) {
|
||||
await updateObservations(payload);
|
||||
await updateAddress(data);
|
||||
toCustomerAddress();
|
||||
}
|
||||
function getPayload() {
|
||||
return {
|
||||
|
@ -112,8 +112,8 @@ function getPayload() {
|
|||
(oNote) =>
|
||||
oNote.id === note.id &&
|
||||
(note.description !== oNote.description ||
|
||||
note.observationTypeFk !== oNote.observationTypeFk)
|
||||
)
|
||||
note.observationTypeFk !== oNote.observationTypeFk),
|
||||
),
|
||||
)
|
||||
.map((note) => ({
|
||||
data: note,
|
||||
|
@ -130,24 +130,19 @@ async function handleDialog(data) {
|
|||
.dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
title: t(
|
||||
'confirmTicket'
|
||||
),
|
||||
title: t('confirmTicket'),
|
||||
message: t('confirmDeletionMessage'),
|
||||
},
|
||||
})
|
||||
.onOk(async () => {
|
||||
await updateAddressTicket();
|
||||
await updateAll(body);
|
||||
toCustomerAddress();
|
||||
})
|
||||
.onCancel(async () => {
|
||||
await updateAll(body);
|
||||
toCustomerAddress();
|
||||
});
|
||||
} else {
|
||||
updateAll(body);
|
||||
toCustomerAddress();
|
||||
await updateAll(body);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,20 +31,18 @@ onMounted(async () => {
|
|||
ref="summary"
|
||||
:url="`Departments/${entityId}`"
|
||||
class="full-width"
|
||||
style="max-width: 900px"
|
||||
module-name="Department"
|
||||
>
|
||||
<template #header="{ entity }">
|
||||
<div>{{ entity.name }}</div>
|
||||
</template>
|
||||
<template #body="{ entity: department }">
|
||||
<QCard class="column">
|
||||
<QCard class="vn-one">
|
||||
<VnTitle
|
||||
:url="`#/worker/department/${entityId}/basic-data`"
|
||||
:text="t('Basic data')"
|
||||
/>
|
||||
<div class="full-width row wrap justify-between content-between">
|
||||
<div class="column" style="min-width: 50%">
|
||||
<div class="column">
|
||||
<VnLv :label="t('globals.name')" :value="department.name" dash />
|
||||
<VnLv :label="t('globals.code')" :value="department.code" dash />
|
||||
<VnLv
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
import VnInput from 'components/common/VnInput.vue';
|
||||
import VnSelect from 'components/common/VnSelect.vue';
|
||||
|
@ -18,18 +16,10 @@ defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const itemTypeWorkersOptions = ref([]);
|
||||
const tagValues = ref([]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="TicketRequests/getItemTypeWorker"
|
||||
limit="30"
|
||||
auto-load
|
||||
:filter="{ fields: ['id', 'nickname'], order: 'nickname ASC', limit: 30 }"
|
||||
@on-fetch="(data) => (itemTypeWorkersOptions = data)"
|
||||
/>
|
||||
<ItemsFilterPanel :data-key="dataKey" :custom-tags="['tags']">
|
||||
<template #body="{ params, searchFn }">
|
||||
<QItem class="q-my-md">
|
||||
|
@ -37,9 +27,10 @@ const tagValues = ref([]);
|
|||
<VnSelect
|
||||
:label="t('components.itemsFilterPanel.salesPersonFk')"
|
||||
v-model="params.salesPersonFk"
|
||||
:options="itemTypeWorkersOptions"
|
||||
option-value="id"
|
||||
url="TicketRequests/getItemTypeWorker"
|
||||
option-label="nickname"
|
||||
:fields="['id', 'nickname']"
|
||||
sort-by="nickname ASC"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
|
@ -52,8 +43,9 @@ const tagValues = ref([]);
|
|||
<QItemSection>
|
||||
<VnSelectSupplier
|
||||
v-model="params.supplierFk"
|
||||
@update:model-value="searchFn()"
|
||||
hide-selected
|
||||
url="Suppliers"
|
||||
:fields="['id', 'name', 'nickname']"
|
||||
sort-by="name ASC"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
|
|
|
@ -7,7 +7,6 @@ import { toDate } from 'src/filters';
|
|||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import { getTotal } from 'src/composables/getTotal';
|
||||
import CrudModel from 'src/components/CrudModel.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
|
@ -21,7 +20,6 @@ const invoiceIn = computed(() => arrayData.store.data);
|
|||
const currency = computed(() => invoiceIn.value?.currency?.code);
|
||||
|
||||
const rowsSelected = ref([]);
|
||||
const banks = ref([]);
|
||||
const invoiceInFormRef = ref();
|
||||
const invoiceId = +route.params.id;
|
||||
const filter = { where: { invoiceInFk: invoiceId } };
|
||||
|
@ -40,10 +38,9 @@ const columns = computed(() => [
|
|||
name: 'bank',
|
||||
label: t('Bank'),
|
||||
field: (row) => row.bankFk,
|
||||
options: banks.value,
|
||||
model: 'bankFk',
|
||||
optionValue: 'id',
|
||||
optionLabel: 'bank',
|
||||
url: 'Accountings',
|
||||
sortable: true,
|
||||
tabIndex: 2,
|
||||
align: 'left',
|
||||
|
@ -75,12 +72,6 @@ async function insert() {
|
|||
}
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
url="Accountings"
|
||||
auto-load
|
||||
limit="30"
|
||||
@on-fetch="(data) => (banks = data)"
|
||||
/>
|
||||
<CrudModel
|
||||
v-if="invoiceIn"
|
||||
ref="invoiceInFormRef"
|
||||
|
@ -110,9 +101,9 @@ async function insert() {
|
|||
<QTd>
|
||||
<VnSelect
|
||||
v-model="row[col.model]"
|
||||
:options="col.options"
|
||||
:option-value="col.optionValue"
|
||||
:url="col.url"
|
||||
:option-label="col.optionLabel"
|
||||
:option-value="col.optionValue"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
|
@ -186,8 +177,7 @@ async function insert() {
|
|||
:label="t('Bank')"
|
||||
class="full-width"
|
||||
v-model="props.row['bankFk']"
|
||||
:options="banks"
|
||||
option-value="id"
|
||||
url="Accountings"
|
||||
option-label="bank"
|
||||
>
|
||||
<template #option="scope">
|
||||
|
|
|
@ -125,7 +125,7 @@ const ticketsColumns = ref([
|
|||
:value="toDate(invoiceOut.issued)"
|
||||
/>
|
||||
<VnLv
|
||||
:label="t('invoiceOut.summary.dued')"
|
||||
:label="t('invoiceOut.summary.expirationDate')"
|
||||
:value="toDate(invoiceOut.dued)"
|
||||
/>
|
||||
<VnLv :label="t('globals.created')" :value="toDate(invoiceOut.created)" />
|
||||
|
|
|
@ -97,12 +97,19 @@ const columns = computed(() => [
|
|||
},
|
||||
{
|
||||
align: 'left',
|
||||
name: 'companyCode',
|
||||
name: 'companyFk',
|
||||
label: t('globals.company'),
|
||||
cardVisible: true,
|
||||
component: 'select',
|
||||
attrs: { url: 'Companies', optionLabel: 'code', optionValue: 'id' },
|
||||
columnField: { component: null },
|
||||
attrs: {
|
||||
url: 'Companies',
|
||||
optionLabel: 'code',
|
||||
optionValue: 'id',
|
||||
},
|
||||
columnField: {
|
||||
component: null,
|
||||
},
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.companyCode),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
|
|
|
@ -19,6 +19,7 @@ invoiceOut:
|
|||
summary:
|
||||
issued: Issued
|
||||
dued: Due
|
||||
expirationDate: Expiration date
|
||||
booked: Booked
|
||||
taxBreakdown: Tax breakdown
|
||||
taxableBase: Taxable base
|
||||
|
|
|
@ -19,6 +19,7 @@ invoiceOut:
|
|||
summary:
|
||||
issued: Fecha
|
||||
dued: Fecha límite
|
||||
expirationDate: Fecha vencimiento
|
||||
booked: Contabilizada
|
||||
taxBreakdown: Desglose impositivo
|
||||
taxableBase: Base imp.
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
import VnSelect from 'components/common/VnSelect.vue';
|
||||
import ItemsFilterPanel from 'src/components/ItemsFilterPanel.vue';
|
||||
|
@ -16,17 +14,9 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const itemTypeWorkersOptions = ref([]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="TicketRequests/getItemTypeWorker"
|
||||
limit="30"
|
||||
auto-load
|
||||
:filter="{ fields: ['id', 'nickname'], order: 'nickname ASC', limit: 30 }"
|
||||
@on-fetch="(data) => (itemTypeWorkersOptions = data)"
|
||||
/>
|
||||
<ItemsFilterPanel :data-key="props.dataKey" :custom-tags="['tags']">
|
||||
<template #body="{ params, searchFn }">
|
||||
<QItem class="q-my-md">
|
||||
|
@ -34,14 +24,15 @@ const itemTypeWorkersOptions = ref([]);
|
|||
<VnSelect
|
||||
:label="t('params.buyerFk')"
|
||||
v-model="params.buyerFk"
|
||||
:options="itemTypeWorkersOptions"
|
||||
option-value="id"
|
||||
url="TicketRequests/getItemTypeWorker"
|
||||
:fields="['id', 'nickname']"
|
||||
option-label="nickname"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
use-input
|
||||
@update:model-value="searchFn()"
|
||||
sort-by="nickname ASC"
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
|
@ -50,11 +41,10 @@ const itemTypeWorkersOptions = ref([]);
|
|||
<VnSelect
|
||||
url="Warehouses"
|
||||
auto-load
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }"
|
||||
:fields="['id', 'name']"
|
||||
sort-by="name ASC"
|
||||
:label="t('params.warehouseFk')"
|
||||
v-model="params.warehouseFk"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
|
|
|
@ -61,6 +61,7 @@ function exprBuilder(param, value) {
|
|||
case 'nickname':
|
||||
return { [`t.nickname`]: { like: `%${value}%` } };
|
||||
case 'zoneFk':
|
||||
return { 't.zoneFk': value };
|
||||
case 'department':
|
||||
return { 'd.name': value };
|
||||
case 'totalWithVat':
|
||||
|
|
|
@ -43,10 +43,9 @@ const addToOrder = async () => {
|
|||
);
|
||||
|
||||
state.set('orderTotal', orderTotal);
|
||||
const rows = orderData.value.rows.push(...items) || [];
|
||||
state.set('orderData', {
|
||||
...orderData.value,
|
||||
rows,
|
||||
items,
|
||||
});
|
||||
notify(t('globals.dataSaved'), 'positive');
|
||||
emit('added', -totalQuantity(items));
|
||||
|
|
|
@ -15,7 +15,7 @@ const sectors = ref([]);
|
|||
const sectorFilter = { fields: ['id', 'description'] };
|
||||
|
||||
const filter = {
|
||||
fields: ['sectorFk', 'code', 'pickingOrder', 'row', 'column'],
|
||||
fields: ['sectorFk', 'code', 'pickingOrder'],
|
||||
include: [{ relation: 'sector', scope: sectorFilter }],
|
||||
};
|
||||
</script>
|
||||
|
@ -33,10 +33,6 @@ const filter = {
|
|||
<VnInput v-model="data.code" :label="t('globals.code')" />
|
||||
<VnInput v-model="data.pickingOrder" :label="t('parking.pickingOrder')" />
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput v-model="data.row" :label="t('parking.row')" />
|
||||
<VnInput v-model="data.column" :label="t('parking.column')" />
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
v-model="data.sectorFk"
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
parking:
|
||||
pickingOrder: Picking order
|
||||
sector: Sector
|
||||
row: Row
|
||||
column: Column
|
||||
search: Search parking
|
||||
searchInfo: You can search by parking code
|
|
@ -1,7 +1,5 @@
|
|||
parking:
|
||||
pickingOrder: Orden de recogida
|
||||
row: Fila
|
||||
sector: Sector
|
||||
column: Columna
|
||||
search: Buscar parking
|
||||
searchInfo: Puedes buscar por código de parking
|
|
@ -46,7 +46,6 @@ const exprBuilder = (param, value) => {
|
|||
url="AgencyModes"
|
||||
:filter="{ fields: ['id', 'name'] }"
|
||||
sort-by="name ASC"
|
||||
limit="30"
|
||||
@on-fetch="(data) => (agencyList = data)"
|
||||
auto-load
|
||||
/>
|
||||
|
@ -54,7 +53,6 @@ const exprBuilder = (param, value) => {
|
|||
url="Agencies"
|
||||
:filter="{ fields: ['id', 'name'] }"
|
||||
sort-by="name ASC"
|
||||
limit="30"
|
||||
@on-fetch="(data) => (agencyAgreementList = data)"
|
||||
auto-load
|
||||
/>
|
||||
|
@ -120,7 +118,11 @@ const exprBuilder = (param, value) => {
|
|||
<VnSelectSupplier
|
||||
:label="t('Autonomous')"
|
||||
v-model="params.supplierFk"
|
||||
hide-selected
|
||||
url="Suppliers"
|
||||
:fields="['name']"
|
||||
sort-by="name ASC"
|
||||
option-value="name"
|
||||
option-label="name"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||
|
@ -7,7 +7,7 @@ import VnLv from 'components/ui/VnLv.vue';
|
|||
import useCardDescription from 'composables/useCardDescription';
|
||||
import { dashIfEmpty, toDate } from 'src/filters';
|
||||
import RouteDescriptorMenu from 'pages/Route/Card/RouteDescriptorMenu.vue';
|
||||
|
||||
import axios from 'axios';
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
|
@ -18,10 +18,24 @@ const $props = defineProps({
|
|||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
||||
const zone = ref();
|
||||
const zoneId = ref();
|
||||
const entityId = computed(() => {
|
||||
return $props.id || route.params.id;
|
||||
});
|
||||
const getZone = async () => {
|
||||
const filter = {
|
||||
where: { routeFk: $props.id ? $props.id : route.params.id },
|
||||
};
|
||||
const { data } = await axios.get('Tickets/findOne', {
|
||||
params: {
|
||||
filter: JSON.stringify(filter),
|
||||
},
|
||||
});
|
||||
zoneId.value = data.zoneFk;
|
||||
const { data: zoneData } = await axios.get(`Zones/${zoneId.value}`);
|
||||
zone.value = zoneData.name;
|
||||
};
|
||||
|
||||
const filter = {
|
||||
fields: [
|
||||
|
@ -38,7 +52,6 @@ const filter = {
|
|||
'started',
|
||||
'finished',
|
||||
'cost',
|
||||
'zoneFk',
|
||||
'isOk',
|
||||
],
|
||||
include: [
|
||||
|
@ -47,7 +60,13 @@ const filter = {
|
|||
relation: 'vehicle',
|
||||
scope: { fields: ['id', 'm3'] },
|
||||
},
|
||||
{ relation: 'zone', scope: { fields: ['id', 'name'] } },
|
||||
{
|
||||
relation: 'ticket',
|
||||
scope: {
|
||||
fields: ['id', 'name', 'zoneFk'],
|
||||
include: { relation: 'zone', scope: { fields: ['id', 'name'] } },
|
||||
},
|
||||
},
|
||||
{
|
||||
relation: 'worker',
|
||||
scope: {
|
||||
|
@ -65,6 +84,9 @@ const filter = {
|
|||
};
|
||||
const data = ref(useCardDescription());
|
||||
const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
|
||||
onMounted(async () => {
|
||||
getZone();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -81,11 +103,11 @@ const setData = (entity) => (data.value = useCardDescription(entity.code, entity
|
|||
<template #body="{ entity }">
|
||||
<VnLv :label="t('Date')" :value="toDate(entity?.dated)" />
|
||||
<VnLv :label="t('Agency')" :value="entity?.agencyMode?.name" />
|
||||
<VnLv :label="t('Zone')" :value="entity?.zone?.name" />
|
||||
<VnLv :label="t('Zone')" :value="zone" />
|
||||
<VnLv
|
||||
:label="t('Volume')"
|
||||
:value="`${dashIfEmpty(entity?.m3)} / ${dashIfEmpty(
|
||||
entity?.vehicle?.m3
|
||||
entity?.vehicle?.m3,
|
||||
)} m³`"
|
||||
/>
|
||||
<VnLv :label="t('Description')" :value="entity?.description" />
|
||||
|
|
|
@ -43,7 +43,6 @@ const routeFilter = {
|
|||
'started',
|
||||
'finished',
|
||||
'cost',
|
||||
'zoneFk',
|
||||
'isOk',
|
||||
],
|
||||
include: [
|
||||
|
@ -52,7 +51,13 @@ const routeFilter = {
|
|||
relation: 'vehicle',
|
||||
scope: { fields: ['id', 'm3'] },
|
||||
},
|
||||
{ relation: 'zone', scope: { fields: ['id', 'name'] } },
|
||||
{
|
||||
relation: 'ticket',
|
||||
scope: {
|
||||
fields: ['id', 'name', 'zoneFk'],
|
||||
include: { relation: 'zone', scope: { fields: ['id', 'name'] } },
|
||||
},
|
||||
},
|
||||
{
|
||||
relation: 'worker',
|
||||
scope: {
|
||||
|
|
|
@ -48,7 +48,6 @@ const onFetch = (data) => {
|
|||
},
|
||||
],
|
||||
}"
|
||||
limit="30"
|
||||
@on-fetch="onFetch"
|
||||
/>
|
||||
<div :class="[isDialog ? 'column' : 'form-gap', 'full-width flex']">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useRouter } from 'vue-router';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import FormModel from 'components/FormModel.vue';
|
||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||
|
@ -10,7 +10,6 @@ import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
|
|||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
const filter = { include: [{ relation: 'supplier' }] };
|
||||
const onSave = (data, response) => {
|
||||
|
@ -19,7 +18,7 @@ const onSave = (data, response) => {
|
|||
</script>
|
||||
<template>
|
||||
<FormModel
|
||||
:url="`Roadmaps/${route.params?.id}`"
|
||||
:url="`Roadmaps/${$route.params?.id}`"
|
||||
observe-form-changes
|
||||
:filter="filter"
|
||||
model="roadmap"
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnFilterPanel from 'components/ui/VnFilterPanel.vue';
|
||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||
import VnInput from 'components/common/VnInput.vue';
|
||||
|
@ -65,6 +63,7 @@ const emit = defineEmits(['search']);
|
|||
<QItemSection>
|
||||
<VnSelectSupplier
|
||||
:label="t('Carrier')"
|
||||
:fields="['id', 'nickname']"
|
||||
v-model="params.supplierFk"
|
||||
dense
|
||||
outlined
|
||||
|
|
|
@ -49,7 +49,7 @@ watch(
|
|||
<FetchData
|
||||
@on-fetch="(data) => (listPackagingsOptions = data)"
|
||||
auto-load
|
||||
:filter="{ fields: ['packagingFk', 'name'], order: 'name ASC', limit: 30 }"
|
||||
:filter="{ fields: ['packagingFk', 'name'], order: 'name ASC' }"
|
||||
url="Packagings/listPackaging"
|
||||
/>
|
||||
<div class="flex justify-center">
|
||||
|
|
|
@ -3,11 +3,46 @@ describe('Client consignee', () => {
|
|||
beforeEach(() => {
|
||||
cy.viewport(1280, 720);
|
||||
cy.login('developer');
|
||||
cy.visit('#/customer/1110/address', {
|
||||
timeout: 5000,
|
||||
});
|
||||
cy.visit('#/customer/1107/address');
|
||||
cy.domContentLoad();
|
||||
});
|
||||
it('Should load layout', () => {
|
||||
cy.get('.q-card').should('be.visible');
|
||||
});
|
||||
|
||||
it('check as equalizated', function () {
|
||||
cy.get('.q-card__section > .address-card').then(($el) => {
|
||||
let addressCards_before = $el.length;
|
||||
|
||||
cy.get('.q-page-sticky > div > .q-btn').click();
|
||||
const addressName = 'test';
|
||||
cy.dataCy('Consignee_input').type(addressName);
|
||||
cy.dataCy('Location_select').click();
|
||||
cy.get('[role="listbox"] .q-item:nth-child(1)').click();
|
||||
cy.dataCy('Street address_input').type('TEST ADDRESS');
|
||||
cy.get('.q-btn-group > .q-btn--standard').click();
|
||||
cy.location('href').should('contain', '#/customer/1107/address');
|
||||
cy.get('.q-card__section > .address-card').should(
|
||||
'have.length',
|
||||
addressCards_before + 1,
|
||||
);
|
||||
cy.get('.q-card__section > .address-card')
|
||||
.eq(addressCards_before)
|
||||
.should('be.visible')
|
||||
.get('.text-weight-bold')
|
||||
.eq(addressCards_before - 1)
|
||||
.should('contain', addressName)
|
||||
.click();
|
||||
});
|
||||
cy.get(
|
||||
'.q-card > :nth-child(1) > :nth-child(2) > .q-checkbox > .q-checkbox__inner',
|
||||
)
|
||||
.should('have.class', 'q-checkbox__inner--falsy')
|
||||
.click();
|
||||
|
||||
cy.get('.q-btn-group > .q-btn--standard > .q-btn__content').click();
|
||||
cy.get(
|
||||
':nth-child(2) > :nth-child(2) > .flex > .q-mr-lg > .q-checkbox__inner',
|
||||
).should('have.class', 'q-checkbox__inner--truthy');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,9 +3,8 @@ describe('Client fiscal data', () => {
|
|||
beforeEach(() => {
|
||||
cy.viewport(1280, 720);
|
||||
cy.login('developer');
|
||||
cy.visit('#/customer/1107/fiscal-data', {
|
||||
timeout: 5000,
|
||||
});
|
||||
cy.visit('#/customer/1107/fiscal-data');
|
||||
cy.domContentLoad();
|
||||
});
|
||||
it('Should change required value when change customer', () => {
|
||||
cy.get('.q-card').should('be.visible');
|
||||
|
@ -15,4 +14,25 @@ describe('Client fiscal data', () => {
|
|||
cy.get('.q-item > .q-item__label').should('have.text', ' #1');
|
||||
cy.dataCy('sageTaxTypeFk').filter('input').should('have.attr', 'required');
|
||||
});
|
||||
|
||||
it('check as equalizated', () => {
|
||||
cy.get(
|
||||
':nth-child(1) > .q-checkbox > .q-checkbox__inner > .q-checkbox__bg',
|
||||
).click();
|
||||
cy.get('.q-btn-group > .q-btn--standard > .q-btn__content').click();
|
||||
|
||||
cy.get('.q-card > :nth-child(1) > span').should(
|
||||
'contain',
|
||||
'You changed the equalization tax',
|
||||
);
|
||||
|
||||
cy.get('.q-card > :nth-child(2) > span').should(
|
||||
'have.text',
|
||||
'Do you want to spread the change?',
|
||||
);
|
||||
cy.get('[data-cy="VnConfirm_confirm"] > .q-btn__content > .block').click();
|
||||
cy.get(
|
||||
'.bg-warning > .q-notification__wrapper > .q-notification__content > .q-notification__message',
|
||||
).should('have.text', 'Equivalent tax spreaded');
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue