Compare commits
132 Commits
hotfix_min
...
dev
Author | SHA1 | Date |
---|---|---|
JOSE ANTONIO TUBAU RODRIGUEZ | 1b05c10b50 | |
JOSE ANTONIO TUBAU RODRIGUEZ | 1d37d0dfb4 | |
JOSE ANTONIO TUBAU RODRIGUEZ | d35c37bfdf | |
JOSE ANTONIO TUBAU RODRIGUEZ | 013c07e51f | |
Pablo Natek | d72b507fd4 | |
Pablo Natek | 87bdf532a8 | |
Carlos Satorres | 59b034d0b4 | |
Carlos Satorres | ac3ca3e243 | |
Carlos Satorres | b022ede6a9 | |
Carlos Satorres | e628a6c445 | |
Pablo Natek | c043a7d99a | |
Carlos Satorres | 79c1709618 | |
Carlos Satorres | 964cf68b9c | |
Pablo Natek | d4bb5a063f | |
Pablo Natek | 8bccb959ed | |
Jon Elias | cd9b433a45 | |
Pablo Natek | 52cacd8c16 | |
Jon Elias | ba300ec065 | |
Jon Elias | e01f1fe5d2 | |
Jon Elias | d7d1e4d691 | |
Jon Elias | 983c86ffa5 | |
Carlos Satorres | 3d666338ce | |
Jorge Penadés | 5b5a935021 | |
Jorge Penadés | 273c879879 | |
Carlos Satorres | 0ecc103fc2 | |
Carlos Satorres | 7697caa85a | |
Alex Moreno | 4fc9ad3f76 | |
Javier Segarra | ee445aca83 | |
Javier Segarra | 854e72fe51 | |
Alex Moreno | 4a6f859a86 | |
Alex Moreno | b2fe1a6b6a | |
Javier Segarra | b97ee919a6 | |
Alex Moreno | 629531cce4 | |
Jorge Penadés | 2fb179803c | |
Jon Elias | 91afc3ddab | |
Jon Elias | d4682248fd | |
Jon Elias | 1de74dec8e | |
Jon Elias | bf68eab480 | |
Jon Elias | 853bb9e5aa | |
Jon Elias | e4837b45be | |
Jorge Penadés | fca380897f | |
Jorge Penadés | 9342cd0408 | |
Jorge Penadés | 7a9edfd88f | |
Jorge Penadés | f16c45b01a | |
Carlos Satorres | 5fc7d66425 | |
Carlos Satorres | a20afa5f35 | |
Jon Elias | 92b05db9d2 | |
Carlos Satorres | d9fe5be6fe | |
Jon Elias | b26d07f605 | |
Jon Elias | f5f77a50bc | |
Jon Elias | 338058c1a4 | |
Jon Elias | 0c88db5931 | |
Carlos Satorres | dc4ae1fd92 | |
Jon Elias | fea161d5c2 | |
Jon Elias | 96920dd540 | |
Jon Elias | cf522684d6 | |
Jon Elias | 6c05347219 | |
Jon Elias | accf61517a | |
Jon Elias | c7115f4781 | |
Jon Elias | 2d2187090c | |
Jon Elias | 1e1032b3da | |
Jon Elias | 646007ea63 | |
Guillermo Bonet | dcbaa7529d | |
Carlos Satorres | 47f81f2b2c | |
Carlos Satorres | 3d0245553e | |
Carlos Satorres | c3c10b2238 | |
Carlos Satorres | 91c9a4a559 | |
Carlos Satorres | cb15652dd6 | |
Jon Elias | 58a18bfb69 | |
Carlos Satorres | 95551d9f99 | |
Carlos Satorres | f5c6810d9e | |
Jorge Penadés | e0090c29c9 | |
Carlos Satorres | a6a21f3925 | |
Carlos Satorres | fc3c80d60d | |
Carlos Satorres | e55d116398 | |
Carlos Satorres | 41292e467b | |
Carlos Satorres | 55627a5b47 | |
Carlos Satorres | 29b923130f | |
Jon Elias | 4276cefd7a | |
Alex Moreno | b4a4c4a0a4 | |
Carlos Satorres | 1f80229bc8 | |
Carlos Satorres | ce83879960 | |
Carlos Satorres | 1291dc1723 | |
Carlos Satorres | 50360523b3 | |
Carlos Satorres | 48482efe3b | |
Jorge Penadés | a3f14bc39f | |
Jorge Penadés | cfa22bbc85 | |
Jorge Penadés | bfa7300651 | |
Jorge Penadés | 1710ae718e | |
Jorge Penadés | b00a3d7acf | |
Carlos Satorres | aaeabefdfe | |
Carlos Satorres | 2d656faf58 | |
Carlos Satorres | 954a777182 | |
Carlos Satorres | 59648d14f0 | |
Pablo Natek | 104348b94b | |
Pablo Natek | c006b4cb37 | |
Pablo Natek | 46cb18b5ef | |
Alex Moreno | e817e51b28 | |
Jon Elias | 2b235e93e7 | |
Jorge Penadés | 9e0f54ea9b | |
Jorge Penadés | 26e777cdd5 | |
Jorge Penadés | 8f8fcfe440 | |
Jorge Penadés | 93144439d2 | |
Carlos Satorres | eac476781f | |
Carlos Satorres | af7f7aa8f3 | |
Carlos Satorres | 1844e15239 | |
Jorge Penadés | 0fe740e415 | |
Jorge Penadés | fa43f270ca | |
Jorge Penadés | 43af96eb05 | |
Jorge Penadés | f7c64fe6ff | |
Jorge Penadés | 81f1c447ad | |
Jorge Penadés | a5d032f022 | |
Jorge Penadés | 34df9cf254 | |
Jorge Penadés | 0c476725ae | |
Jorge Penadés | 00c712469f | |
Javier Segarra | 4dc2be291f | |
Javier Segarra | a4ccbe66c7 | |
Javier Segarra | c3c51e01d4 | |
Javier Segarra | 9b681d806b | |
Jorge Penadés | 8a4589910c | |
Javier Segarra | d55764d2bc | |
Jorge Penadés | f6d200405c | |
Jorge Penadés | 3ca26a97dc | |
Jorge Penadés | 8817fd7c55 | |
Carlos Satorres | 8dd2c94b37 | |
Carlos Satorres | c0c1d3e3a9 | |
Javier Segarra | 4df05b7522 | |
Carlos Satorres | fee51db30d | |
Carlos Satorres | e8fd3c0a8f | |
Carlos Satorres | daf57c9b2b | |
Carlos Satorres | 861a507e10 | |
Carlos Satorres | 1bafdf1b85 |
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "salix-front",
|
"name": "salix-front",
|
||||||
"version": "24.50.0",
|
"version": "24.52.0",
|
||||||
"description": "Salix frontend",
|
"description": "Salix frontend",
|
||||||
"productName": "Salix",
|
"productName": "Salix",
|
||||||
"author": "Verdnatura",
|
"author": "Verdnatura",
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import routes from 'src/router/modules';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
let isNotified = false;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
created: function () {
|
||||||
|
const router = useRouter();
|
||||||
|
const keyBindingMap = routes
|
||||||
|
.filter((route) => route.meta.keyBinding)
|
||||||
|
.reduce((map, route) => {
|
||||||
|
map['Key' + route.meta.keyBinding.toUpperCase()] = route.path;
|
||||||
|
return map;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const handleKeyDown = (event) => {
|
||||||
|
const { ctrlKey, altKey, code } = event;
|
||||||
|
|
||||||
|
if (ctrlKey && altKey && keyBindingMap[code] && !isNotified) {
|
||||||
|
event.preventDefault();
|
||||||
|
router.push(keyBindingMap[code]);
|
||||||
|
isNotified = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyUp = (event) => {
|
||||||
|
const { ctrlKey, altKey } = event;
|
||||||
|
if (!ctrlKey || !altKey) {
|
||||||
|
isNotified = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
|
window.addEventListener('keyup', handleKeyUp);
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,13 +1,37 @@
|
||||||
import { getCurrentInstance } from 'vue';
|
function focusFirstInput(input) {
|
||||||
|
input.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
export default {
|
export default {
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
const vm = getCurrentInstance();
|
|
||||||
if (vm.type.name === 'QForm') {
|
|
||||||
if (!['searchbarForm', 'filterPanelForm'].includes(this.$el?.id)) {
|
|
||||||
// TODO: AUTOFOCUS IS NOT FOCUSING
|
|
||||||
const that = this;
|
const that = this;
|
||||||
this.$el.addEventListener('keyup', function (evt) {
|
|
||||||
|
const form = document.querySelector('.q-form#formModel');
|
||||||
|
if (!form) return;
|
||||||
|
try {
|
||||||
|
const inputsFormCard = form.querySelectorAll(
|
||||||
|
`input:not([disabled]):not([type="checkbox"])`
|
||||||
|
);
|
||||||
|
if (inputsFormCard.length) {
|
||||||
|
focusFirstInput(inputsFormCard[0]);
|
||||||
|
}
|
||||||
|
const textareas = document.querySelectorAll(
|
||||||
|
'textarea:not([disabled]), [contenteditable]:not([disabled])'
|
||||||
|
);
|
||||||
|
if (textareas.length) {
|
||||||
|
focusFirstInput(textareas[textareas.length - 1]);
|
||||||
|
}
|
||||||
|
const inputs = document.querySelectorAll(
|
||||||
|
'form#formModel input:not([disabled]):not([type="checkbox"])'
|
||||||
|
);
|
||||||
|
const input = inputs[0];
|
||||||
|
if (!input) return;
|
||||||
|
|
||||||
|
focusFirstInput(input);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
form.addEventListener('keyup', function (evt) {
|
||||||
if (evt.key === 'Enter') {
|
if (evt.key === 'Enter') {
|
||||||
const input = evt.target;
|
const input = evt.target;
|
||||||
if (input.type == 'textarea' && evt.shiftKey) {
|
if (input.type == 'textarea' && evt.shiftKey) {
|
||||||
|
@ -24,7 +48,5 @@ export default {
|
||||||
that.onSubmit();
|
that.onSubmit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
|
import axios from 'axios';
|
||||||
import { boot } from 'quasar/wrappers';
|
import { boot } from 'quasar/wrappers';
|
||||||
import qFormMixin from './qformMixin';
|
import qFormMixin from './qformMixin';
|
||||||
import keyShortcut from './keyShortcut';
|
import keyShortcut from './keyShortcut';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import { QForm } from 'quasar';
|
||||||
import { CanceledError } from 'axios';
|
import { QLayout } from 'quasar';
|
||||||
|
import mainShortcutMixin from './mainShortcutMixin';
|
||||||
const { notify } = useNotify();
|
import { useCau } from 'src/composables/useCau';
|
||||||
|
|
||||||
export default boot(({ app }) => {
|
export default boot(({ app }) => {
|
||||||
app.mixin(qFormMixin);
|
QForm.mixins = [qFormMixin];
|
||||||
|
QLayout.mixins = [mainShortcutMixin];
|
||||||
|
|
||||||
app.directive('shortcut', keyShortcut);
|
app.directive('shortcut', keyShortcut);
|
||||||
app.config.errorHandler = (error) => {
|
app.config.errorHandler = async (error) => {
|
||||||
let message;
|
let message;
|
||||||
const response = error.response;
|
const response = error.response;
|
||||||
const responseData = response?.data;
|
const responseData = response?.data;
|
||||||
|
@ -40,12 +43,12 @@ export default boot(({ app }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(error);
|
console.error(error);
|
||||||
if (error instanceof CanceledError) {
|
if (error instanceof axios.CanceledError) {
|
||||||
const env = process.env.NODE_ENV;
|
const env = process.env.NODE_ENV;
|
||||||
if (env && env !== 'development') return;
|
if (env && env !== 'development') return;
|
||||||
message = 'Duplicate request';
|
message = 'Duplicate request';
|
||||||
}
|
}
|
||||||
|
|
||||||
notify(message ?? 'globals.error', 'negative', 'error');
|
await useCau(response, message);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,7 +25,6 @@ const townsFetchDataRef = ref(false);
|
||||||
const townFilter = ref({});
|
const townFilter = ref({});
|
||||||
|
|
||||||
const countriesRef = ref(false);
|
const countriesRef = ref(false);
|
||||||
const provincesFetchDataRef = ref(false);
|
|
||||||
const provincesOptions = ref([]);
|
const provincesOptions = ref([]);
|
||||||
const townsOptions = ref([]);
|
const townsOptions = ref([]);
|
||||||
const town = ref({});
|
const town = ref({});
|
||||||
|
@ -71,9 +70,6 @@ async function setProvince(id, data) {
|
||||||
await fetchTowns();
|
await fetchTowns();
|
||||||
}
|
}
|
||||||
async function onProvinceCreated(data) {
|
async function onProvinceCreated(data) {
|
||||||
await provincesFetchDataRef.value.fetch({
|
|
||||||
where: { countryFk: postcodeFormData.countryFk },
|
|
||||||
});
|
|
||||||
postcodeFormData.provinceFk = data.id;
|
postcodeFormData.provinceFk = data.id;
|
||||||
}
|
}
|
||||||
function provinceByCountry(countryFk = postcodeFormData.countryFk) {
|
function provinceByCountry(countryFk = postcodeFormData.countryFk) {
|
||||||
|
@ -92,7 +88,6 @@ function setTown(newTown, data) {
|
||||||
data.countryFk = newTown?.province?.countryFk ?? newTown;
|
data.countryFk = newTown?.province?.countryFk ?? newTown;
|
||||||
}
|
}
|
||||||
async function onCityCreated(newTown, formData) {
|
async function onCityCreated(newTown, formData) {
|
||||||
await provincesFetchDataRef.value.fetch();
|
|
||||||
newTown.province = provincesOptions.value.find(
|
newTown.province = provincesOptions.value.find(
|
||||||
(province) => province.id === newTown.provinceFk
|
(province) => province.id === newTown.provinceFk
|
||||||
);
|
);
|
||||||
|
@ -125,14 +120,6 @@ async function filterTowns(name) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
|
||||||
ref="provincesFetchDataRef"
|
|
||||||
@on-fetch="handleProvinces"
|
|
||||||
:sort-by="['name ASC']"
|
|
||||||
:limit="30"
|
|
||||||
auto-load
|
|
||||||
url="Provinces/location"
|
|
||||||
/>
|
|
||||||
<FetchData
|
<FetchData
|
||||||
ref="townsFetchDataRef"
|
ref="townsFetchDataRef"
|
||||||
:sort-by="['name ASC']"
|
:sort-by="['name ASC']"
|
||||||
|
@ -205,6 +192,11 @@ async function filterTowns(name) {
|
||||||
:country-fk="data.countryFk"
|
:country-fk="data.countryFk"
|
||||||
:province-selected="data.provinceFk"
|
:province-selected="data.provinceFk"
|
||||||
@update:model-value="(value) => setProvince(value, data)"
|
@update:model-value="(value) => setProvince(value, data)"
|
||||||
|
@update:options="
|
||||||
|
(data) => {
|
||||||
|
provincesOptions = data;
|
||||||
|
}
|
||||||
|
"
|
||||||
v-model="data.provinceFk"
|
v-model="data.provinceFk"
|
||||||
@on-province-created="onProvinceCreated"
|
@on-province-created="onProvinceCreated"
|
||||||
required
|
required
|
||||||
|
|
|
@ -177,6 +177,7 @@ function normalize(text) {
|
||||||
class="full-width"
|
class="full-width"
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
|
autofocus
|
||||||
/>
|
/>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QSeparator />
|
<QSeparator />
|
||||||
|
|
|
@ -7,7 +7,7 @@ import VnSelectDialog from 'components/common/VnSelectDialog.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import CreateNewProvinceForm from './CreateNewProvinceForm.vue';
|
import CreateNewProvinceForm from './CreateNewProvinceForm.vue';
|
||||||
|
|
||||||
const emit = defineEmits(['onProvinceCreated', 'onProvinceFetched']);
|
const emit = defineEmits(['onProvinceCreated', 'onProvinceFetched', 'update:options']);
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
countryFk: {
|
countryFk: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -41,6 +41,7 @@ async function onProvinceCreated(_, data) {
|
||||||
}
|
}
|
||||||
async function handleProvinces(data) {
|
async function handleProvinces(data) {
|
||||||
provincesOptions.value = data;
|
provincesOptions.value = data;
|
||||||
|
emit('update:options', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
@ -610,6 +610,7 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
|
||||||
$props.rowClick && $props.rowClick(row);
|
$props.rowClick && $props.rowClick(row);
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
style="height: 100%"
|
||||||
>
|
>
|
||||||
<QCardSection
|
<QCardSection
|
||||||
vertical
|
vertical
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<script setup>
|
||||||
|
import { toDateFormat } from 'src/filters/date.js';
|
||||||
|
|
||||||
|
defineProps({ date: { type: [Date, String], required: true } });
|
||||||
|
|
||||||
|
function getBadgeAttrs(date) {
|
||||||
|
let today = Date.vnNew();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
let timeTicket = new Date(date);
|
||||||
|
timeTicket.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
let timeDiff = today - timeTicket;
|
||||||
|
|
||||||
|
if (timeDiff == 0) return { color: 'warning', 'text-color': 'black' };
|
||||||
|
if (timeDiff < 0) return { color: 'success', 'text-color': 'black' };
|
||||||
|
return { color: 'transparent', 'text-color': 'white' };
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatShippedDate(date) {
|
||||||
|
if (!date) return '-';
|
||||||
|
const dateSplit = date.split('T');
|
||||||
|
const [year, month, day] = dateSplit[0].split('-');
|
||||||
|
const newDate = new Date(year, month - 1, day);
|
||||||
|
return toDateFormat(newDate);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<QBadge v-bind="getBadgeAttrs(date)" class="q-pa-sm" style="font-size: 14px">
|
||||||
|
{{ formatShippedDate(date) }}
|
||||||
|
</QBadge>
|
||||||
|
</template>
|
|
@ -238,6 +238,7 @@ async function openPointRecord(id, modelLog) {
|
||||||
pointRecord.value = parseProps(propNames, locale, data);
|
pointRecord.value = parseProps(propNames, locale, data);
|
||||||
}
|
}
|
||||||
async function setLogTree(data) {
|
async function setLogTree(data) {
|
||||||
|
if (!data) return;
|
||||||
logTree.value = getLogTree(data);
|
logTree.value = getLogTree(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
<script setup>
|
||||||
|
import { computed, useAttrs } from 'vue';
|
||||||
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
|
import VnAvatar from 'src/components/ui/VnAvatar.vue';
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue']);
|
||||||
|
const $props = defineProps({
|
||||||
|
hasAvatar: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
hasInfo: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: [String, Number, Object],
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const $attrs = useAttrs();
|
||||||
|
|
||||||
|
const value = computed({
|
||||||
|
get() {
|
||||||
|
return $props.modelValue;
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
emit('update:modelValue', val);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = computed(() => {
|
||||||
|
let url = 'Workers/search';
|
||||||
|
const { departmentCodes } = $attrs.params ?? {};
|
||||||
|
if (!departmentCodes) return url;
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
departmentCodes: JSON.stringify(departmentCodes),
|
||||||
|
});
|
||||||
|
|
||||||
|
return url.concat(`?${params.toString()}`);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<VnSelect
|
||||||
|
:label="$t('globals.worker')"
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-model="value"
|
||||||
|
:url="url"
|
||||||
|
option-value="id"
|
||||||
|
option-label="nickname"
|
||||||
|
:fields="['id', 'name', 'nickname', 'code']"
|
||||||
|
sort-by="nickname ASC"
|
||||||
|
>
|
||||||
|
<template #prepend v-if="$props.hasAvatar">
|
||||||
|
<VnAvatar :worker-id="value" color="primary" :title="title" />
|
||||||
|
</template>
|
||||||
|
<template #append v-if="$props.hasInfo">
|
||||||
|
<QIcon name="info" class="cursor-pointer">
|
||||||
|
<QTooltip>{{ $t($props.hasInfo) }}</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</template>
|
||||||
|
<template #option="scope">
|
||||||
|
<QItem v-bind="scope.itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel>
|
||||||
|
{{ scope.opt.name }}
|
||||||
|
</QItemLabel>
|
||||||
|
<QItemLabel v-if="!scope.opt.id">
|
||||||
|
{{ scope.opt.nickname }}
|
||||||
|
</QItemLabel>
|
||||||
|
<QItemLabel caption v-else>
|
||||||
|
{{ scope.opt.nickname }}, {{ scope.opt.code }}
|
||||||
|
</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnSelect>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Responsible for approving invoices: Responsable de aprobar las facturas
|
||||||
|
</i18n>
|
|
@ -222,8 +222,8 @@ const toModule = computed(() =>
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss" scoped>
|
||||||
.body {
|
:deep(.body) {
|
||||||
background-color: var(--vn-section-color);
|
background-color: var(--vn-section-color);
|
||||||
.text-h5 {
|
.text-h5 {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
@ -262,9 +262,7 @@ const toModule = computed(() =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.title {
|
.title {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
|
@ -61,6 +61,7 @@ const emit = defineEmits([
|
||||||
'update:modelValue',
|
'update:modelValue',
|
||||||
'refresh',
|
'refresh',
|
||||||
'clear',
|
'clear',
|
||||||
|
'search',
|
||||||
'init',
|
'init',
|
||||||
'remove',
|
'remove',
|
||||||
'setUserParams',
|
'setUserParams',
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
import { useVnConfirm } from 'src/composables/useVnConfirm';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { i18n } from 'src/boot/i18n';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
|
export async function useCau(res, message) {
|
||||||
|
const { notify } = useNotify();
|
||||||
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
|
const { config, headers, request, status, statusText, data } = res || {};
|
||||||
|
const { params, url, method, signal, headers: confHeaders } = config || {};
|
||||||
|
const { message: resMessage, code, name } = data?.error || {};
|
||||||
|
|
||||||
|
const additionalData = {
|
||||||
|
path: location.hash,
|
||||||
|
message: resMessage,
|
||||||
|
code,
|
||||||
|
request: request?.responseURL,
|
||||||
|
status,
|
||||||
|
name,
|
||||||
|
statusText: statusText,
|
||||||
|
config: {
|
||||||
|
url,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
headers: confHeaders,
|
||||||
|
aborted: signal?.aborted,
|
||||||
|
version: headers?.['salix-version'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const opts = {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
icon: 'support_agent',
|
||||||
|
color: 'primary',
|
||||||
|
dense: true,
|
||||||
|
flat: false,
|
||||||
|
round: true,
|
||||||
|
handler: async () => {
|
||||||
|
const locale = i18n.global.t;
|
||||||
|
const reason = ref(
|
||||||
|
code == 'ACCESS_DENIED' ? locale('cau.askPrivileges') : ''
|
||||||
|
);
|
||||||
|
openConfirmationModal(
|
||||||
|
locale('cau.title'),
|
||||||
|
locale('cau.subtitle'),
|
||||||
|
async () => {
|
||||||
|
await axios.post('OsTickets/send-to-support', {
|
||||||
|
reason: reason.value,
|
||||||
|
additionalData,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
component: VnInput,
|
||||||
|
props: {
|
||||||
|
modelValue: reason,
|
||||||
|
'onUpdate:modelValue': (val) => (reason.value = val),
|
||||||
|
label: locale('cau.inputLabel'),
|
||||||
|
class: 'full-width',
|
||||||
|
required: true,
|
||||||
|
autofocus: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
notify(message ?? 'globals.error', 'negative', 'error', opts);
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import { Notify } from 'quasar';
|
||||||
import { i18n } from 'src/boot/i18n';
|
import { i18n } from 'src/boot/i18n';
|
||||||
|
|
||||||
export default function useNotify() {
|
export default function useNotify() {
|
||||||
const notify = (message, type, icon) => {
|
const notify = (message, type, icon, opts = {}) => {
|
||||||
const defaultIcons = {
|
const defaultIcons = {
|
||||||
warning: 'warning',
|
warning: 'warning',
|
||||||
negative: 'error',
|
negative: 'error',
|
||||||
|
@ -13,6 +13,7 @@ export default function useNotify() {
|
||||||
message: i18n.global.t(message),
|
message: i18n.global.t(message),
|
||||||
type: type,
|
type: type,
|
||||||
icon: icon ? icon : defaultIcons[type],
|
icon: icon ? icon : defaultIcons[type],
|
||||||
|
...opts,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,27 @@
|
||||||
|
import { h } from 'vue';
|
||||||
|
import { Dialog } from 'quasar';
|
||||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
import { useQuasar } from 'quasar';
|
|
||||||
|
|
||||||
export function useVnConfirm() {
|
export function useVnConfirm() {
|
||||||
const quasar = useQuasar();
|
const openConfirmationModal = (
|
||||||
|
title,
|
||||||
const openConfirmationModal = (title, message, promise, successFn) => {
|
message,
|
||||||
quasar
|
promise,
|
||||||
.dialog({
|
successFn,
|
||||||
component: VnConfirm,
|
customHTML = {}
|
||||||
componentProps: {
|
) => {
|
||||||
|
const { component, props } = customHTML;
|
||||||
|
Dialog.create({
|
||||||
|
component: h(
|
||||||
|
VnConfirm,
|
||||||
|
{
|
||||||
title: title,
|
title: title,
|
||||||
message: message,
|
message: message,
|
||||||
promise: promise,
|
promise: promise,
|
||||||
},
|
},
|
||||||
})
|
{ customHTML: () => h(component, props) }
|
||||||
.onOk(async () => {
|
),
|
||||||
|
}).onOk(async () => {
|
||||||
if (successFn) successFn();
|
if (successFn) successFn();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -129,6 +129,7 @@ globals:
|
||||||
small: Small
|
small: Small
|
||||||
medium: Medium
|
medium: Medium
|
||||||
big: Big
|
big: Big
|
||||||
|
email: Email
|
||||||
pageTitles:
|
pageTitles:
|
||||||
logIn: Login
|
logIn: Login
|
||||||
addressEdit: Update address
|
addressEdit: Update address
|
||||||
|
@ -329,6 +330,7 @@ globals:
|
||||||
email: Email
|
email: Email
|
||||||
SSN: SSN
|
SSN: SSN
|
||||||
fi: FI
|
fi: FI
|
||||||
|
packing: ITP
|
||||||
myTeam: My team
|
myTeam: My team
|
||||||
departmentFk: Department
|
departmentFk: Department
|
||||||
countryFk: Country
|
countryFk: Country
|
||||||
|
@ -369,6 +371,11 @@ resetPassword:
|
||||||
repeatPassword: Repeat password
|
repeatPassword: Repeat password
|
||||||
passwordNotMatch: Passwords don't match
|
passwordNotMatch: Passwords don't match
|
||||||
passwordChanged: Password changed
|
passwordChanged: Password changed
|
||||||
|
cau:
|
||||||
|
title: Send cau
|
||||||
|
subtitle: By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.
|
||||||
|
inputLabel: Explain why this error should not appear
|
||||||
|
askPrivileges: Ask for privileges
|
||||||
entry:
|
entry:
|
||||||
list:
|
list:
|
||||||
newEntry: New entry
|
newEntry: New entry
|
||||||
|
@ -398,8 +405,8 @@ entry:
|
||||||
buys: Buys
|
buys: Buys
|
||||||
stickers: Stickers
|
stickers: Stickers
|
||||||
package: Package
|
package: Package
|
||||||
packing: Packing
|
packing: Pack.
|
||||||
grouping: Grouping
|
grouping: Group.
|
||||||
buyingValue: Buying value
|
buyingValue: Buying value
|
||||||
import: Import
|
import: Import
|
||||||
pvp: PVP
|
pvp: PVP
|
||||||
|
|
|
@ -131,6 +131,7 @@ globals:
|
||||||
small: Pequeño/a
|
small: Pequeño/a
|
||||||
medium: Mediano/a
|
medium: Mediano/a
|
||||||
big: Grande
|
big: Grande
|
||||||
|
email: Correo
|
||||||
pageTitles:
|
pageTitles:
|
||||||
logIn: Inicio de sesión
|
logIn: Inicio de sesión
|
||||||
addressEdit: Modificar consignatario
|
addressEdit: Modificar consignatario
|
||||||
|
@ -335,6 +336,7 @@ globals:
|
||||||
SSN: NSS
|
SSN: NSS
|
||||||
fi: NIF
|
fi: NIF
|
||||||
myTeam: Mi equipo
|
myTeam: Mi equipo
|
||||||
|
packing: ITP
|
||||||
countryFk: País
|
countryFk: País
|
||||||
changePass: Cambiar contraseña
|
changePass: Cambiar contraseña
|
||||||
deleteConfirmTitle: Eliminar los elementos seleccionados
|
deleteConfirmTitle: Eliminar los elementos seleccionados
|
||||||
|
@ -371,6 +373,11 @@ resetPassword:
|
||||||
repeatPassword: Repetir contraseña
|
repeatPassword: Repetir contraseña
|
||||||
passwordNotMatch: Las contraseñas no coinciden
|
passwordNotMatch: Las contraseñas no coinciden
|
||||||
passwordChanged: Contraseña cambiada
|
passwordChanged: Contraseña cambiada
|
||||||
|
cau:
|
||||||
|
title: Enviar cau
|
||||||
|
subtitle: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
|
||||||
|
inputLabel: Explique el motivo por el que no deberia aparecer este fallo
|
||||||
|
askPrivileges: Solicitar permisos
|
||||||
entry:
|
entry:
|
||||||
list:
|
list:
|
||||||
newEntry: Nueva entrada
|
newEntry: Nueva entrada
|
||||||
|
@ -401,8 +408,8 @@ entry:
|
||||||
buys: Compras
|
buys: Compras
|
||||||
stickers: Etiquetas
|
stickers: Etiquetas
|
||||||
package: Embalaje
|
package: Embalaje
|
||||||
packing: Packing
|
packing: Pack.
|
||||||
grouping: Grouping
|
grouping: Group.
|
||||||
buyingValue: Coste
|
buyingValue: Coste
|
||||||
import: Importe
|
import: Importe
|
||||||
pvp: PVP
|
pvp: PVP
|
||||||
|
|
|
@ -1,50 +1,10 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useQuasar } from 'quasar';
|
|
||||||
import Navbar from 'src/components/NavBar.vue';
|
import Navbar from 'src/components/NavBar.vue';
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import routes from 'src/router/modules';
|
|
||||||
import { onMounted } from 'vue';
|
|
||||||
|
|
||||||
const quasar = useQuasar();
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
let isNotified = false;
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
const keyBindingMap = routes
|
|
||||||
.filter((route) => route.meta.keyBinding)
|
|
||||||
.reduce((map, route) => {
|
|
||||||
map['Key' + route.meta.keyBinding.toUpperCase()] = route.path;
|
|
||||||
return map;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const handleKeyDown = (event) => {
|
|
||||||
const { ctrlKey, altKey, code } = event;
|
|
||||||
|
|
||||||
if (ctrlKey && altKey && keyBindingMap[code] && !isNotified) {
|
|
||||||
event.preventDefault();
|
|
||||||
router.push(keyBindingMap[code]);
|
|
||||||
isNotified = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleKeyUp = (event) => {
|
|
||||||
const { ctrlKey, altKey } = event;
|
|
||||||
|
|
||||||
if (!ctrlKey || !altKey) {
|
|
||||||
isNotified = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('keydown', handleKeyDown);
|
|
||||||
window.addEventListener('keyup', handleKeyUp);
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QLayout view="hHh LpR fFf" v-shortcut>
|
<QLayout view="hHh LpR fFf" v-shortcut>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<RouterView></RouterView>
|
<RouterView></RouterView>
|
||||||
<QFooter v-if="quasar.platform.is.mobile"></QFooter>
|
<QFooter v-if="$q.platform.is.mobile"></QFooter>
|
||||||
</QLayout>
|
</QLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -31,7 +31,6 @@ const rolesOptions = ref([]);
|
||||||
<VnFilterPanel
|
<VnFilterPanel
|
||||||
:data-key="props.dataKey"
|
:data-key="props.dataKey"
|
||||||
:search-button="true"
|
:search-button="true"
|
||||||
:hidden-tags="['search']"
|
|
||||||
:redirect="false"
|
:redirect="false"
|
||||||
search-url="table"
|
search-url="table"
|
||||||
>
|
>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import AccountSummary from './Card/AccountSummary.vue';
|
||||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
import AccountFilter from './AccountFilter.vue';
|
import AccountFilter from './AccountFilter.vue';
|
||||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { viewSummary } = useSummaryDialog();
|
const { viewSummary } = useSummaryDialog();
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
|
@ -22,10 +23,27 @@ const columns = computed(() => [
|
||||||
field: 'id',
|
field: 'id',
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'name',
|
||||||
|
label: t('Name'),
|
||||||
|
component: 'input',
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
cardVisible: true,
|
||||||
|
create: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'roleFk',
|
name: 'roleFk',
|
||||||
label: t('role'),
|
label: t('Role'),
|
||||||
|
component: 'select',
|
||||||
|
attrs: {
|
||||||
|
url: 'VnRoles',
|
||||||
|
optionValue: 'id',
|
||||||
|
optionLabel: 'name',
|
||||||
|
},
|
||||||
columnFilter: {
|
columnFilter: {
|
||||||
component: 'select',
|
component: 'select',
|
||||||
name: 'roleFk',
|
name: 'roleFk',
|
||||||
|
@ -35,7 +53,11 @@ const columns = computed(() => [
|
||||||
optionLabel: 'name',
|
optionLabel: 'name',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
format: ({ role }, dashIfEmpty) => dashIfEmpty(role?.name),
|
format: ({ role }, dashIfEmpty) => dashIfEmpty(role?.name),
|
||||||
|
create: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -51,20 +73,32 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'name',
|
name: 'email',
|
||||||
label: t('Name'),
|
label: t('Email'),
|
||||||
component: 'input',
|
component: 'input',
|
||||||
columnField: {
|
columnField: {
|
||||||
component: null,
|
component: null,
|
||||||
},
|
},
|
||||||
cardVisible: true,
|
|
||||||
create: true,
|
create: true,
|
||||||
|
visible: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'email',
|
name: 'password',
|
||||||
label: t('email'),
|
label: t('Password'),
|
||||||
component: 'input',
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
attrs: {},
|
||||||
|
required: true,
|
||||||
|
visible: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'active',
|
||||||
|
label: t('Active'),
|
||||||
|
component: 'checkbox',
|
||||||
create: true,
|
create: true,
|
||||||
visible: false,
|
visible: false,
|
||||||
},
|
},
|
||||||
|
@ -101,7 +135,6 @@ const exprBuilder = (param, value) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnSearchbar
|
<VnSearchbar
|
||||||
data-key="AccountList"
|
data-key="AccountList"
|
||||||
|
@ -119,6 +152,12 @@ const exprBuilder = (param, value) => {
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
data-key="AccountList"
|
data-key="AccountList"
|
||||||
url="VnUsers/preview"
|
url="VnUsers/preview"
|
||||||
|
:create="{
|
||||||
|
urlCreate: 'VnUsers',
|
||||||
|
title: t('Create user'),
|
||||||
|
onDataSaved: ({ id }) => tableRef.redirect(id),
|
||||||
|
formInitialData: {},
|
||||||
|
}"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
order="id DESC"
|
order="id DESC"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
|
@ -127,7 +166,19 @@ const exprBuilder = (param, value) => {
|
||||||
:use-model="true"
|
:use-model="true"
|
||||||
:right-search="false"
|
:right-search="false"
|
||||||
auto-load
|
auto-load
|
||||||
|
>
|
||||||
|
<template #more-create-dialog="{ data }">
|
||||||
|
<QCardSection>
|
||||||
|
<VnInput
|
||||||
|
:label="t('Password')"
|
||||||
|
v-model="data.password"
|
||||||
|
type="password"
|
||||||
|
:required="true"
|
||||||
|
autocomplete="new-password"
|
||||||
/>
|
/>
|
||||||
|
</QCardSection>
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
@ -135,4 +186,7 @@ const exprBuilder = (param, value) => {
|
||||||
Id: Id
|
Id: Id
|
||||||
Nickname: Nickname
|
Nickname: Nickname
|
||||||
Name: Nombre
|
Name: Nombre
|
||||||
|
Password: Contraseña
|
||||||
|
Active: Activo
|
||||||
|
Role: Rol
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -37,11 +37,7 @@ onBeforeMount(() => {
|
||||||
@on-fetch="(data) => (rolesOptions = data)"
|
@on-fetch="(data) => (rolesOptions = data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<VnFilterPanel
|
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
|
||||||
:data-key="props.dataKey"
|
|
||||||
:search-button="true"
|
|
||||||
:hidden-tags="['search']"
|
|
||||||
>
|
|
||||||
<template #tags="{ tag, formatFn }">
|
<template #tags="{ tag, formatFn }">
|
||||||
<div class="q-gutter-x-xs">
|
<div class="q-gutter-x-xs">
|
||||||
<strong>{{ t(`acls.aclFilter.${tag.label}`) }}: </strong>
|
<strong>{{ t(`acls.aclFilter.${tag.label}`) }}: </strong>
|
||||||
|
|
|
@ -13,12 +13,7 @@ const props = defineProps({
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnFilterPanel
|
<VnFilterPanel :data-key="props.dataKey" :search-button="true" :redirect="false">
|
||||||
:data-key="props.dataKey"
|
|
||||||
:search-button="true"
|
|
||||||
:hidden-tags="['search']"
|
|
||||||
:redirect="false"
|
|
||||||
>
|
|
||||||
<template #tags="{ tag, formatFn }">
|
<template #tags="{ tag, formatFn }">
|
||||||
<div class="q-gutter-x-xs">
|
<div class="q-gutter-x-xs">
|
||||||
<strong>{{ t(`role.${tag.label}`) }}: </strong>
|
<strong>{{ t(`role.${tag.label}`) }}: </strong>
|
||||||
|
|
|
@ -8,7 +8,7 @@ import FormModel from 'components/FormModel.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import VnAvatar from 'src/components/ui/VnAvatar.vue';
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
import { getDifferences, getUpdatedValues } from 'src/filters';
|
import { getDifferences, getUpdatedValues } from 'src/filters';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -16,7 +16,6 @@ const { t } = useI18n();
|
||||||
|
|
||||||
const businessTypes = ref([]);
|
const businessTypes = ref([]);
|
||||||
const contactChannels = ref([]);
|
const contactChannels = ref([]);
|
||||||
const title = ref();
|
|
||||||
const handleSalesModelValue = (val) => ({
|
const handleSalesModelValue = (val) => ({
|
||||||
or: [
|
or: [
|
||||||
{ id: val },
|
{ id: val },
|
||||||
|
@ -117,41 +116,17 @@ function onBeforeSave(formData, originalData) {
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
url="Workers/search"
|
|
||||||
v-model="data.salesPersonFk"
|
|
||||||
:label="t('customer.summary.salesPerson')"
|
:label="t('customer.summary.salesPerson')"
|
||||||
|
v-model="data.salesPersonFk"
|
||||||
:params="{
|
:params="{
|
||||||
departmentCodes: ['VT', 'shopping'],
|
departmentCodes: ['VT', 'shopping'],
|
||||||
}"
|
}"
|
||||||
:fields="['id', 'nickname']"
|
:has-avatar="true"
|
||||||
sort-by="nickname ASC"
|
|
||||||
option-label="nickname"
|
|
||||||
option-value="id"
|
|
||||||
:rules="validate('client.salesPersonFk')"
|
:rules="validate('client.salesPersonFk')"
|
||||||
:expr-builder="exprBuilder"
|
:expr-builder="exprBuilder"
|
||||||
emit-value
|
emit-value
|
||||||
auto-load
|
|
||||||
>
|
|
||||||
<template #prepend>
|
|
||||||
<VnAvatar
|
|
||||||
:worker-id="data.salesPersonFk"
|
|
||||||
color="primary"
|
|
||||||
:title="title"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption
|
|
||||||
>{{ scope.opt?.nickname }},
|
|
||||||
{{ scope.opt?.code }}</QItemLabel
|
|
||||||
>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-model="data.contactChannelFk"
|
v-model="data.contactChannelFk"
|
||||||
:options="contactChannels"
|
:options="contactChannels"
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { useI18n } from 'vue-i18n';
|
||||||
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
defineProps({
|
defineProps({
|
||||||
|
@ -65,19 +66,14 @@ const exprBuilder = (param, value) => {
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem class="q-mb-sm">
|
<QItem class="q-mb-sm">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
url="Workers/search"
|
:label="t('Salesperson')"
|
||||||
|
v-model="params.salesPersonFk"
|
||||||
:params="{
|
:params="{
|
||||||
departmentCodes: ['VT'],
|
departmentCodes: ['VT'],
|
||||||
}"
|
}"
|
||||||
auto-load
|
|
||||||
:label="t('Salesperson')"
|
|
||||||
:expr-builder="exprBuilder"
|
:expr-builder="exprBuilder"
|
||||||
v-model="params.salesPersonFk"
|
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
option-value="id"
|
|
||||||
option-label="name"
|
|
||||||
sort-by="nickname ASC"
|
|
||||||
emit-value
|
emit-value
|
||||||
map-options
|
map-options
|
||||||
use-input
|
use-input
|
||||||
|
@ -86,18 +82,7 @@ const exprBuilder = (param, value) => {
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
:input-debounce="0"
|
:input-debounce="0"
|
||||||
>
|
/>
|
||||||
<template #option="{ itemProps, opt }">
|
|
||||||
<QItem v-bind="itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ opt.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption>
|
|
||||||
{{ opt.nickname }},{{ opt.code }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template></VnSelect
|
|
||||||
>
|
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem class="q-mb-sm">
|
<QItem class="q-mb-sm">
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import { ref, computed, markRaw } from 'vue';
|
import { ref, computed, markRaw } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
|
||||||
import VnTable from 'components/VnTable/VnTable.vue';
|
import VnTable from 'components/VnTable/VnTable.vue';
|
||||||
import VnLocation from 'src/components/common/VnLocation.vue';
|
import VnLocation from 'src/components/common/VnLocation.vue';
|
||||||
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
||||||
|
@ -12,7 +11,7 @@ import RightMenu from 'src/components/common/RightMenu.vue';
|
||||||
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
|
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
|
||||||
import { toDate } from 'src/filters';
|
import { toDate } from 'src/filters';
|
||||||
import CustomerFilter from './CustomerFilter.vue';
|
import CustomerFilter from './CustomerFilter.vue';
|
||||||
import VnAvatar from 'src/components/ui/VnAvatar.vue';
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -422,40 +421,17 @@ function handleLocation(data, location) {
|
||||||
auto-load
|
auto-load
|
||||||
>
|
>
|
||||||
<template #more-create-dialog="{ data }">
|
<template #more-create-dialog="{ data }">
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
url="Workers/search"
|
|
||||||
v-model="data.salesPersonFk"
|
|
||||||
:label="t('customer.summary.salesPerson')"
|
:label="t('customer.summary.salesPerson')"
|
||||||
|
v-model="data.salesPersonFk"
|
||||||
:params="{
|
:params="{
|
||||||
departmentCodes: ['VT', 'shopping'],
|
departmentCodes: ['VT', 'shopping'],
|
||||||
}"
|
}"
|
||||||
:fields="['id', 'nickname', 'code']"
|
:has-avatar="true"
|
||||||
sort-by="nickname ASC"
|
:id-value="data.salesPersonFk"
|
||||||
option-label="nickname"
|
|
||||||
option-value="id"
|
|
||||||
emit-value
|
emit-value
|
||||||
auto-load
|
auto-load
|
||||||
>
|
|
||||||
<template #prepend>
|
|
||||||
<VnAvatar
|
|
||||||
:worker-id="data.salesPersonFk"
|
|
||||||
color="primary"
|
|
||||||
:title="title"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption
|
|
||||||
>{{ scope.opt?.nickname }},
|
|
||||||
{{ scope.opt?.code }}</QItemLabel
|
|
||||||
>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
|
|
||||||
<VnLocation
|
<VnLocation
|
||||||
:acls="[{ model: 'Province', props: '*', accessType: 'WRITE' }]"
|
:acls="[{ model: 'Province', props: '*', accessType: 'WRITE' }]"
|
||||||
v-model="data.location"
|
v-model="data.location"
|
||||||
|
|
|
@ -6,6 +6,7 @@ import FormModel from 'components/FormModel.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -48,14 +49,9 @@ const { t } = useI18n();
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
:label="t('department.bossDepartment')"
|
:label="t('department.bossDepartment')"
|
||||||
v-model="data.workerFk"
|
v-model="data.workerFk"
|
||||||
url="Workers/search"
|
|
||||||
option-value="id"
|
|
||||||
option-label="name"
|
|
||||||
hide-selected
|
|
||||||
map-options
|
|
||||||
:rules="validate('department.workerFk')"
|
:rules="validate('department.workerFk')"
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
|
|
|
@ -83,7 +83,7 @@ const { openConfirmationModal } = useVnConfirm();
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="t('department.chat')" :value="entity.chatName" />
|
<VnLv :label="t('department.chat')" :value="entity.chatName" />
|
||||||
<VnLv :label="t('department.email')" :value="entity.notificationEmail" copy />
|
<VnLv :label="t('globals.email')" :value="entity.notificationEmail" copy />
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('department.selfConsumptionCustomer')"
|
:label="t('department.selfConsumptionCustomer')"
|
||||||
:value="entity.client?.name"
|
:value="entity.client?.name"
|
||||||
|
|
|
@ -58,7 +58,7 @@ onMounted(async () => {
|
||||||
dash
|
dash
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('department.email')"
|
:label="t('globals.email')"
|
||||||
:value="department.notificationEmail"
|
:value="department.notificationEmail"
|
||||||
dash
|
dash
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,12 +2,15 @@
|
||||||
import { ref, nextTick } from 'vue';
|
import { ref, nextTick } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
import CrudModel from 'src/components/CrudModel.vue';
|
import CrudModel from 'src/components/CrudModel.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const { notify } = useNotify();
|
||||||
|
|
||||||
const itemBarcodeRef = ref(null);
|
const itemBarcodeRef = ref(null);
|
||||||
|
|
||||||
|
@ -23,6 +26,24 @@ const focusLastInput = () => {
|
||||||
if (lastInput) lastInput.focus();
|
if (lastInput) lastInput.focus();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const removeRow = (row) => {
|
||||||
|
itemBarcodeRef.value.remove([row]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const submit = async (rows) => {
|
||||||
|
const params = rows[rows.length - 1];
|
||||||
|
let { data } = await axios.get('ItemBarcodes');
|
||||||
|
const code = params.code;
|
||||||
|
|
||||||
|
if (data.some((codes) => codes.code === code)) {
|
||||||
|
notify(t('Codes can not be repeated'), 'negative');
|
||||||
|
itemBarcodeRef.value.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await axios.patch(`ItemBarcodes`, params);
|
||||||
|
notify(t('globals.dataSaved'), 'positive');
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="full-width flex justify-center">
|
<div class="full-width flex justify-center">
|
||||||
|
@ -39,6 +60,7 @@ const focusLastInput = () => {
|
||||||
ref="itemBarcodeRef"
|
ref="itemBarcodeRef"
|
||||||
url="ItemBarcodes"
|
url="ItemBarcodes"
|
||||||
auto-load
|
auto-load
|
||||||
|
:save-fn="submit"
|
||||||
>
|
>
|
||||||
<template #body="{ rows }">
|
<template #body="{ rows }">
|
||||||
<QCard class="q-px-lg q-py-md">
|
<QCard class="q-px-lg q-py-md">
|
||||||
|
@ -54,7 +76,7 @@ const focusLastInput = () => {
|
||||||
focusable-input
|
focusable-input
|
||||||
/>
|
/>
|
||||||
<QIcon
|
<QIcon
|
||||||
@click="itemBarcodeRef.remove([row])"
|
@click="removeRow(row)"
|
||||||
class="cursor-pointer q-ml-md"
|
class="cursor-pointer q-ml-md"
|
||||||
color="primary"
|
color="primary"
|
||||||
name="delete"
|
name="delete"
|
||||||
|
@ -89,4 +111,5 @@ es:
|
||||||
Code: Código
|
Code: Código
|
||||||
Remove barcode: Quitar código de barras
|
Remove barcode: Quitar código de barras
|
||||||
Add barcode: Añadir código de barras
|
Add barcode: Añadir código de barras
|
||||||
|
Codes can not be repeated: Los códigos no puden ser repetidos
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -70,6 +70,7 @@ const onIntrastatCreated = (response, formData) => {
|
||||||
option-label="name"
|
option-label="name"
|
||||||
hide-selected
|
hide-selected
|
||||||
map-options
|
map-options
|
||||||
|
required
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { cloneItem } from 'src/pages/Item/composables/cloneItem';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: Number,
|
type: [Number, String],
|
||||||
required: false,
|
required: false,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,7 @@ const $props = defineProps({
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
saleFk: {
|
saleFk: {
|
||||||
type: Number,
|
type: [Number, String],
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
warehouseFk: {
|
warehouseFk: {
|
||||||
|
@ -61,7 +61,7 @@ onMounted(async () => {
|
||||||
const data = ref(useCardDescription());
|
const data = ref(useCardDescription());
|
||||||
const setData = async (entity) => {
|
const setData = async (entity) => {
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
data.value = useCardDescription(entity.name, entity.id);
|
data.value = useCardDescription(entity?.name, entity?.id);
|
||||||
await updateStock();
|
await updateStock();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ const $props = defineProps({
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
entityId: {
|
entityId: {
|
||||||
type: String,
|
type: [String, Number],
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
showEditButton: {
|
showEditButton: {
|
||||||
|
@ -67,7 +67,7 @@ const handlePhotoUpdated = (evt = false) => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="relative-position">
|
<div class="relative-position">
|
||||||
<VnImg ref="image" :id="$props.entityId" zoom-resolution="1600x900">
|
<VnImg ref="image" :id="parseInt($props.entityId)" zoom-resolution="1600x900">
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="absolute-full picture text-center q-pa-md flex flex-center">
|
<div class="absolute-full picture text-center q-pa-md flex flex-center">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,21 +1,30 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, computed, onUnmounted, ref, watch } from 'vue';
|
import { onMounted, computed, ref, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { dateRange } from 'src/filters';
|
import { dateRange } from 'src/filters';
|
||||||
import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue';
|
import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue';
|
||||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||||
|
import VnDateBadge from 'src/components/common/VnDateBadge.vue';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
|
||||||
import { toDateTimeFormat } from 'src/filters/date.js';
|
|
||||||
import { dashIfEmpty } from 'src/filters';
|
import { dashIfEmpty } from 'src/filters';
|
||||||
import { toCurrency } from 'filters/index';
|
import { toCurrency } from 'filters/index';
|
||||||
import { useArrayData } from 'composables/useArrayData';
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||||
|
import axios from 'axios';
|
||||||
|
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const stateStore = useStateStore();
|
const from = ref();
|
||||||
|
const to = ref();
|
||||||
|
const hideInventory = ref(true);
|
||||||
|
const inventorySupplierFk = ref();
|
||||||
|
|
||||||
|
async function getInventorySupplier() {
|
||||||
|
inventorySupplierFk.value = (
|
||||||
|
await axios.get(`InventoryConfigs`)
|
||||||
|
)?.data[0]?.supplierFk;
|
||||||
|
}
|
||||||
|
|
||||||
const exprBuilder = (param, value) => {
|
const exprBuilder = (param, value) => {
|
||||||
switch (param) {
|
switch (param) {
|
||||||
|
@ -36,25 +45,27 @@ const exprBuilder = (param, value) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const from = ref();
|
const where = {
|
||||||
const to = ref();
|
itemFk: route.params.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (hideInventory.value) {
|
||||||
|
where.supplierFk = { neq: inventorySupplierFk };
|
||||||
|
}
|
||||||
|
|
||||||
const arrayData = useArrayData('ItemLastEntries', {
|
const arrayData = useArrayData('ItemLastEntries', {
|
||||||
url: 'Items/lastEntriesFilter',
|
url: 'Items/lastEntriesFilter',
|
||||||
order: ['landed DESC', 'buyFk DESC'],
|
order: ['landed DESC', 'buyFk DESC'],
|
||||||
exprBuilder: exprBuilder,
|
exprBuilder: exprBuilder,
|
||||||
userFilter: {
|
userFilter: {
|
||||||
where: {
|
where: where,
|
||||||
itemFk: route.params.id,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const itemLastEntries = ref([]);
|
const itemLastEntries = ref([]);
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
label: t('lastEntries.ig'),
|
label: 'Nv',
|
||||||
name: 'ig',
|
name: 'ig',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
|
@ -62,33 +73,38 @@ const columns = computed(() => [
|
||||||
label: t('itemDiary.warehouse'),
|
label: t('itemDiary.warehouse'),
|
||||||
name: 'warehouse',
|
name: 'warehouse',
|
||||||
field: 'warehouse',
|
field: 'warehouse',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('lastEntries.landed'),
|
label: t('lastEntries.landed'),
|
||||||
name: 'id',
|
name: 'date',
|
||||||
field: 'landed',
|
field: 'landed',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
format: (val) => toDateTimeFormat(val),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('lastEntries.entry'),
|
label: t('lastEntries.entry'),
|
||||||
name: 'entry',
|
name: 'entry',
|
||||||
field: 'stateName',
|
field: 'stateName',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
format: (val) => dashIfEmpty(val),
|
format: (val) => dashIfEmpty(val),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('lastEntries.pvp'),
|
label: t('lastEntries.pvp'),
|
||||||
name: 'pvp',
|
name: 'pvp',
|
||||||
field: 'reference',
|
field: 'reference',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
format: (_, row) => toCurrency(row.price2) + ' / ' + toCurrency(row.price3),
|
format: (_, row) => toCurrency(row.price2) + ' / ' + toCurrency(row.price3),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: t('lastEntries.printedStickers'),
|
||||||
|
name: 'printedStickers',
|
||||||
|
field: 'printedStickers',
|
||||||
|
align: 'center',
|
||||||
|
format: (val) => dashIfEmpty(val),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: t('lastEntries.label'),
|
label: t('lastEntries.label'),
|
||||||
name: 'label',
|
name: 'stickers',
|
||||||
field: 'stickers',
|
field: 'stickers',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
format: (val) => dashIfEmpty(val),
|
format: (val) => dashIfEmpty(val),
|
||||||
|
@ -96,11 +112,13 @@ const columns = computed(() => [
|
||||||
{
|
{
|
||||||
label: t('shelvings.packing'),
|
label: t('shelvings.packing'),
|
||||||
name: 'packing',
|
name: 'packing',
|
||||||
|
field: 'packing',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('lastEntries.grouping'),
|
label: t('lastEntries.grouping'),
|
||||||
name: 'grouping',
|
name: 'grouping',
|
||||||
|
field: 'grouping',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -111,18 +129,19 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('lastEntries.quantity'),
|
label: t('lastEntries.quantity'),
|
||||||
name: 'stems',
|
name: 'quantity',
|
||||||
field: 'quantity',
|
field: 'quantity',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('lastEntries.cost'),
|
label: t('lastEntries.cost'),
|
||||||
name: 'cost',
|
name: 'cost',
|
||||||
align: 'left',
|
field: 'cost',
|
||||||
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('lastEntries.kg'),
|
label: 'Kg',
|
||||||
name: 'stems',
|
name: 'weight',
|
||||||
field: 'weight',
|
field: 'weight',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
|
@ -134,9 +153,9 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('lastEntries.supplier'),
|
label: t('lastEntries.supplier'),
|
||||||
name: 'stems',
|
name: 'supplier',
|
||||||
field: 'supplier',
|
field: 'supplier',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -160,11 +179,18 @@ const updateFilter = async () => {
|
||||||
else if (from.value && !to.value) filter = { gte: from.value };
|
else if (from.value && !to.value) filter = { gte: from.value };
|
||||||
else if (from.value && to.value) filter = { between: [from.value, to.value] };
|
else if (from.value && to.value) filter = { between: [from.value, to.value] };
|
||||||
|
|
||||||
arrayData.store.userFilter.where.landed = filter;
|
const userFilter = arrayData.store.userFilter.where;
|
||||||
|
|
||||||
|
userFilter.landed = filter;
|
||||||
|
if (hideInventory.value) userFilter.supplierFk = { neq: inventorySupplierFk };
|
||||||
|
else delete userFilter.supplierFk;
|
||||||
|
|
||||||
await fetchItemLastEntries();
|
await fetchItemLastEntries();
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
await getInventorySupplier();
|
||||||
|
|
||||||
const _from = Date.vnNew();
|
const _from = Date.vnNew();
|
||||||
_from.setDate(_from.getDate() - 75);
|
_from.setDate(_from.getDate() - 75);
|
||||||
from.value = getDate(_from, 'from');
|
from.value = getDate(_from, 'from');
|
||||||
|
@ -174,16 +200,13 @@ onMounted(async () => {
|
||||||
|
|
||||||
updateFilter();
|
updateFilter();
|
||||||
|
|
||||||
watch([from, to], ([nFrom, nTo], [oFrom, oTo]) => {
|
watch([from, to, hideInventory], ([nFrom, nTo], [oFrom, oTo]) => {
|
||||||
if (nFrom && nFrom != oFrom) nFrom = getDate(new Date(nFrom), 'from');
|
if (nFrom && nFrom != oFrom) nFrom = getDate(new Date(nFrom), 'from');
|
||||||
if (nTo && nTo != oTo) nTo = getDate(new Date(nTo), 'to');
|
if (nTo && nTo != oTo) nTo = getDate(new Date(nTo), 'to');
|
||||||
updateFilter();
|
updateFilter();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnSubToolbar>
|
<VnSubToolbar>
|
||||||
<template #st-data>
|
<template #st-data>
|
||||||
|
@ -192,27 +215,45 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
dense
|
dense
|
||||||
v-model="from"
|
v-model="from"
|
||||||
class="q-mr-lg"
|
class="q-mr-lg"
|
||||||
|
data-cy="from"
|
||||||
|
/>
|
||||||
|
<VnInputDate
|
||||||
|
:label="t('lastEntries.to')"
|
||||||
|
v-model="to"
|
||||||
|
dense
|
||||||
|
class="q-mr-lg"
|
||||||
|
data-cy="to"
|
||||||
|
/>
|
||||||
|
<QCheckbox
|
||||||
|
:label="t('Hide inventory supplier')"
|
||||||
|
v-model="hideInventory"
|
||||||
|
dense
|
||||||
|
class="q-mr-lg"
|
||||||
|
data-cy="hideInventory"
|
||||||
/>
|
/>
|
||||||
<VnInputDate :label="t('lastEntries.to')" dense v-model="to" />
|
|
||||||
</template>
|
</template>
|
||||||
</VnSubToolbar>
|
</VnSubToolbar>
|
||||||
<QPage class="column items-center q-pa-xd">
|
<QPage class="column items-center q-pa-xd">
|
||||||
<QTable
|
<QTable
|
||||||
:rows="itemLastEntries"
|
:rows="itemLastEntries"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
class="full-width q-mt-md"
|
class="table full-width q-mt-md"
|
||||||
:no-data-label="t('globals.noResults')"
|
:no-data-label="t('globals.noResults')"
|
||||||
>
|
>
|
||||||
<template #body-cell-ig="{ row }">
|
<template #body-cell-ig="{ row }">
|
||||||
<QTd @click.stop>
|
<QTd class="text-center">
|
||||||
<QCheckbox
|
<QIcon
|
||||||
v-model="row.isIgnored"
|
:name="row.isIgnored ? 'check_box' : 'check_box_outline_blank'"
|
||||||
:disable="true"
|
style="color: var(--vn-label-color)"
|
||||||
:false-value="0"
|
size="sm"
|
||||||
:true-value="1"
|
|
||||||
/>
|
/>
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
|
<template #body-cell-date="{ row }">
|
||||||
|
<QTd class="text-center">
|
||||||
|
<VnDateBadge :date="row.landed" />
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
<template #body-cell-entry="{ row }">
|
<template #body-cell-entry="{ row }">
|
||||||
<QTd @click.stop>
|
<QTd @click.stop>
|
||||||
<div class="full-width flex justify-center">
|
<div class="full-width flex justify-center">
|
||||||
|
@ -234,8 +275,8 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-pvp="{ value }">
|
<template #body-cell-pvp="{ value }">
|
||||||
<QTd @click.stop
|
<QTd @click.stop class="text-center">
|
||||||
><span> {{ value }}</span>
|
<span> {{ value }}</span>
|
||||||
<QTooltip>
|
<QTooltip>
|
||||||
{{ t('lastEntries.grouping') }}/{{ t('lastEntries.packing') }}
|
{{ t('lastEntries.grouping') }}/{{ t('lastEntries.packing') }}
|
||||||
</QTooltip></QTd
|
</QTooltip></QTd
|
||||||
|
@ -254,7 +295,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-cost="{ row }">
|
<template #body-cell-cost="{ row }">
|
||||||
<QTd @click.stop>
|
<QTd @click.stop class="text-center">
|
||||||
<span>
|
<span>
|
||||||
{{ toCurrency(row.cost, 'EUR', 3) }}
|
{{ toCurrency(row.cost, 'EUR', 3) }}
|
||||||
<QTooltip>
|
<QTooltip>
|
||||||
|
@ -272,10 +313,25 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
</span>
|
</span>
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
|
<template #body-cell-supplier="{ row }">
|
||||||
|
<QTd @click.stop>
|
||||||
|
<div class="full-width flex justify-center">
|
||||||
|
<SupplierDescriptorProxy
|
||||||
|
:id="row.supplierFk"
|
||||||
|
class="q-ma-none"
|
||||||
|
dense
|
||||||
|
/>
|
||||||
|
<span class="link">{{ row.supplier }}</span>
|
||||||
|
</div>
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
</QTable>
|
</QTable>
|
||||||
</QPage>
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Hide inventory supplier: Ocultar proveedor inventario
|
||||||
|
</i18n>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.q-badge--rounded {
|
.q-badge--rounded {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
@ -287,4 +343,10 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
padding: 0 11px;
|
padding: 0 11px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
}
|
}
|
||||||
|
.th :first-child {
|
||||||
|
.td {
|
||||||
|
text-align: center;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, computed, reactive } from 'vue';
|
import { onMounted, ref, computed, reactive, watchEffect } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
|
||||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
|
|
||||||
import { toDateFormat } from 'src/filters/date.js';
|
import { toDateFormat } from 'src/filters/date.js';
|
||||||
import { dashIfEmpty } from 'src/filters';
|
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
|
|
||||||
|
@ -21,8 +17,9 @@ const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
const { openConfirmationModal } = useVnConfirm();
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
|
const tableRef = ref();
|
||||||
const rowsSelected = ref([]);
|
const selectedRows = ref([]);
|
||||||
|
const hasSelectedCards = computed(() => selectedRows.value.length > 0);
|
||||||
|
|
||||||
const exprBuilder = (param, value) => {
|
const exprBuilder = (param, value) => {
|
||||||
switch (param) {
|
switch (param) {
|
||||||
|
@ -36,6 +33,11 @@ const exprBuilder = (param, value) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const params = reactive({ itemFk: route.params.id });
|
const params = reactive({ itemFk: route.params.id });
|
||||||
|
const filter = reactive({
|
||||||
|
where: {
|
||||||
|
itemFk: route.params.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const arrayData = useArrayData('ItemShelvings', {
|
const arrayData = useArrayData('ItemShelvings', {
|
||||||
url: 'ItemShelvingPlacementSupplyStocks',
|
url: 'ItemShelvingPlacementSupplyStocks',
|
||||||
|
@ -44,58 +46,32 @@ const arrayData = useArrayData('ItemShelvings', {
|
||||||
});
|
});
|
||||||
const rows = computed(() => arrayData.store.data || []);
|
const rows = computed(() => arrayData.store.data || []);
|
||||||
|
|
||||||
const applyColumnFilter = async (col) => {
|
|
||||||
const paramKey = col.columnFilter?.filterParamKey || col.field;
|
|
||||||
params[paramKey] = col.columnFilter.filterValue;
|
|
||||||
await arrayData.addFilter({ filter: null, params });
|
|
||||||
};
|
|
||||||
|
|
||||||
const getInputEvents = (col) => {
|
|
||||||
return col.columnFilter.type === 'select'
|
|
||||||
? { 'update:modelValue': () => applyColumnFilter(col) }
|
|
||||||
: {
|
|
||||||
'keyup.enter': () => applyColumnFilter(col),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
label: t('shelvings.created'),
|
label: t('shelvings.created'),
|
||||||
name: 'created',
|
name: 'created',
|
||||||
field: 'created',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
sortable: true,
|
columnFilter: false,
|
||||||
columnFilter: null,
|
format: (row) => toDateFormat(row.created),
|
||||||
format: (val) => toDateFormat(val),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
label: t('shelvings.item'),
|
label: t('shelvings.item'),
|
||||||
name: 'item',
|
name: 'itemFk',
|
||||||
field: 'itemFk',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
sortable: true,
|
columnFilter: false,
|
||||||
columnFilter: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('shelvings.concept'),
|
label: t('shelvings.concept'),
|
||||||
name: 'concept',
|
name: 'longName',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
sortable: true,
|
columnFilter: false,
|
||||||
columnFilter: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('shelvings.parking'),
|
label: t('shelvings.parking'),
|
||||||
name: 'parking',
|
name: 'parking',
|
||||||
field: 'parking',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
sortable: true,
|
component: 'select',
|
||||||
format: (val) => dashIfEmpty(val),
|
|
||||||
columnFilter: {
|
|
||||||
component: VnSelect,
|
|
||||||
type: 'select',
|
|
||||||
filterValue: null,
|
|
||||||
event: getInputEvents,
|
|
||||||
attrs: {
|
attrs: {
|
||||||
url: 'parkings',
|
url: 'parkings',
|
||||||
fields: ['code'],
|
fields: ['code'],
|
||||||
|
@ -104,20 +80,13 @@ const columns = computed(() => [
|
||||||
'option-label': 'code',
|
'option-label': 'code',
|
||||||
dense: true,
|
dense: true,
|
||||||
},
|
},
|
||||||
},
|
columnField: { component: null },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('shelvings.shelving'),
|
label: t('shelvings.shelving'),
|
||||||
name: 'shelving',
|
name: 'shelving',
|
||||||
field: 'shelving',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
sortable: true,
|
component: 'select',
|
||||||
format: (val) => dashIfEmpty(val),
|
|
||||||
columnFilter: {
|
|
||||||
component: VnSelect,
|
|
||||||
type: 'select',
|
|
||||||
filterValue: null,
|
|
||||||
event: getInputEvents,
|
|
||||||
attrs: {
|
attrs: {
|
||||||
url: 'shelvings',
|
url: 'shelvings',
|
||||||
fields: ['code'],
|
fields: ['code'],
|
||||||
|
@ -126,41 +95,20 @@ const columns = computed(() => [
|
||||||
'option-label': 'code',
|
'option-label': 'code',
|
||||||
dense: true,
|
dense: true,
|
||||||
},
|
},
|
||||||
},
|
columnField: { component: null },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('shelvings.label'),
|
label: t('shelvings.label'),
|
||||||
name: 'label',
|
name: 'label',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
sortable: true,
|
columnFilter: { inWhere: true },
|
||||||
format: (_, row) => (row.stock / row.packing).toFixed(2),
|
format: (row) => (row.stock / row.packing).toFixed(2),
|
||||||
columnFilter: {
|
|
||||||
component: VnInput,
|
|
||||||
type: 'text',
|
|
||||||
filterParamKey: 'label',
|
|
||||||
filterValue: null,
|
|
||||||
event: getInputEvents,
|
|
||||||
attrs: {
|
|
||||||
dense: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('shelvings.packing'),
|
label: t('shelvings.packing'),
|
||||||
field: 'packing',
|
|
||||||
name: 'packing',
|
name: 'packing',
|
||||||
|
attrs: { inWhere: true },
|
||||||
align: 'left',
|
align: 'left',
|
||||||
sortable: true,
|
|
||||||
columnFilter: {
|
|
||||||
component: VnInput,
|
|
||||||
type: 'text',
|
|
||||||
filterValue: null,
|
|
||||||
event: getInputEvents,
|
|
||||||
attrs: {
|
|
||||||
dense: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
format: (val) => dashIfEmpty(val),
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -169,15 +117,16 @@ const totalLabels = computed(() =>
|
||||||
);
|
);
|
||||||
|
|
||||||
const removeLines = async () => {
|
const removeLines = async () => {
|
||||||
const itemShelvingIds = rowsSelected.value.map((row) => row.itemShelvingFk);
|
const itemShelvingIds = selectedRows.value.map((row) => row.itemShelvingFk);
|
||||||
await axios.post('ItemShelvings/deleteItemShelvings', { itemShelvingIds });
|
await axios.post('ItemShelvings/deleteItemShelvings', { itemShelvingIds });
|
||||||
rowsSelected.value = [];
|
selectedRows.value = [];
|
||||||
notify('shelvings.shelvingsRemoved', 'positive');
|
notify('shelvings.shelvingsRemoved', 'positive');
|
||||||
await arrayData.fetch({ append: false });
|
await tableRef.value.reload();
|
||||||
};
|
};
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await arrayData.fetch({ append: false });
|
await arrayData.fetch({ append: false });
|
||||||
});
|
});
|
||||||
|
watchEffect(selectedRows);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -203,7 +152,7 @@ onMounted(async () => {
|
||||||
<QBtn
|
<QBtn
|
||||||
color="primary"
|
color="primary"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
:disabled="!rowsSelected.length"
|
:disabled="!hasSelectedCards"
|
||||||
@click="
|
@click="
|
||||||
openConfirmationModal(
|
openConfirmationModal(
|
||||||
t('shelvings.removeConfirmTitle'),
|
t('shelvings.removeConfirmTitle'),
|
||||||
|
@ -219,41 +168,27 @@ onMounted(async () => {
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
<QPage class="column items-center q-pa-md">
|
<QPage class="column items-center q-pa-md">
|
||||||
<QTable
|
<VnTable
|
||||||
:rows="rows"
|
ref="tableRef"
|
||||||
|
data-key="ItemShelving"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
row-key="id"
|
:url="`ItemShelvingPlacementSupplyStocks`"
|
||||||
:pagination="{ rowsPerPage: 0 }"
|
:filter="filter"
|
||||||
class="full-width q-mt-md"
|
:expr-builder="exprBuilder"
|
||||||
selection="multiple"
|
:right-search="false"
|
||||||
v-model:selected="rowsSelected"
|
v-model:selected="selectedRows"
|
||||||
:no-data-label="t('globals.noResults')"
|
:table="{
|
||||||
|
'row-key': 'itemShelvingFk',
|
||||||
|
selection: 'multiple',
|
||||||
|
}"
|
||||||
|
auto-load
|
||||||
>
|
>
|
||||||
<template #top-row="{ cols }">
|
<template #column-longName="{ row }">
|
||||||
<QTr>
|
<span class="link" @click.stop>
|
||||||
<QTd />
|
{{ row.longName }}
|
||||||
<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 #body-cell-concept="{ row }">
|
|
||||||
<QTd @click.stop>
|
|
||||||
<span class="link">{{ row.longName }}</span>
|
|
||||||
<ItemDescriptorProxy :id="row.itemFk" />
|
<ItemDescriptorProxy :id="row.itemFk" />
|
||||||
</QTd>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</QTable>
|
</VnTable>
|
||||||
</QPage>
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -46,7 +46,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
|
||||||
<template #body="{ entity: { item, tags, visible, available, botanical } }">
|
<template #body="{ entity: { item, tags, visible, available, botanical } }">
|
||||||
<QCard class="vn-one photo">
|
<QCard class="vn-one photo">
|
||||||
<ItemDescriptorImage
|
<ItemDescriptorImage
|
||||||
:entity-id="entityId"
|
:entity-id="Number(entityId)"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
:available="available"
|
:available="available"
|
||||||
:show-edit-button="false"
|
:show-edit-button="false"
|
||||||
|
@ -89,7 +89,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
:url="getUrl(entityId, 'basic-data')"
|
:url="getUrl(entityId, 'basic-data')"
|
||||||
:text="t('item.summary.otherData')"
|
:text="t('item.summary.basicData')"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('item.summary.intrastatCode')"
|
:label="t('item.summary.intrastatCode')"
|
||||||
|
|
|
@ -8,7 +8,6 @@ import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -60,6 +59,10 @@ const insertTag = (rows) => {
|
||||||
itemTagsRef.value.formData[itemTagsRef.value.formData.length - 1].priority =
|
itemTagsRef.value.formData[itemTagsRef.value.formData.length - 1].priority =
|
||||||
getHighestPriority(rows);
|
getHighestPriority(rows);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const submitTags = async (data) => {
|
||||||
|
itemTagsRef.value.onSubmit(data);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -77,7 +80,6 @@ const insertTag = (rows) => {
|
||||||
data-key="ItemTags"
|
data-key="ItemTags"
|
||||||
model="ItemTags"
|
model="ItemTags"
|
||||||
url="ItemTags"
|
url="ItemTags"
|
||||||
update-url="Tags/onSubmit"
|
|
||||||
:data-required="{
|
:data-required="{
|
||||||
$index: undefined,
|
$index: undefined,
|
||||||
itemFk: route.params.id,
|
itemFk: route.params.id,
|
||||||
|
@ -147,6 +149,7 @@ const insertTag = (rows) => {
|
||||||
v-model="row.value"
|
v-model="row.value"
|
||||||
:label="t('itemTags.value')"
|
:label="t('itemTags.value')"
|
||||||
:is-clearable="false"
|
:is-clearable="false"
|
||||||
|
@keyup.enter.stop="submitTags(row)"
|
||||||
/>
|
/>
|
||||||
<VnInput
|
<VnInput
|
||||||
:label="t('itemBasicData.relevancy')"
|
:label="t('itemBasicData.relevancy')"
|
||||||
|
@ -154,6 +157,7 @@ const insertTag = (rows) => {
|
||||||
v-model="row.priority"
|
v-model="row.priority"
|
||||||
:required="true"
|
:required="true"
|
||||||
:rules="validate('itemTag.priority')"
|
:rules="validate('itemTag.priority')"
|
||||||
|
@keyup.enter.stop="submitTags(row)"
|
||||||
/>
|
/>
|
||||||
<div class="row justify-center" style="flex: 0">
|
<div class="row justify-center" style="flex: 0">
|
||||||
<QIcon
|
<QIcon
|
||||||
|
@ -189,3 +193,8 @@ const insertTag = (rows) => {
|
||||||
</QPage>
|
</QPage>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Tags can not be repeated: Las etiquetas no pueden repetirse
|
||||||
|
</i18n>
|
||||||
|
|
|
@ -28,7 +28,7 @@ const taxesFilter = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const ItemTaxRef = ref(null);
|
const ItemTaxRef = ref();
|
||||||
const taxesOptions = ref([]);
|
const taxesOptions = ref([]);
|
||||||
|
|
||||||
const submitTaxes = async (data) => {
|
const submitTaxes = async (data) => {
|
||||||
|
@ -36,7 +36,10 @@ const submitTaxes = async (data) => {
|
||||||
id: tax.id,
|
id: tax.id,
|
||||||
taxClassFk: tax.taxClassFk,
|
taxClassFk: tax.taxClassFk,
|
||||||
}));
|
}));
|
||||||
|
if (payload.some((item) => item.taxClassFk === null)) {
|
||||||
|
notify(t('Tax class cannot be blank'), 'negative');
|
||||||
|
return;
|
||||||
|
}
|
||||||
await axios.post(`Items/updateTaxes`, payload);
|
await axios.post(`Items/updateTaxes`, payload);
|
||||||
notify(t('globals.dataSaved'), 'positive');
|
notify(t('globals.dataSaved'), 'positive');
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,17 +55,6 @@ const columns = computed(() => [
|
||||||
label: '',
|
label: '',
|
||||||
name: 'image',
|
name: 'image',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
columnField: {
|
|
||||||
component: VnImg,
|
|
||||||
attrs: ({ row }) => {
|
|
||||||
return {
|
|
||||||
id: row?.id,
|
|
||||||
zoomResolution: '1600x900',
|
|
||||||
zoom: true,
|
|
||||||
class: 'rounded',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
columnFilter: false,
|
columnFilter: false,
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
|
@ -184,7 +173,7 @@ const columns = computed(() => [
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('globals.origin'),
|
label: t('item.list.origin'),
|
||||||
name: 'origin',
|
name: 'origin',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
component: 'select',
|
component: 'select',
|
||||||
|
@ -228,7 +217,8 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('item.list.weightByPiece'),
|
label: t('item.list.weight'),
|
||||||
|
toolTip: t('item.list.weightByPiece'),
|
||||||
name: 'weightByPiece',
|
name: 'weightByPiece',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
component: 'input',
|
component: 'input',
|
||||||
|
@ -322,7 +312,6 @@ const columns = computed(() => [
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
data-key="ItemList"
|
data-key="ItemList"
|
||||||
url="Items/filter"
|
url="Items/filter"
|
||||||
url-create="Items"
|
|
||||||
:create="{
|
:create="{
|
||||||
urlCreate: 'Items',
|
urlCreate: 'Items',
|
||||||
title: t('Create Item'),
|
title: t('Create Item'),
|
||||||
|
@ -333,12 +322,19 @@ const columns = computed(() => [
|
||||||
}"
|
}"
|
||||||
:order="['isActive DESC', 'name', 'id']"
|
:order="['isActive DESC', 'name', 'id']"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
auto-load
|
|
||||||
redirect="Item"
|
redirect="Item"
|
||||||
:is-editable="false"
|
:is-editable="false"
|
||||||
:right-search="false"
|
:right-search="false"
|
||||||
:filer="itemFilter"
|
:filter="itemFilter"
|
||||||
>
|
>
|
||||||
|
<template #column-image="{ row }">
|
||||||
|
<VnImg
|
||||||
|
:id="row?.id"
|
||||||
|
zoom-resolution="1600x900"
|
||||||
|
:zoom="true"
|
||||||
|
class="rounded"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
<template #column-id="{ row }">
|
<template #column-id="{ row }">
|
||||||
<span class="link" @click.stop>
|
<span class="link" @click.stop>
|
||||||
{{ row.id }}
|
{{ row.id }}
|
||||||
|
@ -348,7 +344,7 @@ const columns = computed(() => [
|
||||||
<template #column-userName="{ row }">
|
<template #column-userName="{ row }">
|
||||||
<span class="link" @click.stop>
|
<span class="link" @click.stop>
|
||||||
{{ row.userName }}
|
{{ row.userName }}
|
||||||
<WorkerDescriptorProxy :id="row.workerFk" />
|
<WorkerDescriptorProxy :id="row.buyerFk" />
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<template #column-description="{ row }">
|
<template #column-description="{ row }">
|
||||||
|
|
|
@ -199,7 +199,17 @@ onMounted(async () => {
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
/>
|
>
|
||||||
|
<template #option="scope">
|
||||||
|
<QItem v-bind="scope.itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel>{{
|
||||||
|
t(`params.${scope.opt?.name}`)
|
||||||
|
}}</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnSelect>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
|
@ -434,6 +444,13 @@ en:
|
||||||
description: Description
|
description: Description
|
||||||
name: Name
|
name: Name
|
||||||
id: Id
|
id: Id
|
||||||
|
Accessories: Accessories
|
||||||
|
Artificial: Artificial
|
||||||
|
Flower: Flower
|
||||||
|
Fruit: Fruit
|
||||||
|
Green: Green
|
||||||
|
Handmade: Handmade
|
||||||
|
Plant: Plant
|
||||||
es:
|
es:
|
||||||
More fields: Más campos
|
More fields: Más campos
|
||||||
params:
|
params:
|
||||||
|
@ -450,4 +467,11 @@ es:
|
||||||
description: Descripción
|
description: Descripción
|
||||||
name: Nombre
|
name: Nombre
|
||||||
id: Id
|
id: Id
|
||||||
|
Accessories: Accesorios
|
||||||
|
Artificial: Artificial
|
||||||
|
Flower: Flor
|
||||||
|
Fruit: Fruta
|
||||||
|
Green: Verde
|
||||||
|
Handmade: Hecho a mano
|
||||||
|
Plant: Planta
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -5,13 +5,16 @@ import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.v
|
||||||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useArrayData } from 'composables/useArrayData';
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
import { dashIfEmpty, toCurrency } from 'filters/index';
|
import { toCurrency } from 'filters/index';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import ItemRequestDenyForm from './ItemRequestDenyForm.vue';
|
import ItemRequestDenyForm from './ItemRequestDenyForm.vue';
|
||||||
import { toDate } from 'src/filters';
|
import { toDate } from 'src/filters';
|
||||||
import VnTable from 'components/VnTable/VnTable.vue';
|
import VnTable from 'components/VnTable/VnTable.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||||
|
import ItemRequestFilter from './ItemRequestFilter.vue';
|
||||||
|
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
|
@ -228,6 +231,11 @@ onMounted(async () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<RightMenu>
|
||||||
|
<template #right-panel>
|
||||||
|
<ItemRequestFilter data-key="itemRequest" />
|
||||||
|
</template>
|
||||||
|
</RightMenu>
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
data-key="itemRequest"
|
data-key="itemRequest"
|
||||||
|
@ -239,6 +247,7 @@ onMounted(async () => {
|
||||||
auto-load
|
auto-load
|
||||||
:disable-option="{ card: true }"
|
:disable-option="{ card: true }"
|
||||||
chip-locale="item.params"
|
chip-locale="item.params"
|
||||||
|
:right-search="false"
|
||||||
>
|
>
|
||||||
<template #column-ticketFk="{ row }">
|
<template #column-ticketFk="{ row }">
|
||||||
<span class="link">
|
<span class="link">
|
||||||
|
@ -306,7 +315,6 @@ onMounted(async () => {
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #column-denyOptions="{ row, rowIndex }">
|
<template #column-denyOptions="{ row, rowIndex }">
|
||||||
<QTd class="sticky no-padding">
|
|
||||||
<QIcon
|
<QIcon
|
||||||
v-if="row.response?.length"
|
v-if="row.response?.length"
|
||||||
name="insert_drive_file"
|
name="insert_drive_file"
|
||||||
|
@ -329,7 +337,6 @@ onMounted(async () => {
|
||||||
{{ t('Discard') }}
|
{{ t('Discard') }}
|
||||||
</QTooltip>
|
</QTooltip>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
</QTd>
|
|
||||||
</template>
|
</template>
|
||||||
</VnTable>
|
</VnTable>
|
||||||
<QDialog ref="denyFormRef" transition-show="scale" transition-hide="scale">
|
<QDialog ref="denyFormRef" transition-show="scale" transition-hide="scale">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { dateRange } from 'src/filters';
|
import { dateRange } from 'src/filters';
|
||||||
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
|
@ -7,6 +7,8 @@ import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||||
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -21,7 +23,8 @@ const stateOptions = [
|
||||||
{ code: 'accepted', name: t('accepted') },
|
{ code: 'accepted', name: t('accepted') },
|
||||||
{ code: 'denied', name: t('denied') },
|
{ code: 'denied', name: t('denied') },
|
||||||
];
|
];
|
||||||
|
const arrayData = useArrayData(props.dataKey);
|
||||||
|
const fieldFiltersValues = ref([]);
|
||||||
const itemTypesOptions = ref([]);
|
const itemTypesOptions = ref([]);
|
||||||
const warehousesOptions = ref([]);
|
const warehousesOptions = ref([]);
|
||||||
|
|
||||||
|
@ -56,6 +59,19 @@ const decrement = (paramsObj, key) => {
|
||||||
|
|
||||||
paramsObj[key]--;
|
paramsObj[key]--;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
if (arrayData.store?.userParams) {
|
||||||
|
fieldFiltersValues.value = Object.entries(arrayData.store.userParams).map(
|
||||||
|
([key, value]) => ({
|
||||||
|
name: key,
|
||||||
|
value,
|
||||||
|
selectedField: { name: key, label: t(`params.${key}`) },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
exprBuilder('state', arrayData.store?.userParams?.state);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -145,33 +161,17 @@ const decrement = (paramsObj, key) => {
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
:label="t('params.requesterFk')"
|
:label="t('params.requesterFk')"
|
||||||
v-model="params.requesterFk"
|
v-model="params.requesterFk"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
url="Workers/search"
|
|
||||||
:fields="['id', 'name']"
|
:fields="['id', 'name']"
|
||||||
order="name ASC"
|
|
||||||
:params="{ departmentCodes: ['VT'] }"
|
:params="{ departmentCodes: ['VT'] }"
|
||||||
option-value="id"
|
|
||||||
option-label="name"
|
|
||||||
hide-selected
|
hide-selected
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
>
|
/>
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption
|
|
||||||
>{{ scope.opt?.nickname }},
|
|
||||||
{{ scope.opt?.code }}</QItemLabel
|
|
||||||
>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
|
|
|
@ -10,7 +10,6 @@ const { t } = useI18n();
|
||||||
url="ItemTypes"
|
url="ItemTypes"
|
||||||
:label="t('Search item type')"
|
:label="t('Search item type')"
|
||||||
:info="t('Search itemType by id, name or code')"
|
:info="t('Search itemType by id, name or code')"
|
||||||
search-url="table"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import VnTable from 'components/VnTable/VnTable.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||||
import ItemTypeFilter from './ItemType/ItemTypeFilter.vue';
|
import ItemTypeFilter from './ItemType/ItemTypeFilter.vue';
|
||||||
|
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
|
@ -31,13 +32,14 @@ const columns = computed(() => [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: t('name'),
|
label: t('globals.name'),
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
create: true,
|
create: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: t('worker'),
|
label: t('worker'),
|
||||||
|
name: 'workerFk',
|
||||||
create: true,
|
create: true,
|
||||||
component: 'select',
|
component: 'select',
|
||||||
attrs: {
|
attrs: {
|
||||||
|
@ -45,20 +47,20 @@ const columns = computed(() => [
|
||||||
optionLabel: 'nickname',
|
optionLabel: 'nickname',
|
||||||
optionValue: 'id',
|
optionValue: 'id',
|
||||||
},
|
},
|
||||||
|
format: (row) => row.worker?.user?.name,
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
visible: true,
|
columnField: { component: null },
|
||||||
columnField: {
|
|
||||||
component: 'userLink',
|
|
||||||
attrs: ({ row }) => {
|
|
||||||
return {
|
|
||||||
workerId: row?.worker?.id,
|
|
||||||
name: row.worker?.user?.name,
|
|
||||||
defaultName: true,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
columnFilter: {
|
columnFilter: {
|
||||||
name: 'workerFk',
|
attrs: {
|
||||||
|
url: 'Workers/activeWithInheritedRole',
|
||||||
|
fields: ['id', 'name'],
|
||||||
|
where: { role: 'buyer' },
|
||||||
|
optionFilter: 'firstName',
|
||||||
|
optionLabel: 'name',
|
||||||
|
optionValue: 'id',
|
||||||
|
useLike: false,
|
||||||
|
},
|
||||||
|
inWhere: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -135,24 +137,27 @@ const columns = computed(() => [
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
auto-load
|
auto-load
|
||||||
:right-search="false"
|
:right-search="false"
|
||||||
:is-editable="false"
|
|
||||||
:use-model="true"
|
|
||||||
redirect="item/item-type"
|
redirect="item/item-type"
|
||||||
/>
|
>
|
||||||
|
<template #column-workerFk="{ row }">
|
||||||
|
<span class="link" @click.stop>
|
||||||
|
{{ row.worker?.user?.name }}
|
||||||
|
<WorkerDescriptorProxy :id="row.workerFk" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
id: Id
|
id: Id
|
||||||
code: Código
|
code: Código
|
||||||
name: Nombre
|
|
||||||
worker: Trabajador
|
worker: Trabajador
|
||||||
ItemCategory: Reino
|
ItemCategory: Reino
|
||||||
Temperature: Temperatura
|
Temperature: Temperatura
|
||||||
Create ItemTypes: Crear familia
|
Create ItemTypes: Crear familia
|
||||||
en:
|
en:
|
||||||
code: Code
|
code: Code
|
||||||
name: Name
|
|
||||||
worker: Worker
|
worker: Worker
|
||||||
ItemCategory: ItemCategory
|
ItemCategory: ItemCategory
|
||||||
Temperature: Temperature
|
Temperature: Temperature
|
||||||
|
|
|
@ -66,6 +66,7 @@ lastEntries:
|
||||||
package: Package
|
package: Package
|
||||||
freight: Freight
|
freight: Freight
|
||||||
comission: Comission
|
comission: Comission
|
||||||
|
printedStickers: Pri.
|
||||||
itemTags:
|
itemTags:
|
||||||
removeTag: Remove tag
|
removeTag: Remove tag
|
||||||
addTag: Add tag
|
addTag: Add tag
|
||||||
|
@ -95,6 +96,15 @@ item:
|
||||||
mine: For me
|
mine: For me
|
||||||
state: State
|
state: State
|
||||||
myTeam: My team
|
myTeam: My team
|
||||||
|
shipped: Shipped
|
||||||
|
description: Description
|
||||||
|
quantity: Quantity
|
||||||
|
price: Price
|
||||||
|
item: Item
|
||||||
|
achieved: Achieved
|
||||||
|
concept: Concept
|
||||||
|
denyOptions: Deny
|
||||||
|
scopeDays: Scope days
|
||||||
searchbar:
|
searchbar:
|
||||||
label: Search item
|
label: Search item
|
||||||
descriptor:
|
descriptor:
|
||||||
|
@ -112,7 +122,7 @@ item:
|
||||||
title: All its properties will be copied
|
title: All its properties will be copied
|
||||||
subTitle: Do you want to clone this item?
|
subTitle: Do you want to clone this item?
|
||||||
list:
|
list:
|
||||||
id: Identifier
|
id: Id
|
||||||
grouping: Grouping
|
grouping: Grouping
|
||||||
packing: Packing
|
packing: Packing
|
||||||
description: Description
|
description: Description
|
||||||
|
@ -122,8 +132,9 @@ item:
|
||||||
intrastat: Intrastat
|
intrastat: Intrastat
|
||||||
isActive: Active
|
isActive: Active
|
||||||
size: Size
|
size: Size
|
||||||
origin: Origin
|
origin: Orig.
|
||||||
userName: Buyer
|
userName: Buyer
|
||||||
|
weight: Weight
|
||||||
weightByPiece: Weight/Piece
|
weightByPiece: Weight/Piece
|
||||||
stemMultiplier: Multiplier
|
stemMultiplier: Multiplier
|
||||||
producer: Producer
|
producer: Producer
|
||||||
|
|
|
@ -56,7 +56,7 @@ lastEntries:
|
||||||
landed: F. Entrega
|
landed: F. Entrega
|
||||||
entry: Entrada
|
entry: Entrada
|
||||||
pvp: PVP
|
pvp: PVP
|
||||||
label: Etiquetas
|
label: Eti.
|
||||||
grouping: Grouping
|
grouping: Grouping
|
||||||
quantity: Cantidad
|
quantity: Cantidad
|
||||||
cost: Coste
|
cost: Coste
|
||||||
|
@ -66,6 +66,7 @@ lastEntries:
|
||||||
package: Embalaje
|
package: Embalaje
|
||||||
freight: Porte
|
freight: Porte
|
||||||
comission: Comisión
|
comission: Comisión
|
||||||
|
printedStickers: Imp.
|
||||||
itemTags:
|
itemTags:
|
||||||
removeTag: Quitar etiqueta
|
removeTag: Quitar etiqueta
|
||||||
addTag: Añadir etiqueta
|
addTag: Añadir etiqueta
|
||||||
|
@ -97,6 +98,15 @@ item:
|
||||||
mine: Para mi
|
mine: Para mi
|
||||||
state: Estado
|
state: Estado
|
||||||
myTeam: Mi equipo
|
myTeam: Mi equipo
|
||||||
|
shipped: Enviado
|
||||||
|
description: Descripción
|
||||||
|
quantity: Cantidad
|
||||||
|
price: Precio
|
||||||
|
item: Artículo
|
||||||
|
achieved: Conseguido
|
||||||
|
concept: Concepto
|
||||||
|
denyOptions: Denegado
|
||||||
|
scopeDays: Días en adelante
|
||||||
searchbar:
|
searchbar:
|
||||||
label: Buscar artículo
|
label: Buscar artículo
|
||||||
descriptor:
|
descriptor:
|
||||||
|
@ -114,7 +124,7 @@ item:
|
||||||
title: Todas sus propiedades serán copiadas
|
title: Todas sus propiedades serán copiadas
|
||||||
subTitle: ¿Desea clonar este artículo?
|
subTitle: ¿Desea clonar este artículo?
|
||||||
list:
|
list:
|
||||||
id: Identificador
|
id: Id
|
||||||
grouping: Grouping
|
grouping: Grouping
|
||||||
packing: Packing
|
packing: Packing
|
||||||
description: Descripción
|
description: Descripción
|
||||||
|
@ -124,7 +134,8 @@ item:
|
||||||
intrastat: Intrastat
|
intrastat: Intrastat
|
||||||
isActive: Activo
|
isActive: Activo
|
||||||
size: Medida
|
size: Medida
|
||||||
origin: Origen
|
origin: Orig.
|
||||||
|
weight: Peso
|
||||||
weightByPiece: Peso (gramos)/tallo
|
weightByPiece: Peso (gramos)/tallo
|
||||||
userName: Comprador
|
userName: Comprador
|
||||||
stemMultiplier: Multiplicador
|
stemMultiplier: Multiplicador
|
||||||
|
|
|
@ -9,6 +9,7 @@ import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||||
import FetchData from 'src/components/FetchData.vue';
|
import FetchData from 'src/components/FetchData.vue';
|
||||||
import { dateRange } from 'src/filters';
|
import { dateRange } from 'src/filters';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
defineProps({ dataKey: { type: String, required: true } });
|
defineProps({ dataKey: { type: String, required: true } });
|
||||||
const { t, te } = useI18n();
|
const { t, te } = useI18n();
|
||||||
|
@ -112,33 +113,16 @@ const getLocale = (label) => {
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
outlined
|
outlined
|
||||||
dense
|
dense
|
||||||
rounded
|
rounded
|
||||||
:label="t('globals.params.salesPersonFk')"
|
:label="t('globals.params.salesPersonFk')"
|
||||||
v-model="params.salesPersonFk"
|
v-model="params.salesPersonFk"
|
||||||
url="Workers/search"
|
|
||||||
:params="{ departmentCodes: ['VT'] }"
|
:params="{ departmentCodes: ['VT'] }"
|
||||||
is-outlined
|
|
||||||
option-value="id"
|
|
||||||
option-label="name"
|
|
||||||
:no-one="true"
|
:no-one="true"
|
||||||
>
|
>
|
||||||
<template #option="{ opt, itemProps }">
|
</VnSelectWorker>
|
||||||
<QItem v-bind="itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ opt.name }}</QItemLabel>
|
|
||||||
<QItemLabel
|
|
||||||
v-if="opt.code"
|
|
||||||
class="text-grey text-caption"
|
|
||||||
>
|
|
||||||
{{ `${opt.nickname}, ${opt.code}` }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
|
@ -150,6 +134,7 @@ const getLocale = (label) => {
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
|
@ -225,6 +210,34 @@ const getLocale = (label) => {
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnSelect
|
||||||
|
outlined
|
||||||
|
dense
|
||||||
|
rounded
|
||||||
|
:label="t('globals.params.departmentFk')"
|
||||||
|
v-model="params.department"
|
||||||
|
option-label="name"
|
||||||
|
option-value="name"
|
||||||
|
url="Departments"
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnSelect
|
||||||
|
outlined
|
||||||
|
dense
|
||||||
|
rounded
|
||||||
|
:label="t('globals.params.packing')"
|
||||||
|
v-model="params.packing"
|
||||||
|
url="ItemPackingTypes"
|
||||||
|
option-label="code"
|
||||||
|
option-value="code"
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
|
|
|
@ -10,20 +10,23 @@ import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
|
||||||
import TicketSummary from 'src/pages/Ticket/Card/TicketSummary.vue';
|
import TicketSummary from 'src/pages/Ticket/Card/TicketSummary.vue';
|
||||||
import VnTable from 'components/VnTable/VnTable.vue';
|
import VnTable from 'components/VnTable/VnTable.vue';
|
||||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
import { toDateFormat } from 'src/filters/date.js';
|
|
||||||
import { toCurrency, dateRange, dashIfEmpty } from 'src/filters';
|
import { toCurrency, dateRange, dashIfEmpty } from 'src/filters';
|
||||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||||
import MonitorTicketSearchbar from './MonitorTicketSearchbar.vue';
|
import MonitorTicketSearchbar from './MonitorTicketSearchbar.vue';
|
||||||
import MonitorTicketFilter from './MonitorTicketFilter.vue';
|
import MonitorTicketFilter from './MonitorTicketFilter.vue';
|
||||||
import TicketProblems from 'src/components/TicketProblems.vue';
|
import TicketProblems from 'src/components/TicketProblems.vue';
|
||||||
|
import VnDateBadge from 'src/components/common/VnDateBadge.vue';
|
||||||
|
|
||||||
const DEFAULT_AUTO_REFRESH = 2 * 60 * 1000; // 2min in ms
|
const DEFAULT_AUTO_REFRESH = 2 * 60 * 1000;
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const autoRefresh = ref(false);
|
const autoRefresh = ref(false);
|
||||||
const tableRef = ref(null);
|
const tableRef = ref(null);
|
||||||
const provinceOpts = ref([]);
|
const provinceOpts = ref([]);
|
||||||
const stateOpts = ref([]);
|
const stateOpts = ref([]);
|
||||||
const zoneOpts = ref([]);
|
const zoneOpts = ref([]);
|
||||||
|
const DepartmentOpts = ref([]);
|
||||||
|
const ItemPackingTypeOpts = ref([]);
|
||||||
|
const visibleColumns = ref([]);
|
||||||
const { viewSummary } = useSummaryDialog();
|
const { viewSummary } = useSummaryDialog();
|
||||||
|
|
||||||
const [from, to] = dateRange(Date.vnNew());
|
const [from, to] = dateRange(Date.vnNew());
|
||||||
|
@ -51,6 +54,8 @@ function exprBuilder(param, value) {
|
||||||
case 'nickname':
|
case 'nickname':
|
||||||
return { [`t.nickname`]: { like: `%${value}%` } };
|
return { [`t.nickname`]: { like: `%${value}%` } };
|
||||||
case 'zoneFk':
|
case 'zoneFk':
|
||||||
|
case 'department':
|
||||||
|
return { 'd.name': value };
|
||||||
case 'totalWithVat':
|
case 'totalWithVat':
|
||||||
return { [`t.${param}`]: value };
|
return { [`t.${param}`]: value };
|
||||||
}
|
}
|
||||||
|
@ -137,6 +142,7 @@ const columns = computed(() => [
|
||||||
align: 'left',
|
align: 'left',
|
||||||
format: (row) => row.practicalHour,
|
format: (row) => row.practicalHour,
|
||||||
columnFilter: false,
|
columnFilter: false,
|
||||||
|
dense: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('salesTicketsTable.preparation'),
|
label: t('salesTicketsTable.preparation'),
|
||||||
|
@ -190,6 +196,7 @@ const columns = computed(() => [
|
||||||
'false-value': 0,
|
'false-value': 0,
|
||||||
'true-value': 1,
|
'true-value': 1,
|
||||||
},
|
},
|
||||||
|
component: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('salesTicketsTable.zone'),
|
label: t('salesTicketsTable.zone'),
|
||||||
|
@ -206,6 +213,12 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: t('salesTicketsTable.payMethod'),
|
||||||
|
name: 'payMethod',
|
||||||
|
align: 'left',
|
||||||
|
columnFilter: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: t('salesTicketsTable.total'),
|
label: t('salesTicketsTable.total'),
|
||||||
name: 'totalWithVat',
|
name: 'totalWithVat',
|
||||||
|
@ -219,6 +232,36 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: t('salesTicketsTable.department'),
|
||||||
|
name: 'department',
|
||||||
|
align: 'left',
|
||||||
|
columnFilter: {
|
||||||
|
component: 'select',
|
||||||
|
url: 'Departments',
|
||||||
|
attrs: {
|
||||||
|
options: DepartmentOpts.value,
|
||||||
|
optionValue: 'name',
|
||||||
|
optionLabel: 'name',
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('salesTicketsTable.packing'),
|
||||||
|
name: 'packing',
|
||||||
|
align: 'left',
|
||||||
|
columnFilter: {
|
||||||
|
component: 'select',
|
||||||
|
url: 'ItemPackingTypes',
|
||||||
|
attrs: {
|
||||||
|
options: ItemPackingTypeOpts.value,
|
||||||
|
'option-value': 'code',
|
||||||
|
'option-label': 'code',
|
||||||
|
dense: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
align: 'right',
|
align: 'right',
|
||||||
name: 'tableActions',
|
name: 'tableActions',
|
||||||
|
@ -250,19 +293,6 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const getBadgeAttrs = (date) => {
|
|
||||||
let today = Date.vnNew();
|
|
||||||
today.setHours(0, 0, 0, 0);
|
|
||||||
let timeTicket = new Date(date);
|
|
||||||
timeTicket.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
let timeDiff = today - timeTicket;
|
|
||||||
|
|
||||||
if (timeDiff == 0) return { color: 'warning', 'text-color': 'black' };
|
|
||||||
if (timeDiff < 0) return { color: 'success', 'text-color': 'black' };
|
|
||||||
return { color: 'transparent', 'text-color': 'white' };
|
|
||||||
};
|
|
||||||
|
|
||||||
let refreshTimer = null;
|
let refreshTimer = null;
|
||||||
|
|
||||||
const autoRefreshHandler = (value) => {
|
const autoRefreshHandler = (value) => {
|
||||||
|
@ -279,14 +309,6 @@ const totalPriceColor = (ticket) => {
|
||||||
if (total > 0 && total < 50) return 'warning';
|
if (total > 0 && total < 50) return 'warning';
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatShippedDate = (date) => {
|
|
||||||
if (!date) return '-';
|
|
||||||
const dateSplit = date.split('T');
|
|
||||||
const [year, month, day] = dateSplit[0].split('-');
|
|
||||||
const newDate = new Date(year, month - 1, day);
|
|
||||||
return toDateFormat(newDate);
|
|
||||||
};
|
|
||||||
|
|
||||||
const openTab = (id) =>
|
const openTab = (id) =>
|
||||||
window.open(`#/ticket/${id}/sale`, '_blank', 'noopener, noreferrer');
|
window.open(`#/ticket/${id}/sale`, '_blank', 'noopener, noreferrer');
|
||||||
</script>
|
</script>
|
||||||
|
@ -318,6 +340,24 @@ const openTab = (id) =>
|
||||||
auto-load
|
auto-load
|
||||||
@on-fetch="(data) => (zoneOpts = data)"
|
@on-fetch="(data) => (zoneOpts = data)"
|
||||||
/>
|
/>
|
||||||
|
<FetchData
|
||||||
|
url="ItemPackingTypes"
|
||||||
|
:filter="{
|
||||||
|
fields: ['code'],
|
||||||
|
order: 'code ASC',
|
||||||
|
}"
|
||||||
|
auto-load
|
||||||
|
@on-fetch="(data) => (ItemPackingTypeOpts = data)"
|
||||||
|
/>
|
||||||
|
<FetchData
|
||||||
|
url="Departments"
|
||||||
|
:filter="{
|
||||||
|
fields: ['id', 'name'],
|
||||||
|
order: 'id ASC',
|
||||||
|
}"
|
||||||
|
auto-load
|
||||||
|
@on-fetch="(data) => (DepartmentOpts = data)"
|
||||||
|
/>
|
||||||
<MonitorTicketSearchbar />
|
<MonitorTicketSearchbar />
|
||||||
<RightMenu>
|
<RightMenu>
|
||||||
<template #right-panel>
|
<template #right-panel>
|
||||||
|
@ -337,7 +377,7 @@ const openTab = (id) =>
|
||||||
auto-load
|
auto-load
|
||||||
:row-click="({ id }) => openTab(id)"
|
:row-click="({ id }) => openTab(id)"
|
||||||
:disable-option="{ card: true }"
|
:disable-option="{ card: true }"
|
||||||
:user-params="{ from, to, scopeDays: 0 }"
|
:user-params="{ from, to, scopeDays: 0, packing }"
|
||||||
>
|
>
|
||||||
<template #top-left>
|
<template #top-left>
|
||||||
<QBtn
|
<QBtn
|
||||||
|
@ -382,13 +422,7 @@ const openTab = (id) =>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #column-shippedDate="{ row }">
|
<template #column-shippedDate="{ row }">
|
||||||
<QBadge
|
<VnDateBadge :date="row.shippedDate" />
|
||||||
v-bind="getBadgeAttrs(row.shippedDate)"
|
|
||||||
class="q-pa-sm"
|
|
||||||
style="font-size: 14px"
|
|
||||||
>
|
|
||||||
{{ formatShippedDate(row.shippedDate) }}
|
|
||||||
</QBadge>
|
|
||||||
</template>
|
</template>
|
||||||
<template #column-provinceFk="{ row }">
|
<template #column-provinceFk="{ row }">
|
||||||
<span :title="row.province" v-text="row.province" />
|
<span :title="row.province" v-text="row.province" />
|
||||||
|
|
|
@ -26,8 +26,8 @@ salesTicketsTable:
|
||||||
componentLack: Component lack
|
componentLack: Component lack
|
||||||
tooLittle: Ticket too little
|
tooLittle: Ticket too little
|
||||||
identifier: Identifier
|
identifier: Identifier
|
||||||
theoretical: Theoretical
|
theoretical: H.Theor
|
||||||
practical: Practical
|
practical: H.Prac
|
||||||
province: Province
|
province: Province
|
||||||
state: State
|
state: State
|
||||||
isFragile: Is fragile
|
isFragile: Is fragile
|
||||||
|
@ -35,7 +35,10 @@ salesTicketsTable:
|
||||||
goToLines: Go to lines
|
goToLines: Go to lines
|
||||||
preview: Preview
|
preview: Preview
|
||||||
total: Total
|
total: Total
|
||||||
preparation: Preparation
|
preparation: H.Prep
|
||||||
|
payMethod: Pay method
|
||||||
|
department: Department
|
||||||
|
packing: ITP
|
||||||
searchBar:
|
searchBar:
|
||||||
label: Search tickets
|
label: Search tickets
|
||||||
info: Search tickets by id or alias
|
info: Search tickets by id or alias
|
||||||
|
|
|
@ -26,8 +26,8 @@ salesTicketsTable:
|
||||||
componentLack: Faltan componentes
|
componentLack: Faltan componentes
|
||||||
tooLittle: Ticket demasiado pequeño
|
tooLittle: Ticket demasiado pequeño
|
||||||
identifier: Identificador
|
identifier: Identificador
|
||||||
theoretical: Teórica
|
theoretical: H.Teór
|
||||||
practical: Práctica
|
practical: H.Prác
|
||||||
province: Provincia
|
province: Provincia
|
||||||
state: Estado
|
state: Estado
|
||||||
isFragile: Es frágil
|
isFragile: Es frágil
|
||||||
|
@ -35,7 +35,10 @@ salesTicketsTable:
|
||||||
goToLines: Ir a líneas
|
goToLines: Ir a líneas
|
||||||
preview: Vista previa
|
preview: Vista previa
|
||||||
total: Total
|
total: Total
|
||||||
preparation: Preparación
|
preparation: H.Prep
|
||||||
|
payMethod: Método de pago
|
||||||
|
department: Departamento
|
||||||
|
packing: ITP
|
||||||
searchBar:
|
searchBar:
|
||||||
label: Buscar tickets
|
label: Buscar tickets
|
||||||
info: Buscar tickets por identificador o alias
|
info: Buscar tickets por identificador o alias
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { onMounted, onUnmounted, ref, computed, watch, provide, nextTick } from 'vue';
|
import { onMounted, ref, computed, watch, provide } from 'vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
||||||
|
@ -30,8 +30,6 @@ onMounted(() => {
|
||||||
checkOrderConfirmation();
|
checkOrderConfirmation();
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
|
|
||||||
async function checkOrderConfirmation() {
|
async function checkOrderConfirmation() {
|
||||||
const response = await axios.get(`Orders/${route.params.id}`);
|
const response = await axios.get(`Orders/${route.params.id}`);
|
||||||
if (response.data.isConfirmed === 1) {
|
if (response.data.isConfirmed === 1) {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { reactive, onMounted, ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useState } from 'composables/useState';
|
|
||||||
import FormModelPopup from 'components/FormModelPopup.vue';
|
import FormModelPopup from 'components/FormModelPopup.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
|
@ -11,29 +10,12 @@ import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
import { useDialogPluginComponent } from 'quasar';
|
import { useDialogPluginComponent } from 'quasar';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const state = useState();
|
|
||||||
const ORDER_MODEL = 'order';
|
const ORDER_MODEL = 'order';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const agencyList = ref([]);
|
const agencyList = ref([]);
|
||||||
const addressList = ref([]);
|
|
||||||
defineEmits(['confirm', ...useDialogPluginComponent.emits]);
|
defineEmits(['confirm', ...useDialogPluginComponent.emits]);
|
||||||
|
|
||||||
const fetchAddressList = async (addressId) => {
|
|
||||||
const { data } = await axios.get('addresses', {
|
|
||||||
params: {
|
|
||||||
filter: JSON.stringify({
|
|
||||||
fields: ['id', 'nickname', 'street', 'city'],
|
|
||||||
where: { id: addressId },
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
addressList.value = data;
|
|
||||||
if (addressList.value?.length === 1) {
|
|
||||||
state.get(ORDER_MODEL).addressId = addressList.value[0].id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchAgencyList = async (landed, addressFk) => {
|
const fetchAgencyList = async (landed, addressFk) => {
|
||||||
if (!landed || !addressFk) {
|
if (!landed || !addressFk) {
|
||||||
return;
|
return;
|
||||||
|
@ -59,17 +41,9 @@ const initialFormState = reactive({
|
||||||
clientFk: $props.clientFk,
|
clientFk: $props.clientFk,
|
||||||
});
|
});
|
||||||
|
|
||||||
const onClientChange = async (clientId = $props.clientFk) => {
|
|
||||||
const { data } = await axios.get(`Clients/${clientId}`);
|
|
||||||
await fetchAddressList(data.defaultAddressFk);
|
|
||||||
};
|
|
||||||
|
|
||||||
async function onDataSaved(_, id) {
|
async function onDataSaved(_, id) {
|
||||||
await router.push({ path: `/order/${id}/catalog` });
|
await router.push({ path: `/order/${id}/catalog` });
|
||||||
}
|
}
|
||||||
onMounted(async () => {
|
|
||||||
await onClientChange();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -90,10 +64,9 @@ onMounted(async () => {
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="name"
|
option-label="name"
|
||||||
:filter="{
|
:filter="{
|
||||||
fields: ['id', 'name', 'defaultAddressFk'],
|
fields: ['id', 'name'],
|
||||||
}"
|
}"
|
||||||
hide-selected
|
hide-selected
|
||||||
@update:model-value="onClientChange"
|
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
@ -110,7 +83,7 @@ onMounted(async () => {
|
||||||
:label="t('order.form.addressFk')"
|
:label="t('order.form.addressFk')"
|
||||||
v-model="data.addressId"
|
v-model="data.addressId"
|
||||||
url="addresses"
|
url="addresses"
|
||||||
:fields="['id', 'nickname', 'defaultAddressFk', 'street', 'city']"
|
:fields="['id', 'nickname', 'street', 'city']"
|
||||||
sort-by="id"
|
sort-by="id"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="street"
|
option-label="street"
|
||||||
|
|
|
@ -6,6 +6,7 @@ import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
import VnInput from 'components/common/VnInput.vue';
|
import VnInput from 'components/common/VnInput.vue';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -61,28 +62,16 @@ const sourceList = ref([]);
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
:label="t('salesPerson')"
|
:label="t('globals.salesPerson')"
|
||||||
v-model="params.workerFk"
|
v-model="params.workerFk"
|
||||||
url="Workers/search"
|
:params="{
|
||||||
:filter="{ departmentCodes: ['VT'] }"
|
departmentCodes: ['VT'],
|
||||||
sort-by="nickname ASC"
|
}"
|
||||||
option-label="nickname"
|
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
>
|
/>
|
||||||
<template #option="{ itemProps, opt }">
|
|
||||||
<QItem v-bind="itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ opt.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption>
|
|
||||||
{{ opt.nickname }},{{ opt.code }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
<VnInputDate
|
<VnInputDate
|
||||||
v-model="params.from"
|
v-model="params.from"
|
||||||
:label="t('fromLanded')"
|
:label="t('fromLanded')"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { computed, onMounted, ref } from 'vue';
|
import { computed, ref, onMounted } from 'vue';
|
||||||
import { dashIfEmpty, toCurrency, toDate } from 'src/filters';
|
import { dashIfEmpty, toCurrency, toDate } from 'src/filters';
|
||||||
import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
|
import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
|
||||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
|
@ -15,14 +15,13 @@ import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vu
|
||||||
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
|
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
import { toDateTimeFormat } from 'src/filters/date';
|
import { toDateTimeFormat } from 'src/filters/date';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import dataByOrder from 'src/utils/dataByOrder';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { viewSummary } = useSummaryDialog();
|
const { viewSummary } = useSummaryDialog();
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const agencyList = ref([]);
|
const agencyList = ref([]);
|
||||||
const addressesList = ref([]);
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const addressOptions = ref([]);
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -148,16 +147,12 @@ onMounted(() => {
|
||||||
const id = JSON.parse(clientId);
|
const id = JSON.parse(clientId);
|
||||||
fetchClientAddress(id.clientFk);
|
fetchClientAddress(id.clientFk);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function fetchClientAddress(id, formData = {}) {
|
async function fetchClientAddress(id, formData = {}) {
|
||||||
const { data } = await axios.get(`Clients/${id}`, {
|
const { data } = await axios.get(
|
||||||
params: {
|
`Clients/${id}/addresses?filter[order]=isActive DESC`
|
||||||
filter: {
|
);
|
||||||
order: ['isDefaultAddress DESC', 'isActive DESC', 'nickname ASC'],
|
addressOptions.value = data;
|
||||||
include: { relation: 'addresses' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
addressesList.value = data.addresses;
|
|
||||||
formData.addressId = data.defaultAddressFk;
|
formData.addressId = data.defaultAddressFk;
|
||||||
fetchAgencies(formData);
|
fetchAgencies(formData);
|
||||||
}
|
}
|
||||||
|
@ -168,7 +163,7 @@ async function fetchAgencies({ landed, addressId }) {
|
||||||
const { data } = await axios.get('Agencies/landsThatDay', {
|
const { data } = await axios.get('Agencies/landsThatDay', {
|
||||||
params: { addressFk: addressId, landed },
|
params: { addressFk: addressId, landed },
|
||||||
});
|
});
|
||||||
agencyList.value = dataByOrder(data, 'agencyMode ASC');
|
agencyList.value = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getDateColor = (date) => {
|
const getDateColor = (date) => {
|
||||||
|
@ -252,34 +247,29 @@ const getDateColor = (date) => {
|
||||||
</VnSelect>
|
</VnSelect>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-model="data.addressId"
|
v-model="data.addressId"
|
||||||
:options="addressesList"
|
:options="addressOptions"
|
||||||
:label="t('module.address')"
|
:label="t('module.address')"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="nickname"
|
option-label="nickname"
|
||||||
@update:model-value="() => fetchAgencies(data)"
|
@update:model-value="() => fetchAgencies(data)"
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem
|
<QItem v-bind="scope.itemProps">
|
||||||
v-bind="scope.itemProps"
|
|
||||||
:class="{ disabled: !scope.opt.isActive }"
|
|
||||||
>
|
|
||||||
<QItemSection style="min-width: min-content" avatar>
|
|
||||||
<QIcon
|
|
||||||
v-if="
|
|
||||||
scope.opt.isActive && data.addressId === scope.opt.id
|
|
||||||
"
|
|
||||||
size="sm"
|
|
||||||
color="grey"
|
|
||||||
name="star"
|
|
||||||
class="fill-icon"
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QItemLabel>
|
<QItemLabel
|
||||||
{{ scope.opt.nickname }}
|
:class="{
|
||||||
</QItemLabel>
|
'color-vn-label': !scope.opt?.isActive,
|
||||||
<QItemLabel caption>
|
}"
|
||||||
{{ `${scope.opt.street}, ${scope.opt.city}` }}
|
>
|
||||||
|
{{
|
||||||
|
`${
|
||||||
|
!scope.opt?.isActive
|
||||||
|
? t('basicData.inactive')
|
||||||
|
: ''
|
||||||
|
} `
|
||||||
|
}}
|
||||||
|
{{ scope.opt?.nickname }}: {{ scope.opt?.street }},
|
||||||
|
{{ scope.opt?.city }}
|
||||||
</QItemLabel>
|
</QItemLabel>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import VnFilterPanel from 'components/ui/VnFilterPanel.vue';
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
import VnInput from 'components/common/VnInput.vue';
|
import VnInput from 'components/common/VnInput.vue';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -31,29 +32,13 @@ const emit = defineEmits(['search']);
|
||||||
<template #body="{ params }">
|
<template #body="{ params }">
|
||||||
<QItem class="q-my-sm">
|
<QItem class="q-my-sm">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
:label="t('Worker')"
|
|
||||||
v-model="params.workerFk"
|
v-model="params.workerFk"
|
||||||
url="Workers/search"
|
|
||||||
sort-by="nickname ASC"
|
|
||||||
option-value="id"
|
|
||||||
option-label="nickname"
|
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
:input-debounce="0"
|
:input-debounce="0"
|
||||||
>
|
/>
|
||||||
<template #option="{ itemProps, opt }">
|
|
||||||
<QItem v-bind="itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ opt.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption>
|
|
||||||
{{ opt.nickname }},{{ opt.code }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem class="q-my-sm">
|
<QItem class="q-my-sm">
|
||||||
|
|
|
@ -11,6 +11,7 @@ import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
import VnInput from 'components/common/VnInput.vue';
|
import VnInput from 'components/common/VnInput.vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import VnInputTime from 'components/common/VnInputTime.vue';
|
import VnInputTime from 'components/common/VnInputTime.vue';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -94,26 +95,7 @@ const onSave = (data, response) => {
|
||||||
>
|
>
|
||||||
<template #form="{ data }">
|
<template #form="{ data }">
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnSelect
|
<VnSelectWorker v-model="data.workerFk" />
|
||||||
:label="t('Worker')"
|
|
||||||
v-model="data.workerFk"
|
|
||||||
url="Workers/search"
|
|
||||||
sort-by="nickname ASC"
|
|
||||||
option-value="id"
|
|
||||||
option-label="nickname"
|
|
||||||
:input-debounce="0"
|
|
||||||
>
|
|
||||||
<template #option="{ itemProps, opt }">
|
|
||||||
<QItem v-bind="itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ opt.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption>
|
|
||||||
{{ opt.nickname }}, {{ opt.code }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('Vehicle')"
|
:label="t('Vehicle')"
|
||||||
v-model="data.vehicleFk"
|
v-model="data.vehicleFk"
|
||||||
|
|
|
@ -223,10 +223,10 @@ function navigate(id) {
|
||||||
router.push({ path: `/route/${id}` });
|
router.push({ path: `/route/${id}` });
|
||||||
}
|
}
|
||||||
|
|
||||||
const cloneRoutes = () => {
|
const cloneRoutes = async () => {
|
||||||
if (!selectedRows.value.length || !startingDate.value) return;
|
if (!selectedRows.value.length || !startingDate.value) return;
|
||||||
axios.post('Routes/clone', {
|
await axios.post('Routes/clone', {
|
||||||
created: startingDate.value,
|
dated: startingDate.value,
|
||||||
ids: selectedRows.value.map((row) => row?.id),
|
ids: selectedRows.value.map((row) => row?.id),
|
||||||
});
|
});
|
||||||
startingDate.value = null;
|
startingDate.value = null;
|
||||||
|
@ -274,7 +274,6 @@ const openTicketsDialog = (id) => {
|
||||||
<QCardSection>
|
<QCardSection>
|
||||||
<p class="text-h6 q-ma-none">{{ t('route.Select the starting date') }}</p>
|
<p class="text-h6 q-ma-none">{{ t('route.Select the starting date') }}</p>
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
|
|
||||||
<QCardSection class="q-pt-none">
|
<QCardSection class="q-pt-none">
|
||||||
<VnInputDate
|
<VnInputDate
|
||||||
:label="t('route.Stating date')"
|
:label="t('route.Stating date')"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import VnPaginate from 'components/ui/VnPaginate.vue';
|
import VnPaginate from 'components/ui/VnPaginate.vue';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { onMounted, onUnmounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
import CardList from 'components/ui/CardList.vue';
|
import CardList from 'components/ui/CardList.vue';
|
||||||
import VnLv from 'components/ui/VnLv.vue';
|
import VnLv from 'components/ui/VnLv.vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
@ -21,7 +21,6 @@ const filter = {
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => (stateStore.rightDrawer = true));
|
onMounted(() => (stateStore.rightDrawer = true));
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
|
|
||||||
function navigate(id) {
|
function navigate(id) {
|
||||||
router.push({ path: `/shelving/${id}` });
|
router.push({ path: `/shelving/${id}` });
|
||||||
|
|
|
@ -5,6 +5,7 @@ import FormModel from 'components/FormModel.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -30,31 +31,11 @@ const companySizes = [
|
||||||
:rules="validate('supplier.nickname')"
|
:rules="validate('supplier.nickname')"
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
:label="t('supplier.basicData.workerFk')"
|
|
||||||
v-model="data.workerFk"
|
v-model="data.workerFk"
|
||||||
url="Workers/search"
|
has-info="Responsible for approving invoices"
|
||||||
sort-by="nickname ASC"
|
|
||||||
:rules="validate('supplier.workerFk')"
|
:rules="validate('supplier.workerFk')"
|
||||||
>
|
/>
|
||||||
<template #append>
|
|
||||||
<QIcon name="info" class="cursor-pointer">
|
|
||||||
<QTooltip>{{
|
|
||||||
t('Responsible for approving invoices')
|
|
||||||
}}</QTooltip>
|
|
||||||
</QIcon>
|
|
||||||
</template>
|
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption>
|
|
||||||
{{ scope.opt?.nickname }}, {{ scope.opt?.id }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('supplier.basicData.size')"
|
:label="t('supplier.basicData.size')"
|
||||||
v-model="data.companySize"
|
v-model="data.companySize"
|
||||||
|
@ -102,6 +83,5 @@ const companySizes = [
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Responsible for approving invoices: Responsable de aprobar las facturas
|
|
||||||
Small(1-5), Medium(6-50), Big(> 50): Pequeño(1-5), Mediano(6-50), Grande(> 50)
|
Small(1-5), Medium(6-50), Big(> 50): Pequeño(1-5), Mediano(6-50), Grande(> 50)
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
|
import { ref, computed, onMounted, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
|
@ -134,8 +134,6 @@ onMounted(() => {
|
||||||
loadDefaultTicketAction();
|
loadDefaultTicketAction();
|
||||||
ticketHaveNegatives();
|
ticketHaveNegatives();
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
import { ref, computed, onMounted, watch, nextTick } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
@ -168,8 +168,6 @@ const getTicketVolume = async () => {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
stateStore.rightDrawer = true;
|
stateStore.rightDrawer = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -9,6 +9,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const emit = defineEmits(['onRequestCreated']);
|
const emit = defineEmits(['onRequestCreated']);
|
||||||
|
|
||||||
|
@ -46,29 +47,7 @@ const onStateFkChange = (formData) => (formData.userFk = user.value.id);
|
||||||
option-label="name"
|
option-label="name"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelectWorker v-model="data.userFk" :fields="['id', 'name']" />
|
||||||
:label="t('expedition.worker')"
|
|
||||||
v-model="data.userFk"
|
|
||||||
url="Workers/search"
|
|
||||||
fields=" ['id', 'name']"
|
|
||||||
sort-by="name ASC"
|
|
||||||
hide-selected
|
|
||||||
option-label="name"
|
|
||||||
option-value="id"
|
|
||||||
>
|
|
||||||
<template #option="{ opt, itemProps }">
|
|
||||||
<QItem v-bind="itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>
|
|
||||||
{{ opt.name }}
|
|
||||||
</QItemLabel>
|
|
||||||
<QItemLabel caption>
|
|
||||||
{{ opt.nickname }}, {{ opt.code }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template></VnSelect
|
|
||||||
>
|
|
||||||
</VnRow>
|
</VnRow>
|
||||||
</template>
|
</template>
|
||||||
</FormModelPopup>
|
</FormModelPopup>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { computed, ref, toRefs } from 'vue';
|
import { computed, onMounted, ref, toRefs, watch } from 'vue';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
@ -24,6 +24,15 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
restoreTicket();
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.ticket,
|
||||||
|
() => restoreTicket
|
||||||
|
);
|
||||||
|
|
||||||
const { push, currentRoute } = useRouter();
|
const { push, currentRoute } = useRouter();
|
||||||
const { dialog, notify } = useQuasar();
|
const { dialog, notify } = useQuasar();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -42,6 +51,7 @@ const hasPdf = ref();
|
||||||
const weight = ref();
|
const weight = ref();
|
||||||
const hasDocuwareFile = ref();
|
const hasDocuwareFile = ref();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
const canRestoreTicket = ref(false);
|
||||||
const actions = {
|
const actions = {
|
||||||
clone: async () => {
|
clone: async () => {
|
||||||
const opts = { message: t('Ticket cloned'), type: 'positive' };
|
const opts = { message: t('Ticket cloned'), type: 'positive' };
|
||||||
|
@ -373,6 +383,54 @@ async function uploadDocuware(force) {
|
||||||
|
|
||||||
if (data) notify({ message: t('PDF sent!'), type: 'positive' });
|
if (data) notify({ message: t('PDF sent!'), type: 'positive' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const restoreTicket = async () => {
|
||||||
|
const filter = {
|
||||||
|
fields: ['id', 'originFk', 'creationDate', 'newInstance'],
|
||||||
|
where: {
|
||||||
|
originFk: ticketId.value,
|
||||||
|
newInstance: { like: '%"isDeleted":true%' },
|
||||||
|
},
|
||||||
|
order: 'creationDate DESC',
|
||||||
|
limit: 1,
|
||||||
|
};
|
||||||
|
const params = { filter: JSON.stringify(filter) };
|
||||||
|
|
||||||
|
const { data } = await axios.get(`TicketLogs`, { params });
|
||||||
|
|
||||||
|
if (data && data.length) {
|
||||||
|
const now = Date.vnNew();
|
||||||
|
const maxDate = new Date(data[0].creationDate);
|
||||||
|
maxDate.setHours(maxDate.getHours() + 1);
|
||||||
|
if (now <= maxDate) {
|
||||||
|
return (canRestoreTicket.value = true);
|
||||||
|
}
|
||||||
|
return (canRestoreTicket.value = false);
|
||||||
|
}
|
||||||
|
return (canRestoreTicket.value = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function openRestoreConfirmation(force) {
|
||||||
|
if (!force)
|
||||||
|
return quasar
|
||||||
|
.dialog({
|
||||||
|
component: VnConfirm,
|
||||||
|
componentProps: {
|
||||||
|
title: t('Are you sure you want to restore the ticket?'),
|
||||||
|
message: t('You are going to restore this ticket'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.onOk(async () => {
|
||||||
|
ticketToRestore();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ticketToRestore() {
|
||||||
|
const { data } = await axios.post(`Tickets/${ticketId.value}/restore`);
|
||||||
|
if (data) {
|
||||||
|
notify({ message: t('Ticket restored'), type: 'positive' });
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FetchData
|
||||||
|
@ -560,6 +618,12 @@ async function uploadDocuware(force) {
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
<QItemSection>{{ t('Show Proforma') }}</QItemSection>
|
<QItemSection>{{ t('Show Proforma') }}</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
<QItem v-if="canRestoreTicket" @click="openRestoreConfirmation()" v-ripple clickable>
|
||||||
|
<QItemSection avatar>
|
||||||
|
<QIcon name="restore" />
|
||||||
|
</QItemSection>
|
||||||
|
<QItemSection>{{ t('Restore ticket') }}</QItemSection>
|
||||||
|
</QItem>
|
||||||
<QItem
|
<QItem
|
||||||
v-if="isEditable"
|
v-if="isEditable"
|
||||||
@click="showChangeTimeDialog = !showChangeTimeDialog"
|
@click="showChangeTimeDialog = !showChangeTimeDialog"
|
||||||
|
@ -746,4 +810,8 @@ es:
|
||||||
You are going to delete this ticket: Vas a eliminar este ticket
|
You are going to delete this ticket: Vas a eliminar este ticket
|
||||||
as PDF signed: como PDF firmado
|
as PDF signed: como PDF firmado
|
||||||
Are you sure you want to replace this delivery note?: ¿Seguro que quieres reemplazar este albarán?
|
Are you sure you want to replace this delivery note?: ¿Seguro que quieres reemplazar este albarán?
|
||||||
|
Restore ticket: Restaurar ticket
|
||||||
|
Are you sure you want to restore the ticket?: ¿Seguro que quieres restaurar el ticket?
|
||||||
|
You are going to restore this ticket: Vas a restaurar este ticket
|
||||||
|
Ticket restored: Ticket restaurado
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, computed, onUnmounted } from 'vue';
|
import { onMounted, ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
@ -197,8 +197,6 @@ onMounted(async () => {
|
||||||
const filteredColumns = columns.value.filter((col) => col.name !== 'history');
|
const filteredColumns = columns.value.filter((col) => col.name !== 'history');
|
||||||
allColumnNames.value = filteredColumns.map((col) => col.name);
|
allColumnNames.value = filteredColumns.map((col) => col.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, computed, onUnmounted, watch } from 'vue';
|
import { onMounted, ref, computed, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter, useRoute } from 'vue-router';
|
import { useRouter, useRoute } from 'vue-router';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
|
@ -421,8 +421,6 @@ onMounted(async () => {
|
||||||
getConfig();
|
getConfig();
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
|
|
||||||
const items = ref([]);
|
const items = ref([]);
|
||||||
const newRow = ref({});
|
const newRow = ref({});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
import { ref, computed, onMounted, watch, nextTick } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
@ -90,8 +90,6 @@ const applyVolumes = async (salesData) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => (stateStore.rightDrawer = true));
|
onMounted(() => (stateStore.rightDrawer = true));
|
||||||
|
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -57,7 +57,6 @@ onMounted(async () => await getItemPackingTypes());
|
||||||
search-url="advanceTickets"
|
search-url="advanceTickets"
|
||||||
:data-key="props.dataKey"
|
:data-key="props.dataKey"
|
||||||
:search-button="true"
|
:search-button="true"
|
||||||
:hidden-tags="['search']"
|
|
||||||
:unremovable-params="['warehouseFk', 'dateFuture', 'dateToAdvance']"
|
:unremovable-params="['warehouseFk', 'dateFuture', 'dateToAdvance']"
|
||||||
>
|
>
|
||||||
<template #tags="{ tag, formatFn }">
|
<template #tags="{ tag, formatFn }">
|
||||||
|
|
|
@ -59,7 +59,6 @@ onMounted(async () => {
|
||||||
/>
|
/>
|
||||||
<VnFilterPanel
|
<VnFilterPanel
|
||||||
:data-key="props.dataKey"
|
:data-key="props.dataKey"
|
||||||
:hidden-tags="['search']"
|
|
||||||
:un-removable-params="['warehouseFk', 'originScopeDays ', 'futureScopeDays']"
|
:un-removable-params="['warehouseFk', 'originScopeDays ', 'futureScopeDays']"
|
||||||
>
|
>
|
||||||
<template #tags="{ tag, formatFn }">
|
<template #tags="{ tag, formatFn }">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, computed, onUnmounted } from 'vue';
|
import { onMounted, ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import VnSelectCache from 'src/components/common/VnSelectCache.vue';
|
import VnSelectCache from 'src/components/common/VnSelectCache.vue';
|
||||||
|
@ -170,8 +170,6 @@ onMounted(async () => {
|
||||||
const filteredColumns = columns.value.filter((col) => col.name !== 'actions');
|
const filteredColumns = columns.value.filter((col) => col.name !== 'actions');
|
||||||
allColumnNames.value = filteredColumns.map((col) => col.name);
|
allColumnNames.value = filteredColumns.map((col) => col.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { useState } from 'src/composables/useState';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import VnImg from 'src/components/ui/VnImg.vue';
|
import VnImg from 'src/components/ui/VnImg.vue';
|
||||||
import EditPictureForm from 'components/EditPictureForm.vue';
|
import EditPictureForm from 'components/EditPictureForm.vue';
|
||||||
|
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -143,10 +144,14 @@ const handlePhotoUpdated = (evt = false) => {
|
||||||
:value="entity.user?.emailUser?.email"
|
:value="entity.user?.emailUser?.email"
|
||||||
copy
|
copy
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv :label="t('worker.list.department')">
|
||||||
:label="t('worker.list.department')"
|
<template #value>
|
||||||
:value="entity.department ? entity.department.department.name : null"
|
<span class="link" v-text="entity.department?.department?.name" />
|
||||||
|
<DepartmentDescriptorProxy
|
||||||
|
:id="entity.department?.department?.id"
|
||||||
/>
|
/>
|
||||||
|
</template>
|
||||||
|
</VnLv>
|
||||||
<VnLv :value="entity.phone">
|
<VnLv :value="entity.phone">
|
||||||
<template #label>
|
<template #label>
|
||||||
{{ t('globals.phone') }}
|
{{ t('globals.phone') }}
|
||||||
|
|
|
@ -133,6 +133,7 @@ function reloadData() {
|
||||||
option-value="id"
|
option-value="id"
|
||||||
id="deviceProductionFk"
|
id="deviceProductionFk"
|
||||||
hide-selected
|
hide-selected
|
||||||
|
data-cy="pda-dialog-select"
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
|
|
@ -14,6 +14,7 @@ import FormModel from 'components/FormModel.vue';
|
||||||
import CreateBankEntityForm from 'src/components/CreateBankEntityForm.vue';
|
import CreateBankEntityForm from 'src/components/CreateBankEntityForm.vue';
|
||||||
import VnRadio from 'src/components/common/VnRadio.vue';
|
import VnRadio from 'src/components/common/VnRadio.vue';
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const user = useState().getUser();
|
const user = useState().getUser();
|
||||||
|
@ -149,27 +150,11 @@ async function autofillBic(worker) {
|
||||||
hide-selected
|
hide-selected
|
||||||
:rules="validate('Worker.company')"
|
:rules="validate('Worker.company')"
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
:label="t('worker.summary.boss')"
|
:label="t('worker.summary.boss')"
|
||||||
v-model="data.bossFk"
|
v-model="data.bossFk"
|
||||||
url="Workers/search"
|
|
||||||
option-value="id"
|
|
||||||
option-label="name"
|
|
||||||
hide-selected
|
|
||||||
:rules="validate('Worker.boss')"
|
:rules="validate('Worker.boss')"
|
||||||
>
|
/>
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ scope.opt.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption
|
|
||||||
>{{ scope.opt.nickname }},
|
|
||||||
{{ scope.opt.code }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnInput
|
<VnInput
|
||||||
|
|
|
@ -18,6 +18,7 @@ import RightMenu from 'src/components/common/RightMenu.vue';
|
||||||
import WorkerFilter from './WorkerFilter.vue';
|
import WorkerFilter from './WorkerFilter.vue';
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
|
@ -260,26 +261,10 @@ async function autofillBic(worker) {
|
||||||
option-label="code"
|
option-label="code"
|
||||||
hide-selected
|
hide-selected
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelectWorker
|
||||||
:label="t('worker.summary.boss')"
|
:label="t('worker.summary.boss')"
|
||||||
v-model="data.bossFk"
|
v-model="data.bossFk"
|
||||||
url="Workers/search"
|
/>
|
||||||
option-value="id"
|
|
||||||
option-label="name"
|
|
||||||
hide-selected
|
|
||||||
>
|
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel>{{ scope.opt.name }}</QItemLabel>
|
|
||||||
<QItemLabel caption
|
|
||||||
>{{ scope.opt.nickname }},
|
|
||||||
{{ scope.opt.code }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnInput v-model="data.fi" :label="t('worker.create.fi')" />
|
<VnInput v-model="data.fi" :label="t('worker.create.fi')" />
|
||||||
|
@ -376,6 +361,7 @@ async function autofillBic(worker) {
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
|
Create worker: Crear trabajador
|
||||||
Search worker: Buscar trabajador
|
Search worker: Buscar trabajador
|
||||||
You can search by worker id or name: Puedes buscar por id o nombre del trabajador
|
You can search by worker id or name: Puedes buscar por id o nombre del trabajador
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -32,7 +32,12 @@ const agencyOptions = ref([]);
|
||||||
<FormModel :url="`Zones/${route.params.id}`" auto-load model="zone">
|
<FormModel :url="`Zones/${route.params.id}`" auto-load model="zone">
|
||||||
<template #form="{ data, validate }">
|
<template #form="{ data, validate }">
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnInput :label="t('Name')" clearable v-model="data.name" />
|
<VnInput
|
||||||
|
data-cy="zone-basic-data-name"
|
||||||
|
:label="t('Name')"
|
||||||
|
clearable
|
||||||
|
v-model="data.name"
|
||||||
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
|
||||||
<VnRow>
|
<VnRow>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onUnmounted } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import ZoneEventsPanel from './ZoneEventsPanel.vue';
|
import ZoneEventsPanel from './ZoneEventsPanel.vue';
|
||||||
|
@ -40,8 +40,6 @@ const onZoneEventFormClose = () => {
|
||||||
showZoneEventForm.value = false;
|
showZoneEventForm.value = false;
|
||||||
zoneEventsFormProps.value = {};
|
zoneEventsFormProps.value = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -28,11 +28,7 @@ const agencies = ref([]);
|
||||||
@on-fetch="(data) => (agencies = data)"
|
@on-fetch="(data) => (agencies = data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<VnFilterPanel
|
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
|
||||||
:data-key="props.dataKey"
|
|
||||||
:search-button="true"
|
|
||||||
:hidden-tags="['search']"
|
|
||||||
>
|
|
||||||
<template #tags="{ tag }">
|
<template #tags="{ tag }">
|
||||||
<div class="q-gutter-x-xs">
|
<div class="q-gutter-x-xs">
|
||||||
<strong>{{ t(`filterPanel.${tag.label}`) }}: </strong>
|
<strong>{{ t(`filterPanel.${tag.label}`) }}: </strong>
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
describe('ItemLastEntries', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport(1280, 720);
|
||||||
|
cy.login('buyer');
|
||||||
|
cy.visit('/#/item/1/last-entries');
|
||||||
|
cy.intercept('GET', /.*lastEntriesFilter/).as('item');
|
||||||
|
cy.waitForElement('tbody');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter by agency', () => {
|
||||||
|
cy.get('tbody > tr')
|
||||||
|
.its('length')
|
||||||
|
.then((rowCount) => {
|
||||||
|
cy.get('[data-cy="hideInventory"]').click();
|
||||||
|
cy.wait('@item');
|
||||||
|
cy.waitForElement('tbody');
|
||||||
|
cy.get('tbody > tr').should('have.length.greaterThan', rowCount);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,6 +1,5 @@
|
||||||
describe('WorkerPda', () => {
|
describe('WorkerPda', () => {
|
||||||
const deviceProductionField =
|
const select = '[data-cy="pda-dialog-select"]';
|
||||||
'.vn-row > .q-field > .q-field__inner > .q-field__control > .q-field__control-container';
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.viewport(1920, 1080);
|
cy.viewport(1920, 1080);
|
||||||
cy.login('developer');
|
cy.login('developer');
|
||||||
|
@ -9,7 +8,8 @@ describe('WorkerPda', () => {
|
||||||
|
|
||||||
it('assign pda', () => {
|
it('assign pda', () => {
|
||||||
cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click();
|
cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click();
|
||||||
cy.get(deviceProductionField).type('{downArrow}{enter}');
|
cy.get(select).click();
|
||||||
|
cy.get(select).type('{downArrow}{enter}');
|
||||||
cy.get('.q-notification__message').should('have.text', 'Data created');
|
cy.get('.q-notification__message').should('have.text', 'Data created');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
describe('ZoneBasicData', () => {
|
describe('ZoneBasicData', () => {
|
||||||
const notification = '.q-notification__message';
|
const notification = '.q-notification__message';
|
||||||
|
const priceBasicData = '[data-cy="Price_input"]';
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.viewport(1280, 720);
|
cy.viewport(1280, 720);
|
||||||
|
@ -8,14 +9,20 @@ describe('ZoneBasicData', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if the name is empty', () => {
|
it('should throw an error if the name is empty', () => {
|
||||||
cy.get('.q-card > :nth-child(1)').clear();
|
cy.get('[data-cy="zone-basic-data-name"] input').type('{selectall}{backspace}');
|
||||||
cy.get('.q-btn-group > .q-btn--standard').click();
|
cy.get('.q-btn-group > .q-btn--standard').click();
|
||||||
cy.get(notification).should('contains.text', "can't be blank");
|
cy.get(notification).should('contains.text', "can't be blank");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the price is empty', () => {
|
||||||
|
cy.get(priceBasicData).clear();
|
||||||
|
cy.get('.q-btn-group > .q-btn--standard').click();
|
||||||
|
cy.get(notification).should('contains.text', 'cannot be blank');
|
||||||
|
});
|
||||||
|
|
||||||
it("should edit the basicData's zone", () => {
|
it("should edit the basicData's zone", () => {
|
||||||
cy.get('.q-card > :nth-child(1)').type(' modified');
|
cy.get('.q-card > :nth-child(1)').type(' modified');
|
||||||
cy.get('.q-btn-group > .q-btn--standard').click();
|
cy.get('.q-btn-group > .q-btn--standard').click();
|
||||||
cy.get(notification).should('contains.text', 'Data saved');
|
cy.checkNotification('Data saved');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue