Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 8395-invoiceInVatTotal
gitea/salix-front/pipeline/pr-dev This commit looks good Details

This commit is contained in:
Jorge Penadés 2025-01-20 13:21:32 +01:00
commit ff14d81f51
9 changed files with 135 additions and 87 deletions

View File

@ -42,10 +42,13 @@ const $props = defineProps({
type: Number, type: Number,
default: null, default: null,
}, },
uppercase: {
type: Boolean,
default: false,
},
}); });
const vnInputRef = ref(null); const vnInputRef = ref(null);
const showPassword = ref(false);
const value = computed({ const value = computed({
get() { get() {
return $props.modelValue; return $props.modelValue;
@ -117,6 +120,10 @@ const handleInsertMode = (e) => {
input.setSelectionRange(cursorPos + 1, cursorPos + 1); input.setSelectionRange(cursorPos + 1, cursorPos + 1);
}); });
}; };
const handleUppercase = () => {
value.value = value.value?.toUpperCase() || '';
};
</script> </script>
<template> <template>
@ -159,7 +166,16 @@ const handleInsertMode = (e) => {
emit('remove'); emit('remove');
} }
" "
></QIcon>
<QIcon
name="match_case"
size="xs"
v-if="!$attrs.disabled && !($attrs.readonly) && $props.uppercase"
@click="handleUppercase"
class="uppercase-icon"
/> />
<slot name="append" v-if="$slots.append && !$attrs.disabled" /> <slot name="append" v-if="$slots.append && !$attrs.disabled" />
<QIcon v-if="info" name="info"> <QIcon v-if="info" name="info">
<QTooltip max-width="350px"> <QTooltip max-width="350px">
@ -170,3 +186,14 @@ const handleInsertMode = (e) => {
</QInput> </QInput>
</div> </div>
</template> </template>
<i18n>
en:
inputMin: Must be more than {value}
maxLength: The value exceeds {value} characters
inputMax: Must be less than {value}
es:
inputMin: Debe ser mayor a {value}
maxLength: El valor excede los {value} carácteres
inputMax: Debe ser menor a {value}
</i18n>

View File

@ -44,6 +44,7 @@ function handleLocation(data, location) {
:required="true" :required="true"
:rules="validate('client.socialName')" :rules="validate('client.socialName')"
clearable clearable
uppercase="true"
v-model="data.socialName" v-model="data.socialName"
> >
<template #append> <template #append>

View File

@ -50,6 +50,14 @@ const columns = computed(() => [
isTitle: true, isTitle: true,
create: true, create: true,
columnClass: 'expand', columnClass: 'expand',
attrs: {
uppercase: true,
},
columnFilter: {
attrs: {
uppercase: false,
},
},
}, },
{ {
align: 'left', align: 'left',

View File

@ -106,7 +106,7 @@ const { openConfirmationModal } = useVnConfirm();
:to="{ :to="{
name: 'WorkerList', name: 'WorkerList',
query: { query: {
params: JSON.stringify({ departmentFk: entityId }), table: JSON.stringify({ departmentFk: entityId }),
}, },
}" }"
> >

View File

@ -1,7 +1,7 @@
<script setup> <script setup>
import { onMounted, computed, reactive, ref, nextTick, watch } from 'vue'; import { onMounted, computed, ref, nextTick } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router'; import { useRoute } from 'vue-router';
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue'; import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue'; import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue';
@ -22,19 +22,16 @@ import VnSubToolbar from 'components/ui/VnSubToolbar.vue';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
const router = useRouter();
const state = useState(); const state = useState();
const user = state.getUser(); const user = state.getUser();
const today = ref(Date.vnNew()); const today = Date.vnNew();
today.setHours(0, 0, 0, 0);
const warehousesOptions = ref([]); const warehousesOptions = ref([]);
const itemBalancesRef = ref(null); const itemBalances = computed(() => arrayDataItemBalances.store.data);
const itemsBalanceFilter = reactive({ const where = computed(() => arrayDataItemBalances.store.filter.where || {});
where: { itemFk: route.params.id, warehouseFk: null, date: null }, const showWhatsBeforeInventory = ref(false);
});
const itemBalances = ref([]);
const warehouseFk = ref(null);
const _showWhatsBeforeInventory = ref(false);
const inventoriedDate = ref(null); const inventoriedDate = ref(null);
let arrayDataItemBalances = useArrayData('ItemBalances');
const originTypeMap = { const originTypeMap = {
entry: { entry: {
@ -122,36 +119,28 @@ const columns = computed(() => [
}, },
]); ]);
const showWhatsBeforeInventory = computed({
get: () => _showWhatsBeforeInventory.value,
set: (val) => {
_showWhatsBeforeInventory.value = val;
if (!val) itemsBalanceFilter.where.date = null;
else itemsBalanceFilter.where.date = inventoriedDate.value ?? new Date();
},
});
onMounted(async () => { onMounted(async () => {
today.value.setHours(0, 0, 0, 0); const ref = where.value;
if (route.query.warehouseFk) warehouseFk.value = route.query.warehouseFk; const query = route.query;
else if (user.value) warehouseFk.value = user.value.warehouseFk; inventoriedDate.value =
itemsBalanceFilter.where.warehouseFk = warehouseFk.value; (await axios.get('Configs/findOne')).data?.inventoried || today;
const { data } = await axios.get('Configs/findOne');
inventoriedDate.value = data.inventoried; if (query.warehouseFk) ref.warehouseFk = query.warehouseFk;
else if (!ref.warehouseFk && user.value) ref.warehouseFk = user.value.warehouseFk;
if (ref.date) showWhatsBeforeInventory.value = true;
ref.itemFk = route.params.id;
arrayDataItemBalances = useArrayData('ItemBalances', {
url: 'Items/getBalance',
filter: { where: ref },
});
await fetchItemBalances(); await fetchItemBalances();
await scrollToToday(); await scrollToToday();
await updateWarehouse(warehouseFk.value); await updateWarehouse(ref.warehouseFk);
}); });
watch( const fetchItemBalances = async () => await arrayDataItemBalances.fetch({});
() => router.currentRoute.value.params.id,
(newId) => {
itemsBalanceFilter.where.itemFk = newId;
itemBalancesRef.value.fetch();
}
);
const fetchItemBalances = async () => await itemBalancesRef.value.fetch();
const getBadgeAttrs = (_date) => { const getBadgeAttrs = (_date) => {
const isSameDate = date.isSameDate(today.value, _date); const isSameDate = date.isSameDate(today.value, _date);
@ -178,23 +167,13 @@ const formatDateForAttribute = (dateValue) => {
}; };
async function updateWarehouse(warehouseFk) { async function updateWarehouse(warehouseFk) {
const stock = useArrayData('descriptorStock', { const stock = useArrayData('descriptorStock', { userParams: { warehouseFk } });
userParams: {
warehouseFk,
},
});
await stock.fetch({}); await stock.fetch({});
stock.store.data.itemFk = route.params.id; stock.store.data.itemFk = route.params.id;
} }
</script> </script>
<template> <template>
<FetchData
ref="itemBalancesRef"
url="Items/getBalance"
:filter="itemsBalanceFilter"
@on-fetch="(data) => (itemBalances = data)"
/>
<FetchData <FetchData
url="Warehouses" url="Warehouses"
:filter="{ fields: ['id', 'name'], order: 'name ASC' }" :filter="{ fields: ['id', 'name'], order: 'name ASC' }"
@ -207,27 +186,30 @@ async function updateWarehouse(warehouseFk) {
<VnSelect <VnSelect
:label="t('itemDiary.warehouse')" :label="t('itemDiary.warehouse')"
:options="warehousesOptions" :options="warehousesOptions"
hide-selected v-model="where.warehouseFk"
option-label="name"
option-value="id"
dense
v-model="itemsBalanceFilter.where.warehouseFk"
@update:model-value=" @update:model-value="
(value) => fetchItemBalances() && updateWarehouse(value) (val) => fetchItemBalances() && updateWarehouse(val)
" "
class="q-mr-lg" class="q-mr-lg"
:is-clearable="false"
/> />
<QCheckbox <QCheckbox
:label="t('itemDiary.showBefore')" :label="t('itemDiary.showBefore')"
v-model="showWhatsBeforeInventory" v-model="showWhatsBeforeInventory"
@update:model-value="fetchItemBalances" @update:model-value="
async (val) => {
if (!val) where.date = null;
else where.date = inventoriedDate;
await fetchItemBalances();
}
"
class="q-mr-lg" class="q-mr-lg"
/> />
<VnInputDate <VnInputDate
v-if="showWhatsBeforeInventory" v-if="showWhatsBeforeInventory"
:label="t('itemDiary.since')" :label="t('itemDiary.since')"
dense dense
v-model="itemsBalanceFilter.where.date" v-model="where.date"
@update:model-value="fetchItemBalances" @update:model-value="fetchItemBalances"
/> />
</div> </div>

View File

@ -36,18 +36,7 @@ const exprBuilder = (param, value) => {
} }
}; };
const where = { let arrayData = useArrayData('ItemLastEntries');
itemFk: route.params.id,
};
const arrayData = useArrayData('ItemLastEntries', {
url: 'Items/lastEntriesFilter',
order: ['landed DESC', 'buyFk DESC'],
exprBuilder: exprBuilder,
userFilter: {
where: where,
},
});
const itemLastEntries = ref([]); const itemLastEntries = ref([]);
const columns = computed(() => [ const columns = computed(() => [
@ -161,25 +150,51 @@ const getDate = (date, type) => {
}; };
const updateFilter = async () => { const updateFilter = async () => {
let filter; let landed;
if (!from.value && to.value) filter = { lte: to.value }; if (!from.value && to.value) landed = { lte: to.value };
else if (from.value && !to.value) filter = { gte: from.value }; else if (from.value && !to.value) landed = { gte: from.value };
else if (from.value && to.value) filter = { between: [from.value, to.value] }; else if (from.value && to.value) landed = { between: [from.value, to.value] };
const userFilter = arrayData.store.userFilter.where;
userFilter.landed = filter;
arrayData.store.filter.where.landed = landed;
await fetchItemLastEntries(); await fetchItemLastEntries();
}; };
onMounted(async () => { onMounted(async () => {
const _from = Date.vnNew(); const landed = arrayData.store.filter.where?.landed;
_from.setDate(_from.getDate() - 75); arrayData = useArrayData('ItemLastEntries', {
from.value = getDate(_from, 'from'); url: 'Items/lastEntriesFilter',
const _to = Date.vnNew(); order: ['landed DESC', 'buyFk DESC'],
_to.setDate(_to.getDate() + 10); exprBuilder: exprBuilder,
to.value = getDate(_to, 'to'); filter: {
where: {
itemFk: route.params.id,
landed,
},
},
});
if (landed) {
const key = Object.keys(landed)[0];
switch (key) {
case 'gte':
from.value = landed.gte;
break;
case 'lte':
to.value = landed.lte;
break;
case 'between':
from.value = landed.between[0];
to.value = landed.between[1];
break;
}
} else {
const _from = Date.vnNew();
_from.setDate(_from.getDate() - 75);
from.value = getDate(_from, 'from');
const _to = Date.vnNew();
_to.setDate(_to.getDate() + 10);
to.value = getDate(_to, 'to');
}
updateFilter(); updateFilter();

View File

@ -92,6 +92,7 @@ function handleLocation(data, location) {
<VnInput <VnInput
v-model="data.name" v-model="data.name"
:label="t('supplier.fiscalData.name')" :label="t('supplier.fiscalData.name')"
uppercase="true"
clearable clearable
/> />
<VnInput <VnInput

View File

@ -5,6 +5,7 @@ import VnTable from 'components/VnTable/VnTable.vue';
import VnSearchbar from 'components/ui/VnSearchbar.vue'; import VnSearchbar from 'components/ui/VnSearchbar.vue';
import RightMenu from 'src/components/common/RightMenu.vue'; import RightMenu from 'src/components/common/RightMenu.vue';
import SupplierListFilter from './SupplierListFilter.vue'; import SupplierListFilter from './SupplierListFilter.vue';
import VnInput from 'src/components/common/VnInput.vue';
const { t } = useI18n(); const { t } = useI18n();
const tableRef = ref(); const tableRef = ref();
@ -23,9 +24,14 @@ const columns = computed(() => [
align: 'left', align: 'left',
label: t('globals.name'), label: t('globals.name'),
name: 'socialName', name: 'socialName',
create: true, attrs: {
uppercase: true,
},
columnFilter: { columnFilter: {
name: 'search', name: 'search',
attrs: {
uppercase: false,
},
}, },
isTitle: true, isTitle: true,
}, },
@ -118,14 +124,18 @@ const columns = computed(() => [
formInitialData: {}, formInitialData: {},
mapper: (data) => { mapper: (data) => {
data.name = data.socialName; data.name = data.socialName;
delete data.socialName;
return data; return data;
}, },
}" }"
:right-search="false" :right-search="false"
order="id ASC" order="id ASC"
:columns="columns" :columns="columns"
/> >
<template #more-create-dialog="{ data }">
<VnInput :label="t('globals.name')" v-model="data.socialName" :uppercase="true" />
</template>
</VnTable>
</template> </template>
<i18n> <i18n>

View File

@ -138,7 +138,11 @@ function uppercaseStreetModel(data) {
return { return {
get: () => (data.street ? data.street.toUpperCase() : ''), get: () => (data.street ? data.street.toUpperCase() : ''),
set: (value) => { set: (value) => {
data.street = value.toUpperCase(); if (value) {
data.street = value.toUpperCase();
} else {
data.street = null;
}
}, },
}; };
} }