Merge branch 'dev' into 8606-FixZoneModule
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
This commit is contained in:
commit
a2bb7c44f3
3095
CHANGELOG.md
3095
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
|
@ -134,7 +134,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(
|
||||
|
@ -154,7 +155,7 @@ onMounted(async () => {
|
|||
if (!$props.url)
|
||||
watch(
|
||||
() => arrayData.store.data,
|
||||
(val) => updateAndEmit('onFetch', val),
|
||||
(val) => updateAndEmit('onFetch', { val }),
|
||||
);
|
||||
|
||||
watch(
|
||||
|
@ -200,7 +201,7 @@ async function fetch() {
|
|||
});
|
||||
if (Array.isArray(data)) data = data[0] ?? {};
|
||||
|
||||
updateAndEmit('onFetch', data);
|
||||
updateAndEmit('onFetch', { val: data });
|
||||
} catch (e) {
|
||||
state.set(modelValue, {});
|
||||
throw e;
|
||||
|
@ -228,7 +229,11 @@ async function save(prevent = false) {
|
|||
|
||||
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 {
|
||||
|
@ -242,8 +247,7 @@ async function saveAndGo() {
|
|||
}
|
||||
|
||||
function reset() {
|
||||
formData.value = JSON.parse(JSON.stringify(originalData.value));
|
||||
updateAndEmit('onFetch', originalData.value);
|
||||
updateAndEmit('onFetch', { val: originalData.value });
|
||||
if ($props.observeFormChanges) {
|
||||
hasChanges.value = false;
|
||||
isResetting.value = true;
|
||||
|
@ -265,11 +269,11 @@ function filter(value, update, filterOptions) {
|
|||
);
|
||||
}
|
||||
|
||||
function updateAndEmit(evt, val, res) {
|
||||
function updateAndEmit(evt, { val, res, old } = { val: null, res: null, old: null }) {
|
||||
state.set(modelValue, 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>
|
||||
|
@ -10,7 +12,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
|
||||
|
|
|
@ -353,14 +353,14 @@ const clickHandler = async (event) => {
|
|||
const column = $props.columns.find((col) => col.name === colField);
|
||||
|
||||
if (editingRow.value !== null && editingField.value !== null) {
|
||||
if (editingRow.value === rowIndex && editingField.value === colField) {
|
||||
return;
|
||||
}
|
||||
if (editingRow.value == rowIndex && editingField.value == colField) return;
|
||||
|
||||
destroyInput(editingRow.value, editingField.value);
|
||||
}
|
||||
if (isEditableColumn(column))
|
||||
|
||||
if (isEditableColumn(column)) {
|
||||
await renderInput(Number(rowIndex), colField, clickedElement);
|
||||
}
|
||||
};
|
||||
|
||||
async function handleTabKey(event, rowIndex, colField) {
|
||||
|
@ -492,9 +492,7 @@ async function handleTabNavigation(rowIndex, colName, direction) {
|
|||
if (isEditableColumn(columns[newColumnIndex])) break;
|
||||
} while (iterations < totalColumns);
|
||||
|
||||
if (iterations >= totalColumns) {
|
||||
return;
|
||||
}
|
||||
if (iterations >= totalColumns + 1) return;
|
||||
|
||||
if (direction === 1 && newColumnIndex <= currentColumnIndex) {
|
||||
rowIndex++;
|
||||
|
@ -632,6 +630,7 @@ function cardClick(_, row) {
|
|||
<template #header-cell="{ col }">
|
||||
<QTh
|
||||
v-if="col.visible ?? true"
|
||||
v-bind:class="col.headerClass"
|
||||
class="body-cell"
|
||||
:style="col?.width ? `max-width: ${col?.width}` : ''"
|
||||
style="padding: inherit"
|
||||
|
@ -758,7 +757,7 @@ function cardClick(_, row) {
|
|||
flat
|
||||
dense
|
||||
:class="
|
||||
btn.isPrimary ? 'text-primary-light' : 'color-vn-text '
|
||||
btn.isPrimary ? 'text-primary-light' : 'color-vn-label'
|
||||
"
|
||||
:style="`visibility: ${
|
||||
((btn.show && btn.show(row)) ?? true)
|
||||
|
@ -766,6 +765,7 @@ function cardClick(_, row) {
|
|||
: 'hidden'
|
||||
}`"
|
||||
@click="btn.action(row)"
|
||||
:data-cy="btn?.name ?? `tableAction-${index}`"
|
||||
/>
|
||||
</QTd>
|
||||
</template>
|
||||
|
@ -783,7 +783,7 @@ function cardClick(_, row) {
|
|||
<QCardSection
|
||||
vertical
|
||||
class="no-margin no-padding"
|
||||
:class="colsMap.tableActions ? 'w-80' : 'fit'"
|
||||
:class="colsMap.tableActions ? '' : 'fit'"
|
||||
>
|
||||
<!-- Chips -->
|
||||
<QCardSection
|
||||
|
@ -814,7 +814,7 @@ function cardClick(_, row) {
|
|||
</QCardSection>
|
||||
<!-- Fields -->
|
||||
<QCardSection
|
||||
class="q-pl-sm q-pr-lg q-py-xs"
|
||||
class="q-pl-sm q-py-xs"
|
||||
:class="$props.cardClass"
|
||||
>
|
||||
<div
|
||||
|
@ -822,11 +822,11 @@ function cardClick(_, row) {
|
|||
col, index
|
||||
) of splittedColumns.cardVisible"
|
||||
:key="col.name"
|
||||
class="fields"
|
||||
>
|
||||
<VnLv :label="col.label + ':'">
|
||||
<template #value>
|
||||
<span
|
||||
class="q-pl-xs"
|
||||
@click="stopEventPropagation($event)"
|
||||
>
|
||||
<slot
|
||||
|
@ -862,12 +862,12 @@ function cardClick(_, row) {
|
|||
:title="btn.title"
|
||||
:icon="btn.icon"
|
||||
class="q-pa-xs"
|
||||
flat
|
||||
:class="
|
||||
btn.isPrimary
|
||||
? 'text-primary-light'
|
||||
: 'color-vn-text '
|
||||
: 'color-vn-label'
|
||||
"
|
||||
flat
|
||||
@click="btn.action(row)"
|
||||
/>
|
||||
</QCardSection>
|
||||
|
@ -1046,7 +1046,7 @@ es:
|
|||
.grid-three {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, max-content));
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
grid-gap: 20px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
@ -1120,6 +1120,7 @@ es:
|
|||
.vn-label-value {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
color: var(--vn-text-color);
|
||||
.value {
|
||||
overflow: hidden;
|
||||
|
|
|
@ -39,6 +39,13 @@ onBeforeMount(async () => {
|
|||
});
|
||||
|
||||
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 });
|
||||
}
|
||||
}
|
||||
const id = to.params.id;
|
||||
if (id !== from.params.id) await fetch(id, true);
|
||||
});
|
||||
|
@ -50,6 +57,9 @@ async function fetch(id, append = false) {
|
|||
else arrayData.store.url = props.url.replace(regex, `/${id}`);
|
||||
await arrayData.fetch({ append, 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
|
||||
|
|
|
@ -53,3 +53,8 @@ const manaCode = ref(props.manaCode);
|
|||
/>
|
||||
</div>
|
||||
</template>
|
||||
<i18n>
|
||||
es:
|
||||
Promotion mana: Maná promoción
|
||||
Claim mana: Maná reclamación
|
||||
</i18n>
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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 {
|
||||
|
|
|
@ -830,6 +830,8 @@ travel:
|
|||
CloneTravelAndEntries: Clone travel and his entries
|
||||
deleteTravel: Delete travel
|
||||
AddEntry: Add entry
|
||||
availabled: Availabled
|
||||
availabledHour: Availabled hour
|
||||
thermographs: Thermographs
|
||||
hb: HB
|
||||
basicData:
|
||||
|
|
|
@ -839,6 +839,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
|
||||
|
@ -916,6 +917,8 @@ travel:
|
|||
deleteTravel: Eliminar envío
|
||||
AddEntry: Añadir entrada
|
||||
thermographs: Termógrafos
|
||||
availabled: F. Disponible
|
||||
availabledHour: Hora Disponible
|
||||
hb: HB
|
||||
basicData:
|
||||
daysInForward: Desplazamiento automatico (redada)
|
||||
|
|
|
@ -158,7 +158,7 @@ onMounted(() => {
|
|||
>
|
||||
<QItemSection>{{ t('globals.delete') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-if="hasSysadminAccess" v-ripple clickable>
|
||||
<QItem v-if="hasSysadminAccess || isHimself" v-ripple clickable>
|
||||
<QItemSection @click="onChangePass(isHimself)">
|
||||
{{ isHimself ? t('globals.changePass') : t('globals.setPass') }}
|
||||
</QItemSection>
|
||||
|
|
|
@ -156,7 +156,6 @@ function onDrag() {
|
|||
url="Claims"
|
||||
:filter="claimDmsFilter"
|
||||
@on-fetch="([data]) => setClaimDms(data)"
|
||||
limit="20"
|
||||
auto-load
|
||||
ref="claimDmsRef"
|
||||
/>
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -232,7 +232,6 @@ const updateDateParams = (value, params) => {
|
|||
:include="'category'"
|
||||
:sortBy="'name ASC'"
|
||||
dense
|
||||
@update:model-value="(data) => updateDateParams(data, params)"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
|
@ -254,7 +253,6 @@ const updateDateParams = (value, params) => {
|
|||
:fields="['id', 'name']"
|
||||
:sortBy="'name ASC'"
|
||||
dense
|
||||
@update:model-value="(data) => updateDateParams(data, params)"
|
||||
/>
|
||||
<VnSelect
|
||||
v-model="params.campaign"
|
||||
|
@ -303,12 +301,14 @@ en:
|
|||
valentinesDay: Valentine's Day
|
||||
mothersDay: Mother's Day
|
||||
allSaints: All Saints' Day
|
||||
frenchMothersDay: Mother's Day in France
|
||||
es:
|
||||
Enter a new search: Introduce una nueva búsqueda
|
||||
Group by items: Agrupar por artículos
|
||||
valentinesDay: Día de San Valentín
|
||||
mothersDay: Día de la Madre
|
||||
allSaints: Día de Todos los Santos
|
||||
frenchMothersDay: (Francia) Día de la Madre
|
||||
Campaign consumption: Consumo campaña
|
||||
Campaign: Campaña
|
||||
From: Desde
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
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';
|
||||
|
@ -11,9 +14,12 @@ import VnSelect from 'src/components/common/VnSelect.vue';
|
|||
import VnLocation from 'src/components/common/VnLocation.vue';
|
||||
import VnCheckbox from 'src/components/common/VnCheckbox.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([]);
|
||||
|
@ -31,6 +37,31 @@ function onBeforeSave(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>
|
||||
|
@ -45,6 +76,8 @@ function onBeforeSave(formData, originalData) {
|
|||
auto-load
|
||||
model="Customer"
|
||||
:mapper="onBeforeSave"
|
||||
observe-form-changes
|
||||
@on-data-saved="checkEtChanges"
|
||||
>
|
||||
<template #form="{ data, validate }">
|
||||
<VnRow>
|
||||
|
@ -180,6 +213,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)"
|
||||
/>
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
@ -137,15 +137,12 @@ async function handleDialog(data) {
|
|||
.onOk(async () => {
|
||||
await updateAddressTicket();
|
||||
await updateAll(body);
|
||||
toCustomerAddress();
|
||||
})
|
||||
.onCancel(async () => {
|
||||
await updateAll(body);
|
||||
toCustomerAddress();
|
||||
});
|
||||
} else {
|
||||
updateAll(body);
|
||||
toCustomerAddress();
|
||||
await updateAll(body);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -209,13 +209,14 @@ const columns = [
|
|||
row['amount'] = row['quantity'] * row['buyingValue'];
|
||||
},
|
||||
},
|
||||
width: '20px',
|
||||
width: '30px',
|
||||
style: (row) => {
|
||||
if (row.groupingMode === 'grouping')
|
||||
return { color: 'var(--vn-label-color)' };
|
||||
},
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
labelAbbreviation: 'GM',
|
||||
label: t('Grouping selector'),
|
||||
toolTip: t('Grouping selector'),
|
||||
|
@ -249,7 +250,7 @@ const columns = [
|
|||
toolTip: 'Grouping',
|
||||
name: 'grouping',
|
||||
component: 'number',
|
||||
width: '20px',
|
||||
width: '30px',
|
||||
create: true,
|
||||
style: (row) => {
|
||||
if (row.groupingMode === 'packing') return { color: 'var(--vn-label-color)' };
|
||||
|
@ -508,7 +509,7 @@ async function setBuyUltimate(itemFk, data) {
|
|||
|
||||
allowedKeys.forEach((key) => {
|
||||
if (buyUltimateData.hasOwnProperty(key) && key !== 'entryFk') {
|
||||
data[key] = buyUltimateData[key];
|
||||
if (!['stickers', 'quantity'].includes(key)) data[key] = buyUltimateData[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -600,7 +601,6 @@ onMounted(() => {
|
|||
ref="entryBuysRef"
|
||||
data-key="EntryBuys"
|
||||
:url="`Entries/${entityId}/getBuyList`"
|
||||
order="name DESC"
|
||||
save-url="Buys/crud"
|
||||
:disable-option="{ card: true }"
|
||||
v-model:selected="selectedRows"
|
||||
|
@ -644,7 +644,8 @@ onMounted(() => {
|
|||
:is-editable="editableMode"
|
||||
:without-header="!editableMode"
|
||||
:with-filters="editableMode"
|
||||
:right-search="editableMode"
|
||||
:right-search="false"
|
||||
:right-search-icon="false"
|
||||
:row-click="false"
|
||||
:columns="columns"
|
||||
:beforeSaveFn="beforeSave"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -44,28 +44,32 @@ const entryQueryFilter = {
|
|||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
label: 'Ex',
|
||||
labelAbbreviation: 'Ex',
|
||||
label: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
|
||||
toolTip: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
|
||||
name: 'isExcludedFromAvailable',
|
||||
component: 'checkbox',
|
||||
width: '35px',
|
||||
},
|
||||
{
|
||||
label: 'Pe',
|
||||
labelAbbreviation: 'Pe',
|
||||
label: t('entry.list.tableVisibleColumns.isOrdered'),
|
||||
toolTip: t('entry.list.tableVisibleColumns.isOrdered'),
|
||||
name: 'isOrdered',
|
||||
component: 'checkbox',
|
||||
width: '35px',
|
||||
},
|
||||
{
|
||||
label: 'Le',
|
||||
labelAbbreviation: 'LE',
|
||||
label: t('entry.list.tableVisibleColumns.isConfirmed'),
|
||||
toolTip: t('entry.list.tableVisibleColumns.isConfirmed'),
|
||||
name: 'isConfirmed',
|
||||
component: 'checkbox',
|
||||
width: '35px',
|
||||
},
|
||||
{
|
||||
label: 'Re',
|
||||
labelAbbreviation: 'Re',
|
||||
label: t('entry.list.tableVisibleColumns.isReceived'),
|
||||
toolTip: t('entry.list.tableVisibleColumns.isReceived'),
|
||||
name: 'isReceived',
|
||||
component: 'checkbox',
|
||||
|
@ -89,6 +93,7 @@ const columns = computed(() => [
|
|||
chip: {
|
||||
condition: () => true,
|
||||
},
|
||||
width: '50px',
|
||||
},
|
||||
{
|
||||
label: t('entry.list.tableVisibleColumns.supplierFk'),
|
||||
|
@ -99,8 +104,10 @@ const columns = computed(() => [
|
|||
attrs: {
|
||||
url: 'suppliers',
|
||||
fields: ['id', 'name'],
|
||||
where: { order: 'name DESC' },
|
||||
},
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.supplierName),
|
||||
width: '110px',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
|
@ -124,6 +131,7 @@ const columns = computed(() => [
|
|||
label: 'AWB',
|
||||
name: 'awbCode',
|
||||
component: 'input',
|
||||
width: '100px',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
|
@ -160,6 +168,7 @@ const columns = computed(() => [
|
|||
component: null,
|
||||
},
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseOutName),
|
||||
width: '65px',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
|
@ -175,12 +184,24 @@ const columns = computed(() => [
|
|||
component: null,
|
||||
},
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseInName),
|
||||
width: '65px',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
labelAbbreviation: t('Type'),
|
||||
label: t('entry.list.tableVisibleColumns.entryTypeDescription'),
|
||||
toolTip: t('entry.list.tableVisibleColumns.entryTypeDescription'),
|
||||
name: 'entryTypeCode',
|
||||
component: 'select',
|
||||
attrs: {
|
||||
url: 'entryTypes',
|
||||
fields: ['code', 'description'],
|
||||
optionValue: 'code',
|
||||
optionLabel: 'description',
|
||||
},
|
||||
cardVisible: true,
|
||||
width: '65px',
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.entryTypeDescription),
|
||||
},
|
||||
{
|
||||
name: 'companyFk',
|
||||
|
@ -320,4 +341,5 @@ es:
|
|||
Search entries: Buscar entradas
|
||||
You can search by entry reference: Puedes buscar por referencia de la entrada
|
||||
Create entry: Crear entrada
|
||||
Type: Tipo
|
||||
</i18n>
|
||||
|
|
|
@ -34,18 +34,20 @@ const columns = computed(() => [
|
|||
label: t('entryStockBought.buyer'),
|
||||
isTitle: true,
|
||||
component: 'select',
|
||||
isEditable: false,
|
||||
cardVisible: true,
|
||||
create: true,
|
||||
attrs: {
|
||||
url: 'Workers/activeWithInheritedRole',
|
||||
fields: ['id', 'name'],
|
||||
fields: ['id', 'name', 'nickname'],
|
||||
where: { role: 'buyer' },
|
||||
optionFilter: 'firstName',
|
||||
optionLabel: 'name',
|
||||
optionLabel: 'nickname',
|
||||
optionValue: 'id',
|
||||
useLike: false,
|
||||
},
|
||||
columnFilter: false,
|
||||
width: '70px',
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
|
@ -55,6 +57,7 @@ const columns = computed(() => [
|
|||
create: true,
|
||||
component: 'number',
|
||||
summation: true,
|
||||
width: '60px',
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
|
@ -78,6 +81,7 @@ const columns = computed(() => [
|
|||
actions: [
|
||||
{
|
||||
title: t('entryStockBought.viewMoreDetails'),
|
||||
name: 'searchBtn',
|
||||
icon: 'search',
|
||||
isPrimary: true,
|
||||
action: (row) => {
|
||||
|
@ -91,6 +95,7 @@ const columns = computed(() => [
|
|||
},
|
||||
},
|
||||
],
|
||||
'data-cy': 'table-actions',
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -158,7 +163,7 @@ function round(value) {
|
|||
@on-fetch="
|
||||
(data) => {
|
||||
travel = data.find(
|
||||
(data) => data.warehouseIn?.code.toLowerCase() === 'vnh'
|
||||
(data) => data.warehouseIn?.code.toLowerCase() === 'vnh',
|
||||
);
|
||||
}
|
||||
"
|
||||
|
@ -179,6 +184,7 @@ function round(value) {
|
|||
@click="openDialog()"
|
||||
:title="t('entryStockBought.editTravel')"
|
||||
color="primary"
|
||||
data-cy="edit-travel"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
|
@ -239,10 +245,11 @@ function round(value) {
|
|||
table-height="80vh"
|
||||
auto-load
|
||||
:column-search="false"
|
||||
:without-header="true"
|
||||
>
|
||||
<template #column-workerFk="{ row }">
|
||||
<span class="link" @click.stop>
|
||||
{{ row?.worker?.user?.name }}
|
||||
{{ row?.worker?.user?.nickname }}
|
||||
<WorkerDescriptorProxy :id="row?.workerFk" />
|
||||
</span>
|
||||
</template>
|
||||
|
@ -279,10 +286,11 @@ function round(value) {
|
|||
justify-content: center;
|
||||
}
|
||||
.column {
|
||||
min-width: 30%;
|
||||
margin-top: 5%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-width: 35%;
|
||||
}
|
||||
.text-negative {
|
||||
color: $negative !important;
|
||||
|
|
|
@ -21,7 +21,7 @@ const $props = defineProps({
|
|||
const customUrl = `StockBoughts/getStockBoughtDetail?workerFk=${$props.workerFk}&dated=${$props.dated}`;
|
||||
const columns = [
|
||||
{
|
||||
align: 'left',
|
||||
align: 'right',
|
||||
label: t('Entry'),
|
||||
name: 'entryFk',
|
||||
isTitle: true,
|
||||
|
@ -29,7 +29,7 @@ const columns = [
|
|||
columnFilter: false,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
align: 'right',
|
||||
name: 'itemFk',
|
||||
label: t('Item'),
|
||||
columnFilter: false,
|
||||
|
@ -44,21 +44,21 @@ const columns = [
|
|||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
align: 'right',
|
||||
name: 'volume',
|
||||
label: t('Volume'),
|
||||
columnFilter: false,
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
align: 'right',
|
||||
label: t('Packaging'),
|
||||
name: 'packagingFk',
|
||||
columnFilter: false,
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
align: 'right',
|
||||
label: 'Packing',
|
||||
name: 'packing',
|
||||
columnFilter: false,
|
||||
|
@ -73,12 +73,14 @@ const columns = [
|
|||
ref="tableRef"
|
||||
data-key="StockBoughtsDetail"
|
||||
:url="customUrl"
|
||||
order="itemName DESC"
|
||||
order="volume DESC"
|
||||
:columns="columns"
|
||||
:right-search="false"
|
||||
:disable-infinite-scroll="true"
|
||||
:disable-option="{ card: true }"
|
||||
:limit="0"
|
||||
:without-header="true"
|
||||
:with-filters="false"
|
||||
auto-load
|
||||
>
|
||||
<template #column-entryFk="{ row }">
|
||||
|
@ -105,7 +107,7 @@ const columns = [
|
|||
align-items: center;
|
||||
margin: auto;
|
||||
background-color: var(--vn-section-color);
|
||||
padding: 4px;
|
||||
padding: 2%;
|
||||
}
|
||||
.container > div > div > .q-table__top.relative-position.row.items-center {
|
||||
background-color: red !important;
|
||||
|
|
|
@ -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';
|
||||
|
@ -22,7 +21,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 } };
|
||||
|
@ -41,10 +39,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',
|
||||
|
@ -82,12 +79,6 @@ onBeforeMount(async () => {
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
url="Accountings"
|
||||
auto-load
|
||||
limit="30"
|
||||
@on-fetch="(data) => (banks = data)"
|
||||
/>
|
||||
<CrudModel
|
||||
v-if="invoiceIn"
|
||||
ref="invoiceInFormRef"
|
||||
|
@ -117,9 +108,9 @@ onBeforeMount(async () => {
|
|||
<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">
|
||||
|
@ -193,8 +184,7 @@ onBeforeMount(async () => {
|
|||
: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)" />
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -48,7 +48,6 @@ const onFetch = (data) => {
|
|||
},
|
||||
],
|
||||
}"
|
||||
limit="30"
|
||||
@on-fetch="onFetch"
|
||||
/>
|
||||
<div :class="[isDialog ? 'column' : 'form-gap', 'full-width flex']">
|
||||
|
|
|
@ -18,6 +18,7 @@ const onSave = (data, response) => {
|
|||
<template>
|
||||
<FormModel
|
||||
:update-url="`Roadmaps/${$route.params?.id}`"
|
||||
:url="`Roadmaps/${$route.params?.id}`"
|
||||
observe-form-changes
|
||||
model="Roadmap"
|
||||
auto-load
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -47,7 +47,10 @@ const cancel = () => {
|
|||
<div v-else>
|
||||
<div class="header">Mana: {{ toCurrency(mana) }}</div>
|
||||
<div class="q-pa-md">
|
||||
<slot />
|
||||
<slot :popup="QPopupProxyRef" />
|
||||
<div v-if="usesMana" class="column q-gutter-y-sm q-mt-sm">
|
||||
<VnUsesMana :mana-code="manaCode" />
|
||||
</div>
|
||||
<div v-if="newPrice" class="column items-center q-mt-lg">
|
||||
<span class="text-primary">{{ t('New price') }}</span>
|
||||
<span class="text-subtitle1">
|
||||
|
@ -56,9 +59,6 @@ const cancel = () => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="usesMana" class="column q-gutter-y-sm q-mt-sm">
|
||||
<VnUsesMana :mana-code="manaCode" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<QBtn
|
||||
color="primary"
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -133,7 +133,7 @@ const columns = computed(() => [
|
|||
align: 'left',
|
||||
label: t('globals.amount'),
|
||||
name: 'amount',
|
||||
format: (row) => parseInt(row.amount * row.quantity),
|
||||
format: (row) => toCurrency(getSaleTotal(row)),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
|
@ -331,8 +331,7 @@ const updateDiscount = async (sales, newDiscount = null) => {
|
|||
};
|
||||
await axios.post(`Tickets/${route.params.id}/updateDiscount`, params);
|
||||
notify('globals.dataSaved', 'positive');
|
||||
for (let sale of sales) sale.discount = _newDiscount;
|
||||
edit.value = { ...DEFAULT_EDIT };
|
||||
tableRef.value.reload();
|
||||
};
|
||||
|
||||
const getNewPrice = computed(() => {
|
||||
|
@ -789,21 +788,24 @@ watch(
|
|||
:mana-code="manaCode"
|
||||
@save="changeDiscount(row)"
|
||||
>
|
||||
<VnInput
|
||||
v-model.number="edit.discount"
|
||||
:label="t('ticketSale.discount')"
|
||||
type="number"
|
||||
/>
|
||||
<div v-if="usesMana" class="column q-gutter-y-sm q-mt-sm">
|
||||
<VnUsesMana :mana-code="manaCode" />
|
||||
</div>
|
||||
<template #default="{ popup }">
|
||||
<VnInput
|
||||
autofocus
|
||||
@keyup.enter="
|
||||
() => {
|
||||
changeDiscount(row);
|
||||
popup.hide();
|
||||
}
|
||||
"
|
||||
v-model.number="edit.discount"
|
||||
:label="t('ticketSale.discount')"
|
||||
type="number"
|
||||
/>
|
||||
</template>
|
||||
</TicketEditManaProxy>
|
||||
</template>
|
||||
<span v-else>{{ toPercentage(row.discount / 100) }}</span>
|
||||
</template>
|
||||
<template #column-amount="{ row }">
|
||||
{{ toCurrency(row.quantity * row.price) }}
|
||||
</template>
|
||||
</VnTable>
|
||||
|
||||
<QPageSticky :offset="[20, 20]" style="z-index: 2">
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
<script setup>
|
||||
import { onMounted, ref, computed, reactive } from 'vue';
|
||||
import { ref, computed, reactive, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
|
||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
import TicketFutureFilter from './TicketFutureFilter.vue';
|
||||
|
||||
import { dashIfEmpty, toCurrency } from 'src/filters';
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
import { useArrayData } from 'composables/useArrayData';
|
||||
import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { useState } from 'src/composables/useState';
|
||||
|
@ -26,214 +23,126 @@ const { openConfirmationModal } = useVnConfirm();
|
|||
const { notify } = useNotify();
|
||||
const user = state.getUser();
|
||||
|
||||
const itemPackingTypesOptions = ref([]);
|
||||
const selectedTickets = ref([]);
|
||||
|
||||
const exprBuilder = (param, value) => {
|
||||
switch (param) {
|
||||
case 'id':
|
||||
return { id: value };
|
||||
case 'futureId':
|
||||
return { futureId: value };
|
||||
case 'liters':
|
||||
return { liters: value };
|
||||
case 'lines':
|
||||
return { lines: value };
|
||||
case 'iptColFilter':
|
||||
return { ipt: { like: `%${value}%` } };
|
||||
case 'futureIptColFilter':
|
||||
return { futureIpt: { like: `%${value}%` } };
|
||||
case 'totalWithVat':
|
||||
return { totalWithVat: value };
|
||||
}
|
||||
};
|
||||
|
||||
const vnTableRef = ref({});
|
||||
const originElRef = ref(null);
|
||||
const destinationElRef = ref(null);
|
||||
const userParams = reactive({
|
||||
futureScopeDays: Date.vnNew().toISOString(),
|
||||
originScopeDays: Date.vnNew().toISOString(),
|
||||
warehouseFk: user.value.warehouseFk,
|
||||
});
|
||||
|
||||
const arrayData = useArrayData('FutureTickets', {
|
||||
url: 'Tickets/getTicketsFuture',
|
||||
userParams: userParams,
|
||||
exprBuilder: exprBuilder,
|
||||
});
|
||||
const { store } = arrayData;
|
||||
|
||||
const params = reactive({
|
||||
futureScopeDays: Date.vnNew(),
|
||||
originScopeDays: Date.vnNew(),
|
||||
warehouseFk: user.value.warehouseFk,
|
||||
});
|
||||
|
||||
const applyColumnFilter = async (col) => {
|
||||
const paramKey = col.columnFilter?.filterParamKey || col.field;
|
||||
params[paramKey] = col.columnFilter.filterValue;
|
||||
await arrayData.addFilter({ params });
|
||||
};
|
||||
|
||||
const getInputEvents = (col) => {
|
||||
return col.columnFilter.type === 'select'
|
||||
? { 'update:modelValue': () => applyColumnFilter(col) }
|
||||
: {
|
||||
'keyup.enter': () => applyColumnFilter(col),
|
||||
};
|
||||
};
|
||||
|
||||
const tickets = computed(() => store.data);
|
||||
|
||||
const ticketColumns = computed(() => [
|
||||
{
|
||||
label: t('futureTickets.problems'),
|
||||
label: '',
|
||||
name: 'problems',
|
||||
headerClass: 'horizontal-separator',
|
||||
align: 'left',
|
||||
columnFilter: null,
|
||||
columnFilter: false,
|
||||
},
|
||||
{
|
||||
label: t('advanceTickets.ticketId'),
|
||||
name: 'ticketId',
|
||||
name: 'id',
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
filterParamKey: 'id',
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
headerClass: 'horizontal-separator',
|
||||
},
|
||||
{
|
||||
label: t('futureTickets.shipped'),
|
||||
name: 'shipped',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: null,
|
||||
columnFilter: false,
|
||||
headerClass: 'horizontal-separator',
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
class: 'shrink',
|
||||
label: t('advanceTickets.ipt'),
|
||||
name: 'ipt',
|
||||
field: 'ipt',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnSelect,
|
||||
filterParamKey: 'iptColFilter',
|
||||
type: 'select',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
component: 'select',
|
||||
attrs: {
|
||||
options: itemPackingTypesOptions.value,
|
||||
'option-value': 'code',
|
||||
'option-label': 'description',
|
||||
dense: true,
|
||||
url: 'itemPackingTypes',
|
||||
fields: ['code', 'description'],
|
||||
where: { isActive: true },
|
||||
optionValue: 'code',
|
||||
optionLabel: 'description',
|
||||
inWhere: false,
|
||||
},
|
||||
},
|
||||
format: (val) => dashIfEmpty(val),
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.ipt),
|
||||
headerClass: 'horizontal-separator',
|
||||
},
|
||||
{
|
||||
label: t('ticketList.state'),
|
||||
name: 'state',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: null,
|
||||
columnFilter: false,
|
||||
headerClass: 'horizontal-separator',
|
||||
},
|
||||
{
|
||||
label: t('advanceTickets.liters'),
|
||||
name: 'liters',
|
||||
field: 'liters',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
headerClass: 'horizontal-separator',
|
||||
},
|
||||
{
|
||||
label: t('advanceTickets.import'),
|
||||
field: 'import',
|
||||
name: 'import',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
headerClass: 'horizontal-separator',
|
||||
columnFilter: false,
|
||||
format: (row) => toCurrency(row.totalWithVat),
|
||||
},
|
||||
{
|
||||
label: t('futureTickets.availableLines'),
|
||||
name: 'lines',
|
||||
field: 'lines',
|
||||
align: 'center',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
format: (val) => dashIfEmpty(val),
|
||||
headerClass: 'horizontal-separator',
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.lines),
|
||||
},
|
||||
{
|
||||
label: t('advanceTickets.futureId'),
|
||||
name: 'futureId',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnInput,
|
||||
type: 'text',
|
||||
filterValue: null,
|
||||
filterParamKey: 'futureId',
|
||||
event: getInputEvents,
|
||||
attrs: {
|
||||
dense: true,
|
||||
},
|
||||
},
|
||||
align: 'center',
|
||||
headerClass: 'horizontal-separator vertical-separator ',
|
||||
columnClass: 'vertical-separator',
|
||||
},
|
||||
{
|
||||
label: t('futureTickets.futureShipped'),
|
||||
name: 'futureShipped',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: null,
|
||||
format: (val) => dashIfEmpty(val),
|
||||
headerClass: 'horizontal-separator',
|
||||
columnFilter: false,
|
||||
format: (row) => toDateTimeFormat(row.futureShipped),
|
||||
},
|
||||
|
||||
{
|
||||
align: 'center',
|
||||
label: t('advanceTickets.futureIpt'),
|
||||
class: 'shrink',
|
||||
name: 'futureIpt',
|
||||
field: 'futureIpt',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
columnFilter: {
|
||||
component: VnSelect,
|
||||
filterParamKey: 'futureIptColFilter',
|
||||
type: 'select',
|
||||
filterValue: null,
|
||||
event: getInputEvents,
|
||||
component: 'select',
|
||||
attrs: {
|
||||
options: itemPackingTypesOptions.value,
|
||||
'option-value': 'code',
|
||||
'option-label': 'description',
|
||||
dense: true,
|
||||
url: 'itemPackingTypes',
|
||||
fields: ['code', 'description'],
|
||||
where: { isActive: true },
|
||||
optionValue: 'code',
|
||||
optionLabel: 'description',
|
||||
},
|
||||
},
|
||||
format: (val) => dashIfEmpty(val),
|
||||
headerClass: 'horizontal-separator',
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.futureIpt),
|
||||
},
|
||||
{
|
||||
label: t('advanceTickets.futureState'),
|
||||
name: 'futureState',
|
||||
align: 'right',
|
||||
sortable: true,
|
||||
columnFilter: null,
|
||||
format: (val) => dashIfEmpty(val),
|
||||
headerClass: 'horizontal-separator',
|
||||
class: 'expand',
|
||||
columnFilter: false,
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.futureState),
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -258,26 +167,51 @@ const moveTicketsFuture = async () => {
|
|||
await axios.post('Tickets/merge', params);
|
||||
notify(t('advanceTickets.moveTicketSuccess'), 'positive');
|
||||
selectedTickets.value = [];
|
||||
arrayData.fetch({ append: false });
|
||||
vnTableRef.value.reload();
|
||||
};
|
||||
onMounted(async () => {
|
||||
await arrayData.fetch({ append: false });
|
||||
});
|
||||
|
||||
watch(
|
||||
() => vnTableRef.value.tableRef?.$el,
|
||||
($el) => {
|
||||
if (!$el) return;
|
||||
const head = $el.querySelector('thead');
|
||||
const firstRow = $el.querySelector('thead > tr');
|
||||
|
||||
const newRow = document.createElement('tr');
|
||||
destinationElRef.value = document.createElement('th');
|
||||
originElRef.value = document.createElement('th');
|
||||
|
||||
newRow.classList.add('bg-header');
|
||||
destinationElRef.value.classList.add('text-uppercase', 'color-vn-label');
|
||||
originElRef.value.classList.add('text-uppercase', 'color-vn-label');
|
||||
|
||||
destinationElRef.value.setAttribute('colspan', '7');
|
||||
originElRef.value.setAttribute('colspan', '9');
|
||||
|
||||
originElRef.value.textContent = `${t('advanceTickets.origin')}`;
|
||||
destinationElRef.value.textContent = `${t('advanceTickets.destination')}`;
|
||||
|
||||
newRow.append(destinationElRef.value, originElRef.value);
|
||||
head.insertBefore(newRow, firstRow);
|
||||
},
|
||||
{ once: true, inmmediate: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
() => vnTableRef.value.params,
|
||||
() => {
|
||||
if (originElRef.value && destinationElRef.value) {
|
||||
destinationElRef.value.textContent = `${t('advanceTickets.origin')}`;
|
||||
originElRef.value.textContent = `${t('advanceTickets.destination')}`;
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="itemPackingTypes"
|
||||
:filter="{
|
||||
fields: ['code', 'description'],
|
||||
order: 'description ASC',
|
||||
where: { isActive: true },
|
||||
}"
|
||||
auto-load
|
||||
@on-fetch="(data) => (itemPackingTypesOptions = data)"
|
||||
/>
|
||||
<VnSearchbar
|
||||
data-key="FutureTickets"
|
||||
data-key="futureTicket"
|
||||
:label="t('Search ticket')"
|
||||
:info="t('futureTickets.searchInfo')"
|
||||
/>
|
||||
|
@ -293,7 +227,7 @@ onMounted(async () => {
|
|||
t(`futureTickets.moveTicketDialogSubtitle`, {
|
||||
selectedTickets: selectedTickets.length,
|
||||
}),
|
||||
moveTicketsFuture
|
||||
moveTicketsFuture,
|
||||
)
|
||||
"
|
||||
>
|
||||
|
@ -305,77 +239,29 @@ onMounted(async () => {
|
|||
</VnSubToolbar>
|
||||
<RightMenu>
|
||||
<template #right-panel>
|
||||
<TicketFutureFilter data-key="FutureTickets" />
|
||||
<TicketFutureFilter data-key="futureTickets" />
|
||||
</template>
|
||||
</RightMenu>
|
||||
<QPage class="column items-center q-pa-md">
|
||||
<QTable
|
||||
:rows="tickets"
|
||||
<VnTable
|
||||
data-key="futureTickets"
|
||||
ref="vnTableRef"
|
||||
url="Tickets/getTicketsFuture"
|
||||
search-url="futureTickets"
|
||||
:user-params="userParams"
|
||||
:limit="0"
|
||||
:columns="ticketColumns"
|
||||
row-key="id"
|
||||
selection="multiple"
|
||||
:table="{
|
||||
'row-key': '$index',
|
||||
selection: 'multiple',
|
||||
}"
|
||||
v-model:selected="selectedTickets"
|
||||
:pagination="{ rowsPerPage: 0 }"
|
||||
:no-data-label="t('globals.noResults')"
|
||||
style="max-width: 99%"
|
||||
:right-search="false"
|
||||
auto-load
|
||||
:disable-option="{ card: true }"
|
||||
>
|
||||
<template #header="props">
|
||||
<QTr>
|
||||
<QTh class="horizontal-separator" />
|
||||
<QTh
|
||||
class="horizontal-separator text-uppercase color-vn-label"
|
||||
colspan="8"
|
||||
translate
|
||||
>
|
||||
{{ t('advanceTickets.origin') }}
|
||||
</QTh>
|
||||
<QTh
|
||||
class="horizontal-separator text-uppercase color-vn-label"
|
||||
colspan="4"
|
||||
translate
|
||||
>
|
||||
{{ t('advanceTickets.destination') }}
|
||||
</QTh>
|
||||
</QTr>
|
||||
<QTr>
|
||||
<QTh>
|
||||
<QCheckbox v-model="props.selected" />
|
||||
</QTh>
|
||||
<QTh
|
||||
v-for="(col, index) in ticketColumns"
|
||||
:key="index"
|
||||
:class="{ 'vertical-separator': col.name === 'futureId' }"
|
||||
>
|
||||
{{ col.label }}
|
||||
</QTh>
|
||||
</QTr>
|
||||
</template>
|
||||
<template #top-row="{ cols }">
|
||||
<QTr>
|
||||
<QTd />
|
||||
<QTd
|
||||
v-for="(col, index) in cols"
|
||||
:key="index"
|
||||
style="max-width: 100px"
|
||||
>
|
||||
<component
|
||||
:is="col.columnFilter.component"
|
||||
v-if="col.columnFilter"
|
||||
v-model="col.columnFilter.filterValue"
|
||||
v-bind="col.columnFilter.attrs"
|
||||
v-on="col.columnFilter.event(col)"
|
||||
dense
|
||||
/>
|
||||
</QTd>
|
||||
</QTr>
|
||||
</template>
|
||||
<template #header-cell-availableLines="{ col }">
|
||||
<QTh class="vertical-separator">
|
||||
{{ col.label }}
|
||||
</QTh>
|
||||
</template>
|
||||
<template #body-cell-problems="{ row }">
|
||||
<QTd class="q-gutter-x-xs">
|
||||
<template #column-problems="{ row }">
|
||||
<span class="q-gutter-x-xs">
|
||||
<QIcon
|
||||
v-if="row.futureAgencyFk !== row.agencyFk && row.agencyFk"
|
||||
color="primary"
|
||||
|
@ -465,99 +351,87 @@ onMounted(async () => {
|
|||
{{ t('futureTickets.rounding') }}
|
||||
</QTooltip>
|
||||
</QIcon>
|
||||
</QTd>
|
||||
</span>
|
||||
</template>
|
||||
<template #body-cell-ticketId="{ row }">
|
||||
<QTd>
|
||||
<QBtn flat class="link">
|
||||
{{ row.id }}
|
||||
<TicketDescriptorProxy :id="row.id" />
|
||||
</QBtn>
|
||||
</QTd>
|
||||
<template #column-id="{ row }">
|
||||
<QBtn flat class="link" @click.stop dense>
|
||||
{{ row.id }}
|
||||
<TicketDescriptorProxy :id="row.id" />
|
||||
</QBtn>
|
||||
</template>
|
||||
<template #body-cell-shipped="{ row }">
|
||||
<QTd class="shipped">
|
||||
<QBadge
|
||||
text-color="black"
|
||||
:color="getDateQBadgeColor(row.shipped)"
|
||||
class="q-ma-none"
|
||||
>
|
||||
{{ toDateTimeFormat(row.shipped) }}
|
||||
</QBadge>
|
||||
</QTd>
|
||||
<template #column-shipped="{ row }">
|
||||
<QBadge
|
||||
text-color="black"
|
||||
:color="getDateQBadgeColor(row.shipped)"
|
||||
class="q-ma-none"
|
||||
>
|
||||
{{ toDateTimeFormat(row.shipped) }}
|
||||
</QBadge>
|
||||
</template>
|
||||
<template #body-cell-state="{ row }">
|
||||
<QTd>
|
||||
<QBadge
|
||||
text-color="black"
|
||||
:color="row.classColor"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ row.state }}
|
||||
</QBadge>
|
||||
</QTd>
|
||||
<template #column-state="{ row }">
|
||||
<QBadge
|
||||
v-if="row.state"
|
||||
text-color="black"
|
||||
:color="row.classColor"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ row.state }}
|
||||
</QBadge>
|
||||
<span v-else> {{ dashIfEmpty(row.state) }}</span>
|
||||
</template>
|
||||
<template #body-cell-import="{ row }">
|
||||
<QTd>
|
||||
<QBadge
|
||||
:text-color="
|
||||
totalPriceColor(row.totalWithVat) === 'warning'
|
||||
? 'black'
|
||||
: 'white'
|
||||
"
|
||||
:color="totalPriceColor(row.totalWithVat)"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ toCurrency(row.totalWithVat || 0) }}
|
||||
</QBadge>
|
||||
</QTd>
|
||||
<template #column-import="{ row }">
|
||||
<QBadge
|
||||
:text-color="
|
||||
totalPriceColor(row.totalWithVat) === 'warning'
|
||||
? 'black'
|
||||
: 'white'
|
||||
"
|
||||
:color="totalPriceColor(row.totalWithVat)"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ toCurrency(row.totalWithVat || 0) }}
|
||||
</QBadge>
|
||||
</template>
|
||||
<template #body-cell-futureId="{ row }">
|
||||
<QTd class="vertical-separator">
|
||||
<QBtn flat class="link" dense>
|
||||
{{ row.futureId }}
|
||||
<TicketDescriptorProxy :id="row.futureId" />
|
||||
</QBtn>
|
||||
</QTd>
|
||||
<template #column-futureId="{ row }">
|
||||
<QBtn flat class="link" @click.stop dense>
|
||||
{{ row.futureId }}
|
||||
<TicketDescriptorProxy :id="row.futureId" />
|
||||
</QBtn>
|
||||
</template>
|
||||
<template #body-cell-futureShipped="{ row }">
|
||||
<QTd class="shipped">
|
||||
<QBadge
|
||||
text-color="black"
|
||||
:color="getDateQBadgeColor(row.futureShipped)"
|
||||
class="q-ma-none"
|
||||
>
|
||||
{{ toDateTimeFormat(row.futureShipped) }}
|
||||
</QBadge>
|
||||
</QTd>
|
||||
<template #column-futureShipped="{ row }">
|
||||
<QBadge
|
||||
text-color="black"
|
||||
:color="getDateQBadgeColor(row.futureShipped)"
|
||||
class="q-ma-none"
|
||||
>
|
||||
{{ toDateTimeFormat(row.futureShipped) }}
|
||||
</QBadge>
|
||||
</template>
|
||||
<template #body-cell-futureState="{ row }">
|
||||
<QTd>
|
||||
<QBadge
|
||||
text-color="black"
|
||||
:color="row.futureClassColor"
|
||||
class="q-ma-none"
|
||||
dense
|
||||
>
|
||||
{{ row.futureState }}
|
||||
</QBadge>
|
||||
</QTd>
|
||||
<template #column-futureState="{ row }">
|
||||
<QBadge
|
||||
text-color="black"
|
||||
:color="row.futureClassColor"
|
||||
class="q-mr-xs"
|
||||
dense
|
||||
>
|
||||
{{ row.futureState }}
|
||||
</QBadge>
|
||||
</template>
|
||||
</QTable>
|
||||
</VnTable>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.shipped {
|
||||
min-width: 132px;
|
||||
}
|
||||
.vertical-separator {
|
||||
:deep(.vertical-separator) {
|
||||
border-left: 4px solid white !important;
|
||||
}
|
||||
|
||||
.horizontal-separator {
|
||||
:deep(.horizontal-separator) {
|
||||
border-top: 4px solid white !important;
|
||||
}
|
||||
:deep(.horizontal-bottom-separator) {
|
||||
border-bottom: 4px solid white !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -12,7 +12,7 @@ import axios from 'axios';
|
|||
import { onMounted } from 'vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const props = defineProps({
|
||||
defineProps({
|
||||
dataKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
@ -58,7 +58,7 @@ onMounted(async () => {
|
|||
auto-load
|
||||
/>
|
||||
<VnFilterPanel
|
||||
:data-key="props.dataKey"
|
||||
:data-key
|
||||
:un-removable-params="['warehouseFk', 'originScopeDays ', 'futureScopeDays']"
|
||||
>
|
||||
<template #tags="{ tag, formatFn }">
|
||||
|
|
|
@ -9,6 +9,7 @@ import VnRow from 'components/ui/VnRow.vue';
|
|||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||
import VnInputTime from 'components/common/VnInputTime.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
@ -53,7 +54,16 @@ const warehousesOptionsIn = ref([]);
|
|||
<VnInputDate v-model="data.shipped" :label="t('globals.shipped')" />
|
||||
<VnInputDate v-model="data.landed" :label="t('globals.landed')" />
|
||||
</VnRow>
|
||||
|
||||
<VnRow>
|
||||
<VnInputDate
|
||||
v-model="data.availabled"
|
||||
:label="t('travel.summary.availabled')"
|
||||
/>
|
||||
<VnInputTime
|
||||
v-model="data.availabled"
|
||||
:label="t('travel.summary.availabledHour')"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('globals.warehouseOut')"
|
||||
|
@ -101,10 +111,3 @@ const warehousesOptionsIn = ref([]);
|
|||
</template>
|
||||
</FormModel>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
raidDays: El travel se desplaza automáticamente cada día para estar desde hoy al número de días indicado. Si se deja vacio no se moverá
|
||||
en:
|
||||
raidDays: The travel adjusts itself daily to match the number of days set, starting from today. If left blank, it won’t move
|
||||
</i18n>
|
||||
|
|
|
@ -11,6 +11,7 @@ export default {
|
|||
'agencyModeFk',
|
||||
'isRaid',
|
||||
'daysInForward',
|
||||
'availabled',
|
||||
],
|
||||
include: [
|
||||
{
|
||||
|
|
|
@ -10,6 +10,8 @@ import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue'
|
|||
import FetchData from 'src/components/FetchData.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import { toDate, toCurrency, toCelsius } from 'src/filters';
|
||||
import { toDateTimeFormat } from 'src/filters/date.js';
|
||||
import { dashIfEmpty } from 'src/filters';
|
||||
import axios from 'axios';
|
||||
import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
|
||||
|
||||
|
@ -333,6 +335,12 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
|
|||
<VnLv :label="t('globals.reference')" :value="travel.ref" />
|
||||
<VnLv label="m³" :value="travel.m3" />
|
||||
<VnLv :label="t('globals.totalEntries')" :value="travel.totalEntries" />
|
||||
<VnLv
|
||||
:label="t('travel.summary.availabled')"
|
||||
:value="
|
||||
dashIfEmpty(toDateTimeFormat(travel.availabled))
|
||||
"
|
||||
/>
|
||||
</QCard>
|
||||
<QCard class="full-width">
|
||||
<VnTitle :text="t('travel.summary.entries')" />
|
||||
|
|
|
@ -10,6 +10,9 @@ import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js';
|
|||
import TravelFilter from './TravelFilter.vue';
|
||||
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||
import VnSection from 'src/components/common/VnSection.vue';
|
||||
import VnInputTime from 'src/components/common/VnInputTime.vue';
|
||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
import { toDateTimeFormat } from 'src/filters/date';
|
||||
|
||||
const { viewSummary } = useSummaryDialog();
|
||||
const router = useRouter();
|
||||
|
@ -167,6 +170,17 @@ const columns = computed(() => [
|
|||
cardVisible: true,
|
||||
create: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
name: 'availabled',
|
||||
label: t('travel.summary.availabled'),
|
||||
component: 'input',
|
||||
columnClass: 'expand',
|
||||
columnField: {
|
||||
component: null,
|
||||
},
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(toDateTimeFormat(row.availabled)),
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
label: '',
|
||||
|
@ -269,6 +283,16 @@ const columns = computed(() => [
|
|||
:class="{ 'is-active': row.isReceived }"
|
||||
/>
|
||||
</template>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<VnInputDate
|
||||
v-model="data.availabled"
|
||||
:label="t('travel.summary.availabled')"
|
||||
/>
|
||||
<VnInputTime
|
||||
v-model="data.availabled"
|
||||
:label="t('travel.summary.availabledHour')"
|
||||
/>
|
||||
</template>
|
||||
<template #moreFilterPanel="{ params }">
|
||||
<VnInputNumber
|
||||
:label="t('params.scopeDays')"
|
||||
|
|
|
@ -53,7 +53,7 @@ const showChangePasswordDialog = () => {
|
|||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="!worker.user.emailVerified && user.id == worker.id"
|
||||
v-if="!worker.user.emailVerified && user.id != worker.id"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="showChangePasswordDialog"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { computed, ref } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import FormModel from 'src/components/FormModel.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
|
@ -9,33 +9,23 @@ import VnInputTime from 'src/components/common/VnInputTime.vue';
|
|||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const agencyFilter = {
|
||||
fields: ['id', 'name'],
|
||||
order: 'name ASC',
|
||||
limit: 30,
|
||||
};
|
||||
const agencyOptions = ref([]);
|
||||
const validAddresses = ref([]);
|
||||
const addresses = ref([]);
|
||||
|
||||
const filterWhere = computed(() => ({
|
||||
id: { inq: validAddresses.value.map((item) => item.addressFk) },
|
||||
}));
|
||||
const setFilteredAddresses = (data) => {
|
||||
const validIds = new Set(validAddresses.value.map((item) => item.addressFk));
|
||||
addresses.value = data.filter((address) => validIds.has(address.id));
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
:filter="agencyFilter"
|
||||
@on-fetch="(data) => (agencyOptions = data)"
|
||||
auto-load
|
||||
url="AgencyModes/isActive"
|
||||
/>
|
||||
<FetchData
|
||||
url="RoadmapAddresses"
|
||||
auto-load
|
||||
@on-fetch="(data) => (validAddresses = data)"
|
||||
/>
|
||||
<FormModel :url="`Zones/${$route.params.id}`" auto-load data-key="Zone">
|
||||
<FetchData url="Addresses" auto-load @on-fetch="setFilteredAddresses" />
|
||||
<FormModel auto-load model="zone">
|
||||
<template #form="{ data, validate }">
|
||||
<VnRow>
|
||||
<VnInput
|
||||
|
@ -45,7 +35,6 @@ const filterWhere = computed(() => ({
|
|||
v-model="data.name"
|
||||
/>
|
||||
</VnRow>
|
||||
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
v-model="data.agencyModeFk"
|
||||
|
@ -128,7 +117,7 @@ const filterWhere = computed(() => ({
|
|||
v-model="data.addressFk"
|
||||
option-value="id"
|
||||
option-label="nickname"
|
||||
url="Addresses"
|
||||
:options="addresses"
|
||||
:fields="['id', 'nickname']"
|
||||
sort-by="id"
|
||||
hide-selected
|
||||
|
|
|
@ -45,7 +45,6 @@ describe('OrderCatalog', () => {
|
|||
).type('{enter}');
|
||||
cy.get(':nth-child(1) > [data-cy="catalogFilterCategory"]').click();
|
||||
cy.dataCy('catalogFilterValueDialogBtn').last().click();
|
||||
cy.get('[data-cy="catalogFilterValueDialogTagSelect"]').click();
|
||||
cy.selectOption("[data-cy='catalogFilterValueDialogTagSelect']", 'Tallos');
|
||||
cy.dataCy('catalogFilterValueDialogValueInput').find('input').focus();
|
||||
cy.dataCy('catalogFilterValueDialogValueInput').find('input').type('2');
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -106,8 +106,9 @@ describe('Entry', () => {
|
|||
cy.get(`td[data-col-field="${field}"][data-row-index="${row}"]`);
|
||||
const selectSpan = (field, row = 0) => selectCell(field, row).find('div > span');
|
||||
const selectButton = (cySelector) => cy.get(`button[data-cy="${cySelector}"]`);
|
||||
const clickAndType = (field, value, row = 0) =>
|
||||
selectCell(field, row).click().type(value);
|
||||
const clickAndType = (field, value, row = 0) => {
|
||||
selectCell(field, row).click().type(`${value}{esc}`);
|
||||
};
|
||||
const checkText = (field, expectedText, row = 0) =>
|
||||
selectCell(field, row).should('have.text', expectedText);
|
||||
const checkColor = (field, expectedColor, row = 0) =>
|
||||
|
@ -115,21 +116,18 @@ describe('Entry', () => {
|
|||
|
||||
createEntryAndBuy();
|
||||
|
||||
selectCell('isIgnored')
|
||||
.click()
|
||||
.click()
|
||||
.trigger('keydown', { key: 'Tab', keyCode: 9, which: 9 });
|
||||
checkText('isIgnored', 'check');
|
||||
checkColor('quantity', COLORS.negative);
|
||||
selectCell('isIgnored').click().click().type('{esc}');
|
||||
checkText('isIgnored', 'close');
|
||||
|
||||
clickAndType('stickers', '1');
|
||||
checkText('quantity', '11');
|
||||
checkText('amount', '550.00');
|
||||
checkText('stickers', '0/01');
|
||||
checkText('quantity', '1');
|
||||
checkText('amount', '50.00');
|
||||
clickAndType('packing', '2');
|
||||
checkText('packing', '12close');
|
||||
checkText('packing', '12');
|
||||
checkText('weight', '12.0');
|
||||
checkText('quantity', '132');
|
||||
checkText('amount', '6600.00');
|
||||
checkText('quantity', '12');
|
||||
checkText('amount', '600.00');
|
||||
checkColor('packing', COLORS.enabled);
|
||||
|
||||
selectCell('groupingMode').click().click().click();
|
||||
|
@ -137,7 +135,7 @@ describe('Entry', () => {
|
|||
checkColor('grouping', COLORS.enabled);
|
||||
|
||||
selectCell('buyingValue').click().clear().type('{backspace}{backspace}1');
|
||||
checkText('amount', '132.00');
|
||||
checkText('amount', '12.00');
|
||||
checkColor('minPrice', COLORS.disable);
|
||||
|
||||
selectCell('hasMinPrice').click().click();
|
||||
|
@ -145,7 +143,7 @@ describe('Entry', () => {
|
|||
selectCell('hasMinPrice').click();
|
||||
|
||||
cy.saveCard();
|
||||
cy.get('span[data-cy="footer-stickers"]').should('have.text', '11');
|
||||
cy.get('span[data-cy="footer-stickers"]').should('have.text', '1');
|
||||
cy.get('.q-notification__message').contains('Data saved');
|
||||
|
||||
selectButton('change-quantity-sign').should('be.disabled');
|
||||
|
@ -156,9 +154,9 @@ describe('Entry', () => {
|
|||
|
||||
selectButton('change-quantity-sign').click();
|
||||
selectButton('set-negative-quantity').click();
|
||||
checkText('quantity', '-132');
|
||||
checkText('quantity', '-12');
|
||||
selectButton('set-positive-quantity').click();
|
||||
checkText('quantity', '132');
|
||||
checkText('quantity', '12');
|
||||
checkColor('amount', COLORS.disable);
|
||||
|
||||
selectButton('check-buy-amount').click();
|
||||
|
|
|
@ -6,7 +6,7 @@ describe('EntryStockBought', () => {
|
|||
});
|
||||
it('Should edit the reserved space', () => {
|
||||
cy.get('.q-field__native.q-placeholder').should('have.value', '01/01/2001');
|
||||
cy.get('td[data-col-field="reserve"]').click();
|
||||
cy.get('[data-col-field="reserve"][data-row-index="0"]').click();
|
||||
cy.get('input[name="reserve"]').type('10{enter}');
|
||||
cy.get('button[title="Save"]').click();
|
||||
cy.get('.q-notification__message').should('have.text', 'Data saved');
|
||||
|
@ -16,25 +16,35 @@ describe('EntryStockBought', () => {
|
|||
cy.get('input[aria-label="Reserve"]').type('1');
|
||||
cy.get('input[aria-label="Date"]').eq(1).clear();
|
||||
cy.get('input[aria-label="Date"]').eq(1).type('01-01');
|
||||
cy.get('input[aria-label="Buyer"]').type('buyerboss{downarrow}{enter}');
|
||||
cy.get('input[aria-label="Buyer"]').type('buyerBossNick');
|
||||
cy.get('div[role="listbox"] > div > div[role="option"]')
|
||||
.eq(0)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
cy.get('[data-cy="FormModelPopup_save"]').click();
|
||||
cy.get('.q-notification__message').should('have.text', 'Data created');
|
||||
|
||||
cy.get('[data-col-field="reserve"][data-row-index="1"]').click().clear();
|
||||
cy.get('[data-cy="searchBtn"]').eq(1).click();
|
||||
cy.get('.q-table__bottom.row.items-center.q-table__bottom--nodata')
|
||||
.should('have.text', 'warningNo data available')
|
||||
.type('{esc}');
|
||||
cy.get('[data-col-field="reserve"][data-row-index="1"]')
|
||||
.click()
|
||||
.type('{backspace}{enter}');
|
||||
cy.get('[data-cy="crudModelDefaultSaveBtn"]').should('be.enabled').click();
|
||||
cy.get('.q-notification__message').eq(1).should('have.text', 'Data saved');
|
||||
});
|
||||
it('Should check detail for the buyer', () => {
|
||||
cy.get(':nth-child(1) > .sticky > .q-btn > .q-btn__content > .q-icon').click();
|
||||
cy.get('[data-cy="searchBtn"]').eq(0).click();
|
||||
cy.get('tBody > tr').eq(1).its('length').should('eq', 1);
|
||||
});
|
||||
it('Should check detail for the buyerBoss and had no content', () => {
|
||||
cy.get(':nth-child(2) > .sticky > .q-btn > .q-btn__content > .q-icon').click();
|
||||
cy.get('.q-table__bottom.row.items-center.q-table__bottom--nodata').should(
|
||||
'have.text',
|
||||
'warningNo data available',
|
||||
);
|
||||
});
|
||||
|
||||
it('Should edit travel m3 and refresh', () => {
|
||||
cy.get('.vn-row > div > .q-btn > .q-btn__content > .q-icon').click();
|
||||
cy.get('input[aria-label="m3"]').clear();
|
||||
cy.get('input[aria-label="m3"]').type('60');
|
||||
cy.get('.q-mt-lg > .q-btn--standard > .q-btn__content > .block').click();
|
||||
cy.get('[data-cy="edit-travel"]').should('be.visible').click();
|
||||
cy.get('input[aria-label="m3"]').clear().type('60');
|
||||
cy.get('[data-cy="FormModelPopup_save"]').click();
|
||||
cy.get('.vn-row > div > :nth-child(2)').should('have.text', '60');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('InvoiceInVat', () => {
|
|||
cy.get(dialogInputs).eq(0).type(randomInt);
|
||||
cy.get(dialogInputs).eq(1).type('This is a dummy expense');
|
||||
|
||||
cy.get('button[type="submit"]').click();
|
||||
cy.get('[data-cy="FormModelPopup_save"]').click();
|
||||
cy.get('.q-notification__message').should('have.text', 'Data created');
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue