0
0
Fork 0

Merge branch 'dev' into 6739-invoiceOut

This commit is contained in:
Jon Elias 2024-06-11 05:18:59 +00:00
commit 83a4e9c75f
27 changed files with 279 additions and 173 deletions

View File

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- (Item) => Se añade la opción de añadir un comentario del motivo de hacer una foto - (Item) => Se añade la opción de añadir un comentario del motivo de hacer una foto
- (Worker) => Se añade la opción de crear un trabajador ajeno a la empresa
## [2418.01] ## [2418.01]

View File

@ -0,0 +1,6 @@
<script setup>
const model = defineModel({ type: Boolean, required: true });
</script>
<template>
<QRadio v-model="model" v-bind="$attrs" dense :dark="true" class="q-mr-sm" />
</template>

View File

@ -18,7 +18,7 @@ onMounted(() => {
const observer = new MutationObserver( const observer = new MutationObserver(
() => () =>
(hasContent.value = (hasContent.value =
actions.value.childNodes.length + data.value.childNodes.length) actions.value?.childNodes?.length + data.value?.childNodes?.length)
); );
if (actions.value) observer.observe(actions.value, opts); if (actions.value) observer.observe(actions.value, opts);
if (data.value) observer.observe(data.value, opts); if (data.value) observer.observe(data.value, opts);

View File

@ -34,7 +34,7 @@ const entryFilter = {
{ {
relation: 'travel', relation: 'travel',
scope: { scope: {
fields: ['id', 'landed', 'agencyModeFk', 'warehouseOutFk'], fields: ['id', 'landed', 'shipped', 'agencyModeFk', 'warehouseOutFk'],
include: [ include: [
{ {
relation: 'agency', relation: 'agency',
@ -125,10 +125,8 @@ watch;
:label="t('entry.descriptor.agency')" :label="t('entry.descriptor.agency')"
:value="entity.travel?.agency?.name" :value="entity.travel?.agency?.name"
/> />
<VnLv <VnLv :label="t('shipped')" :value="toDate(entity.travel?.shipped)" />
:label="t('entry.descriptor.landed')" <VnLv :label="t('landed')" :value="toDate(entity.travel?.landed)" />
:value="toDate(entity.travel?.landed)"
/>
<VnLv <VnLv
:label="t('entry.descriptor.warehouseOut')" :label="t('entry.descriptor.warehouseOut')"
:value="entity.travel?.warehouseOut?.name" :value="entity.travel?.warehouseOut?.name"

View File

@ -221,10 +221,7 @@ const fetchEntryBuys = async () => {
:value="entry.travel.agency.name" :value="entry.travel.agency.name"
/> />
<VnLv <VnLv :label="t('shipped')" :value="toDate(entry.travel.shipped)" />
:label="t('entry.summary.travelShipped')"
:value="toDate(entry.travel.shipped)"
/>
<VnLv <VnLv
:label="t('entry.summary.travelWarehouseOut')" :label="t('entry.summary.travelWarehouseOut')"
@ -236,10 +233,7 @@ const fetchEntryBuys = async () => {
v-model="entry.travel.isDelivered" v-model="entry.travel.isDelivered"
:disable="true" :disable="true"
/> />
<VnLv <VnLv :label="t('landed')" :value="toDate(entry.travel.landed)" />
:label="t('entry.summary.travelLanded')"
:value="toDate(entry.travel.landed)"
/>
<VnLv <VnLv
:label="t('entry.summary.travelWarehouseIn')" :label="t('entry.summary.travelWarehouseIn')"

View File

@ -78,10 +78,7 @@ onMounted(async () => {
</QIcon> </QIcon>
</template> </template>
<template #list-items> <template #list-items>
<VnLv <VnLv :label="t('landed')" :value="toDate(row.landed)" />
:label="t('entry.list.landed')"
:value="toDate(row.landed)"
/>
<VnLv <VnLv
:label="t('entry.list.booked')" :label="t('entry.list.booked')"
:value="!!row.isBooked" :value="!!row.isBooked"

View File

@ -6,3 +6,5 @@ entryFilter:
filter: filter:
search: General search search: General search
reference: Reference reference: Reference
landed: Landed
shipped: Shipped

View File

@ -8,3 +8,6 @@ entryFilter:
filter: filter:
search: Búsqueda general search: Búsqueda general
reference: Referencia reference: Referencia
landed: F. llegada
shipped: F. salida

View File

@ -19,7 +19,8 @@ const { t } = useI18n();
const dms = ref({}); const dms = ref({});
const route = useRoute(); const route = useRoute();
const editDownloadDisabled = ref(false); const editDownloadDisabled = ref(false);
const invoiceIn = computed(() => useArrayData().store.data); const arrayData = useArrayData();
const invoiceIn = computed(() => arrayData.store.data);
const userConfig = ref(null); const userConfig = ref(null);
const invoiceId = computed(() => +route.params.id); const invoiceId = computed(() => +route.params.id);

View File

@ -12,7 +12,7 @@ const { push, currentRoute } = useRouter();
const { t } = useI18n(); const { t } = useI18n();
const invoiceId = +currentRoute.value.params.id; const invoiceId = +currentRoute.value.params.id;
const arrayData = useArrayData(currentRoute.value.meta.moduleName); const arrayData = useArrayData();
const invoiceIn = computed(() => arrayData.store.data); const invoiceIn = computed(() => arrayData.store.data);
const invoiceInCorrectionRef = ref(); const invoiceInCorrectionRef = ref();
const filter = { const filter = {

View File

@ -27,9 +27,9 @@ const quasar = useQuasar();
const { hasAny } = useRole(); const { hasAny } = useRole();
const { t } = useI18n(); const { t } = useI18n();
const { openReport, sendEmail } = usePrintService(); const { openReport, sendEmail } = usePrintService();
const { store } = useArrayData(currentRoute.value.meta.moduleName); const arrayData = useArrayData();
const invoiceIn = computed(() => store.data); const invoiceIn = computed(() => arrayData.store.data);
const cardDescriptorRef = ref(); const cardDescriptorRef = ref();
const correctionDialogRef = ref(); const correctionDialogRef = ref();
const entityId = computed(() => $props.id || +currentRoute.value.params.id); const entityId = computed(() => $props.id || +currentRoute.value.params.id);
@ -184,7 +184,7 @@ async function toUnbook() {
: t('isNotLinked', { bookEntry }); : t('isNotLinked', { bookEntry });
quasar.notify({ type, message }); quasar.notify({ type, message });
if (!isLinked) store.data.isBooked = false; if (!isLinked) arrayData.store.data.isBooked = false;
} }
async function deleteInvoice() { async function deleteInvoice() {

View File

@ -11,7 +11,8 @@ import { useArrayData } from 'src/composables/useArrayData';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
const currency = computed(() => useArrayData().store.data?.currency?.code); const arrayData = useArrayData();
const currency = computed(() => arrayData.store.data?.currency?.code);
const invoceInIntrastat = ref([]); const invoceInIntrastat = ref([]);
const rowsSelected = ref([]); const rowsSelected = ref([]);
const countries = ref([]); const countries = ref([]);

View File

@ -14,9 +14,10 @@ import VnTitle from 'src/components/common/VnTitle.vue';
const props = defineProps({ id: { type: [Number, String], default: 0 } }); const props = defineProps({ id: { type: [Number, String], default: 0 } });
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
const arrayData = useArrayData();
const entityId = computed(() => props.id || +route.params.id); const entityId = computed(() => props.id || +route.params.id);
const invoiceIn = computed(() => useArrayData().store.data); const invoiceIn = computed(() => arrayData.store.data);
const currency = computed(() => invoiceIn.value?.currency?.code); const currency = computed(() => invoiceIn.value?.currency?.code);
const invoiceInUrl = ref(); const invoiceInUrl = ref();
const amountsNotMatch = ref(null); const amountsNotMatch = ref(null);

View File

@ -56,7 +56,7 @@ const params = reactive({});
const arrayData = useArrayData('ItemFixedPrices', { const arrayData = useArrayData('ItemFixedPrices', {
url: 'FixedPrices/filter', url: 'FixedPrices/filter',
userParams: params, userParams: params,
order: ['itemFk'], order: ['name ASC', 'itemFk'],
exprBuilder: exprBuilder, exprBuilder: exprBuilder,
}); });
const store = arrayData.store; const store = arrayData.store;

View File

@ -34,7 +34,7 @@ const updateDefaultStop = (data) => {
const onSave = async () => { const onSave = async () => {
isLoading.value = true; isLoading.value = true;
try { try {
await axios.post('ExpeditionTrucks', { ...roadmapStopForm }); await axios.post('RoadmapStops', { ...roadmapStopForm });
emit('ok'); emit('ok');
} finally { } finally {
isLoading.value = false; isLoading.value = false;

View File

@ -23,28 +23,43 @@ const props = defineProps({
}); });
const { t } = useI18n(); const { t } = useI18n();
const warehouseList = ref([]); const addressList = ref([]);
const form = computed(() => props.formData); const form = computed(() => props.formData);
const isDialog = computed(() => props.layout === 'dialog'); const isDialog = computed(() => props.layout === 'dialog');
const onFetch = (data) => {
addressList.value = data.map((roadmap) => ({
id: roadmap.addressFk,
nickname: roadmap.address ? roadmap.address.nickname : '',
}));
};
</script> </script>
<template> <template>
<FetchData <FetchData
url="Warehouses" url="RoadmapAddresses"
auto-load auto-load
:filter="{ fields: ['id', 'name'] }" :filter="{
sort-by="name" include: [
{
relation: 'address',
scope: {
fields: ['nickname'],
},
},
],
}"
limit="30" limit="30"
@on-fetch="(data) => (warehouseList = data)" @on-fetch="onFetch"
/> />
<div :class="[isDialog ? 'column' : 'form-gap', 'full-width flex']"> <div :class="[isDialog ? 'column' : 'form-gap', 'full-width flex']">
<QCardSection class="flex-grow q-px-none flex-1"> <QCardSection class="flex-grow q-px-none flex-1">
<VnSelect <VnSelect
v-model.number="form.warehouseFk" v-model.number="form.addressFk"
class="full-width" class="full-width"
:label="t('Warehouse')" :label="t('Address')"
:options="warehouseList" :options="addressList"
option-value="id" option-value="id"
option-label="name" option-label="nickname"
emit-value emit-value
map-options map-options
use-input use-input
@ -80,6 +95,7 @@ const isDialog = computed(() => props.layout === 'dialog');
</QCardSection> </QCardSection>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.form-gap { .form-gap {
gap: 16px; gap: 16px;
@ -93,9 +109,10 @@ const isDialog = computed(() => props.layout === 'dialog');
flex: 2; flex: 2;
} }
</style> </style>
<i18n> <i18n>
es: es:
Warehouse: Almacén Address: Dirección
ETA date: Fecha ETA ETA date: Fecha ETA
ETA hour: Hora ETA ETA hour: Hora ETA
Description: Descripción Description: Descripción

View File

@ -3,7 +3,6 @@ import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import VnRow from 'components/ui/VnRow.vue'; import VnRow from 'components/ui/VnRow.vue';
import FormModel from 'components/FormModel.vue'; import FormModel from 'components/FormModel.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.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 VnInputTime from 'components/common/VnInputTime.vue'; import VnInputTime from 'components/common/VnInputTime.vue';
@ -22,7 +21,6 @@ const onSave = (data, response) => {
}; };
</script> </script>
<template> <template>
<VnSubToolbar />
<FetchData <FetchData
url="Suppliers" url="Suppliers"
auto-load auto-load

View File

@ -1,21 +1,17 @@
<script setup> <script setup>
import { useStateStore } from 'stores/useStateStore'; import VnCard from 'components/common/VnCard.vue';
import LeftMenu from 'components/LeftMenu.vue'; import RoadmapDescriptor from 'pages/Route/Roadmap/RoadmapDescriptor.vue';
import RoadmapDescriptor from "pages/Route/Roadmap/RoadmapDescriptor.vue"; import RoadmapFilter from 'pages/Route/Roadmap/RoadmapFilter.vue';
const stateStore = useStateStore();
</script> </script>
<template> <template>
<QDrawer v-model="stateStore.leftDrawer" show-if-above :width="256"> <VnCard
<QScrollArea class="fit"> data-key="Roadmap"
<RoadmapDescriptor /> base-url="Roadmaps"
<QSeparator /> :descriptor="RoadmapDescriptor"
<LeftMenu source="card" /> :filter-panel="RoadmapFilter"
</QScrollArea> search-data-key="RoadmapList"
</QDrawer> search-url="Roadmaps"
<QPageContainer> searchbar-label="Search roadmap"
<QPage> searchbar-info="You can search by roadmap id or customer name"
<RouterView></RouterView> />
</QPage>
</QPageContainer>
</template> </template>

View File

@ -1,7 +1,6 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import { ref } from 'vue'; import { ref } from 'vue';
import CrudModel from 'components/CrudModel.vue'; import CrudModel from 'components/CrudModel.vue';
@ -23,7 +22,6 @@ const updateDefaultStop = (data) => {
}; };
</script> </script>
<template> <template>
<VnSubToolbar />
<FetchData <FetchData
:url="`Roadmaps/${route.params?.id}`" :url="`Roadmaps/${route.params?.id}`"
auto-load auto-load
@ -33,9 +31,9 @@ const updateDefaultStop = (data) => {
<div class="q-pa-lg"> <div class="q-pa-lg">
<CrudModel <CrudModel
ref="roadmapStopsCrudRef" ref="roadmapStopsCrudRef"
data-key="ExpeditionTrucks" data-key="RoadmapStops"
url="ExpeditionTrucks" url="RoadmapStops"
model="ExpeditionTrucks" model="RoadmapStops"
:filter="{ where: { roadmapFk: route.params?.id } }" :filter="{ where: { roadmapFk: route.params?.id } }"
:default-remove="false" :default-remove="false"
:data-required="defaultStop" :data-required="defaultStop"
@ -86,7 +84,7 @@ const updateDefaultStop = (data) => {
</template> </template>
<i18n> <i18n>
es: es:
Warehouse: Almacén Address: Consignatario
ETA date: Fecha ETA ETA date: Fecha ETA
ETA hour: Hora ETA ETA hour: Hora ETA
Description: Descripción Description: Descripción

View File

@ -35,9 +35,9 @@ onUnmounted(hideRightDrawer);
const columns = ref([ const columns = ref([
{ {
name: 'warehouse', name: 'address',
label: t('Warehouse'), label: t('Address'),
field: (row) => dashIfEmpty(row?.warehouse?.name), field: (row) => dashIfEmpty(row?.address?.nickname),
sortable: true, sortable: true,
align: 'left', align: 'left',
}, },
@ -54,8 +54,17 @@ const filter = {
{ relation: 'supplier' }, { relation: 'supplier' },
{ relation: 'worker' }, { relation: 'worker' },
{ {
relation: 'expeditionTruck', relation: 'roadmapStop',
scope: { include: [{ relation: 'warehouse' }] }, scope: {
include: [
{
relation: 'address',
scope: {
fields: ['nickname'],
},
},
],
},
}, },
], ],
}; };
@ -151,11 +160,9 @@ const openAddStopDialog = () => {
</div> </div>
<QTable <QTable
:columns="columns" :columns="columns"
:rows="entity?.expeditionTruck" :rows="entity?.roadmapStop"
:rows-per-page-options="[0]" :rows-per-page-options="[0]"
row-key="id" row-key="id"
flat
hide-pagination
/> />
</QCard> </QCard>
</template> </template>
@ -171,7 +178,7 @@ es:
Worker: Trabajador Worker: Trabajador
Observations: Observaciones Observations: Observaciones
Stops: Paradas Stops: Paradas
Warehouse: Almacén Address: Dirección
Go to stops: Ir a paradas Go to stops: Ir a paradas
Add stop: Añadir parada Add stop: Añadir parada
</i18n> </i18n>

View File

@ -266,9 +266,9 @@ function navigateToRoadmapSummary(event, row) {
<i18n> <i18n>
es: es:
Search roadmaps: Buscar troncales Search roadmaps: Buscar troncales
You can search by roadmap reference: Puedes buscar por referencia de la troncal You can search by roadmap reference: Puedes buscar por referencia del troncal
Delete roadmap(s): Eliminar troncal(es) Delete roadmap(s): Eliminar troncal(es)
Selected roadmaps will be removed: Las troncales seleccionadas serán eliminadas Selected roadmaps will be removed: Los troncales seleccionadas serán eliminados
Are you sure you want to continue?: ¿Seguro que quieres continuar? Are you sure you want to continue?: ¿Seguro que quieres continuar?
The date can't be empty: La fecha no puede estar vacía The date can't be empty: La fecha no puede estar vacía
Clone Selected Routes: Clonar rutas seleccionadas Clone Selected Routes: Clonar rutas seleccionadas

View File

@ -1,59 +1,29 @@
<script setup> <script setup>
import { onMounted, ref } from 'vue'; import { onBeforeMount, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import axios from 'axios';
import FetchData from 'components/FetchData.vue'; import { useUserConfig } from 'src/composables/useUserConfig';
import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue'; import VnRow from 'components/ui/VnRow.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import VnInputDate from 'components/common/VnInputDate.vue'; import VnInputDate from 'components/common/VnInputDate.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
import CreateBankEntityForm from 'src/components/CreateBankEntityForm.vue';
import VnLocation from 'src/components/common/VnLocation.vue'; import VnLocation from 'src/components/common/VnLocation.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
import FetchData from 'components/FetchData.vue';
import { useUserConfig } from 'src/composables/useUserConfig'; import FormModel from 'components/FormModel.vue';
import CreateBankEntityForm from 'src/components/CreateBankEntityForm.vue';
import VnRadio from 'src/components/common/VnRadio.vue';
const { t } = useI18n(); const { t } = useI18n();
const workerConfigFilter = {
field: ['payMethodFk'],
};
const newWorkerForm = ref({
companyFk: null,
payMethodFk: null,
firstName: null,
lastNames: null,
birth: null,
fi: null,
code: null,
phone: null,
postcode: null,
provinceFk: null,
city: null,
street: null,
name: null,
email: null,
bossFk: null,
iban: null,
bankEntityFk: null,
});
const companiesOptions = ref([]); const companiesOptions = ref([]);
const workersOptions = ref([]); const workersOptions = ref([]);
const payMethodsOptions = ref([]); const payMethodsOptions = ref([]);
const bankEntitiesOptions = ref([]); const bankEntitiesOptions = ref([]);
const postcodesOptions = ref([]); const postcodesOptions = ref([]);
const formData = ref({ isFreelance: false });
const onFetchWorkerConfig = (workerConfig) => { const defaultPayMethod = ref(0);
newWorkerForm.value.payMethodFk = workerConfig.payMethodFk;
};
const onBankEntityCreated = (data) => {
bankEntitiesOptions.value.push(data);
};
function handleLocation(data, location) { function handleLocation(data, location) {
const { town, code, provinceFk, countryFk } = location ?? {}; const { town, code, provinceFk, countryFk } = location ?? {};
@ -63,20 +33,18 @@ function handleLocation(data, location) {
data.countryFk = countryFk; data.countryFk = countryFk;
} }
onMounted(async () => { onBeforeMount(async () => {
const userInfo = await useUserConfig().fetch(); const userInfo = await useUserConfig().fetch();
newWorkerForm.value = { companyFk: userInfo.companyFk }; formData.value.companyFk = userInfo.companyFk;
const { data } = await axios.get('WorkerConfigs/findOne', {
params: { field: ['payMethodFk'] },
});
defaultPayMethod.value = data.payMethodFk;
formData.value.payMethodFk = defaultPayMethod.value;
}); });
</script> </script>
<template> <template>
<FetchData
url="WorkerConfigs/findOne"
@on-fetch="(data) => onFetchWorkerConfig(data)"
:filter="workerConfigFilter"
auto-load
/>
<FetchData <FetchData
url="Companies" url="Companies"
@on-fetch="(data) => (companiesOptions = data)" @on-fetch="(data) => (companiesOptions = data)"
@ -97,16 +65,31 @@ onMounted(async () => {
@on-fetch="(data) => (bankEntitiesOptions = data)" @on-fetch="(data) => (bankEntitiesOptions = data)"
auto-load auto-load
/> />
<QPage> <QPage>
<VnSubToolbar /> <VnSubToolbar>
<template #st-data>
<VnRadio
v-model="formData.isFreelance"
:val="false"
:label="`${t('Internal')}`"
@update:model-value="formData.payMethodFk = defaultPayMethod"
/>
<VnRadio
v-model="formData.isFreelance"
:val="true"
:label="`${t('External')}`"
@update:model-value="delete formData.payMethodFk"
/>
</template>
</VnSubToolbar>
<FormModel <FormModel
url-create="Workers/new" url-create="Workers/new"
model="worker" model="worker"
:form-initial-data="newWorkerForm" :form-initial-data="formData"
@on-data-saved="({ id }) => $router.push({ path: `/worker/${id}` })"
> >
<template #form="{ data, validate }"> <template #form="{ data, validate }">
<VnRow class="row q-gutter-md q-mb-md"> <VnRow>
<VnInput <VnInput
v-model="data.firstName" v-model="data.firstName"
:label="t('worker.create.name')" :label="t('worker.create.name')"
@ -117,47 +100,13 @@ onMounted(async () => {
:label="t('worker.create.lastName')" :label="t('worker.create.lastName')"
:rules="validate('Worker.lastNames')" :rules="validate('Worker.lastNames')"
/> />
<VnInputDate
v-model="data.birth"
:label="t('worker.create.birth')"
:rules="validate('Worker.birth')"
/>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<VnInput
v-model="data.fi"
:label="t('worker.create.fi')"
:rules="validate('Worker.fi')"
/>
<VnInput <VnInput
v-model="data.code" v-model="data.code"
:label="t('worker.create.code')" :label="t('worker.create.code')"
:rules="validate('Worker.code')" :rules="validate('Worker.code')"
/> />
<VnInput
v-model="data.phone"
:label="t('worker.create.phone')"
:rules="validate('Worker.phone')"
/>
</VnRow> </VnRow>
<VnRow class="row q-gutter-md q-mb-md"> <VnRow>
<VnLocation
:rules="validate('Worker.postcode')"
:roles-allowed-to-create="['deliveryAssistant']"
:options="postcodesOptions"
v-model="data.location"
@update:model-value="(location) => handleLocation(data, location)"
>
</VnLocation>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<VnInput
:label="t('worker.create.street')"
v-model="data.street"
:rules="validate('Worker.street')"
/>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<VnInput <VnInput
v-model="data.name" v-model="data.name"
:label="t('worker.create.webUser')" :label="t('worker.create.webUser')"
@ -169,7 +118,7 @@ onMounted(async () => {
:rules="validate('Worker.email')" :rules="validate('Worker.email')"
/> />
</VnRow> </VnRow>
<VnRow class="row q-gutter-md q-mb-md"> <VnRow>
<VnSelect <VnSelect
:label="t('worker.create.company')" :label="t('worker.create.company')"
v-model="data.companyFk" v-model="data.companyFk"
@ -201,7 +150,45 @@ onMounted(async () => {
</template> </template>
</VnSelect> </VnSelect>
</VnRow> </VnRow>
<VnRow class="row q-gutter-md q-mb-md"> <VnRow>
<VnInput
v-model="data.fi"
:label="t('worker.create.fi')"
:rules="validate('Worker.fi')"
/>
<VnInputDate
v-model="data.birth"
:label="t('worker.create.birth')"
:rules="validate('Worker.birth')"
:disable="formData.isFreelance"
/>
<VnInput
v-model="data.phone"
:label="t('worker.create.phone')"
:rules="validate('Worker.phone')"
:disable="formData.isFreelance"
/>
</VnRow>
<VnRow>
<VnLocation
:rules="validate('Worker.postcode')"
:roles-allowed-to-create="['deliveryAssistant']"
:options="postcodesOptions"
v-model="data.location"
@update:model-value="(location) => handleLocation(data, location)"
:disable="formData.isFreelance"
>
</VnLocation>
</VnRow>
<VnRow>
<VnInput
:label="t('worker.create.street')"
v-model="data.street"
:rules="validate('Worker.street')"
:disable="formData.isFreelance"
/>
</VnRow>
<VnRow>
<VnSelect <VnSelect
:label="t('worker.create.payMethods')" :label="t('worker.create.payMethods')"
v-model="data.payMethodFk" v-model="data.payMethodFk"
@ -211,11 +198,14 @@ onMounted(async () => {
map-options map-options
hide-selected hide-selected
:rules="validate('Worker.payMethodFk')" :rules="validate('Worker.payMethodFk')"
:disable="formData.isFreelance"
@update:model-value="(val) => !val && delete formData.payMethodFk"
/> />
<VnInput <VnInput
v-model="data.iban" v-model="data.iban"
:label="t('worker.create.iban')" :label="t('worker.create.iban')"
:rules="validate('Worker.iban')" :rules="validate('Worker.iban')"
:disable="formData.isFreelance"
> >
<template #append> <template #append>
<QIcon name="info" class="cursor-info"> <QIcon name="info" class="cursor-info">
@ -232,10 +222,11 @@ onMounted(async () => {
hide-selected hide-selected
:roles-allowed-to-create="['salesAssistant', 'hr']" :roles-allowed-to-create="['salesAssistant', 'hr']"
:rules="validate('Worker.bankEntity')" :rules="validate('Worker.bankEntity')"
:disable="formData.isFreelance"
> >
<template #form> <template #form>
<CreateBankEntityForm <CreateBankEntityForm
@on-data-saved="onBankEntityCreated($event)" @on-data-saved="(data) => bankEntitiesOptions.push(data)"
/> />
</template> </template>
<template #option="scope"> <template #option="scope">

View File

@ -1,3 +1,5 @@
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
Locker: Taquilla Locker: Taquilla
Internal: Interno
External: Externo

View File

@ -2,12 +2,12 @@ import item from './modules/item';
import customer from './modules/customer'; import customer from './modules/customer';
import ticket from './modules/ticket'; import ticket from './modules/ticket';
import claim from './modules/claim'; import claim from './modules/claim';
import route from './modules/route';
import worker from './modules/worker'; import worker from './modules/worker';
import invoiceOut from './modules/invoiceOut'; import invoiceOut from './modules/invoiceOut';
import invoiceIn from './modules/invoiceIn'; import invoiceIn from './modules/invoiceIn';
import wagon from './modules/wagon'; import wagon from './modules/wagon';
import supplier from './modules/Supplier'; import supplier from './modules/Supplier';
import route from './modules/route';
import travel from './modules/travel'; import travel from './modules/travel';
import department from './modules/department'; import department from './modules/department';
import ItemType from './modules/itemType'; import ItemType from './modules/itemType';

View File

@ -0,0 +1,59 @@
describe('WorkerCreate', () => {
const externalRadio = '.q-toolbar .q-radio:nth-child(2)';
const notification = '.q-notification__message';
const developerBossId = 120;
const internal = {
Fi: { val: '78457139E' },
'Web user': { val: 'manolo' },
Name: { val: 'Manolo' },
'Last name': { val: 'Hurtado' },
'Personal email': { val: 'manolo@mydomain.com' },
Street: { val: 'S/ DEFAULTWORKERSTREET' },
Location: { val: 1, type: 'select' },
Phone: { val: '123456789' },
'Worker code': { val: 'DWW' },
Boss: { val: developerBossId, type: 'select' },
Birth: { val: '2022-12-11T23:00:00.000Z', type: 'date', day: 11 },
};
const external = {
Fi: { val: 'Z4531219V' },
'Web user': { val: 'pepe' },
Name: { val: 'PEPE' },
'Last name': { val: 'GARCIA' },
'Personal email': { val: 'pepe@gmail.com' },
'Worker code': { val: 'PG' },
Boss: { val: developerBossId, type: 'select' },
};
beforeEach(() => {
cy.viewport(1280, 720);
cy.login('hr');
cy.visit('/#/worker/create');
});
it('should throw an error if a pay method has not been selected', () => {
cy.fillInForm(internal);
cy.saveCard();
cy.get(notification).should(
'contains.text',
'That payment method requires an IBAN'
);
});
it('should create an internal', () => {
cy.fillInForm({
...internal,
'Pay method': { val: 'PayMethod one', type: 'select' },
});
cy.saveCard();
cy.get(notification).should('contains.text', 'Data created');
});
it('should create an external', () => {
cy.get(externalRadio).click();
cy.fillInForm(external);
cy.saveCard();
cy.get(notification).should('contains.text', 'Data created');
});
});

View File

@ -8,13 +8,13 @@ describe('WorkerList', () => {
}); });
it('should load workers', () => { it('should load workers', () => {
cy.get(workerFieldNames).eq(0).should('have.text', 'jessicajones'); cy.get(workerFieldNames).eq(2).should('have.text', 'jessicajones');
cy.get(workerFieldNames).eq(1).should('have.text', 'brucebanner'); cy.get(workerFieldNames).eq(3).should('have.text', 'brucebanner');
cy.get(workerFieldNames).eq(2).should('have.text', 'charlesxavier'); cy.get(workerFieldNames).eq(4).should('have.text', 'charlesxavier');
}); });
it('should open the worker summary', () => { it('should open the worker summary', () => {
cy.openListSummary(0); cy.openListSummary(2);
cy.get('.summaryHeader div').should('have.text', '1110 - Jessica Jones'); cy.get('.summaryHeader div').should('have.text', '1110 - Jessica Jones');
cy.get('.summary .header-link') cy.get('.summary .header-link')
.eq(0) .eq(0)

View File

@ -86,6 +86,36 @@ Cypress.Commands.add('selectOption', (selector, option) => {
cy.get('.q-menu .q-item').contains(option).click(); cy.get('.q-menu .q-item').contains(option).click();
}); });
Cypress.Commands.add('fillInForm', (obj, form = '.q-form > .q-card') => {
const days = '.q-date__calendar-days .q-date__calendar-item--in';
cy.waitForElement('.q-form > .q-card');
cy.get(`${form} input`).each(([el]) => {
cy.wrap(el)
.invoke('attr', 'aria-label')
.then((ariaLabel) => {
const field = obj[ariaLabel];
if (!field) return;
const { type, val, day } = field;
switch (type) {
case 'select':
cy.wrap(el).type(val);
cy.get('.q-menu .q-item').contains(val).click();
break;
case 'date':
cy.wrap(el).click();
cy.get(days)
.eq(day ? day - 1 : 0)
.click();
break;
default:
cy.wrap(el).type(val);
break;
}
});
});
});
Cypress.Commands.add('checkOption', (selector) => { Cypress.Commands.add('checkOption', (selector) => {
cy.get(selector).find('.q-checkbox__inner').click(); cy.get(selector).find('.q-checkbox__inner').click();
}); });
@ -198,11 +228,15 @@ Cypress.Commands.add('closeSideMenu', (element) => {
Cypress.Commands.add('clearSearchbar', (element) => { Cypress.Commands.add('clearSearchbar', (element) => {
if (element) cy.waitForElement(element); if (element) cy.waitForElement(element);
cy.get('#searchbar > form > div:nth-child(1) > label > div:nth-child(1) input').clear(); cy.get(
'#searchbar > form > div:nth-child(1) > label > div:nth-child(1) input'
).clear();
}); });
Cypress.Commands.add('writeSearchbar', (value) => { Cypress.Commands.add('writeSearchbar', (value) => {
cy.get('#searchbar > form > div:nth-child(1) > label > div:nth-child(1) input').type(value); cy.get('#searchbar > form > div:nth-child(1) > label > div:nth-child(1) input').type(
value
);
}); });
Cypress.Commands.add('validateContent', (selector, expectedValue) => { Cypress.Commands.add('validateContent', (selector, expectedValue) => {
cy.get(selector).should('have.text', expectedValue); cy.get(selector).should('have.text', expectedValue);