Merge branch 'dev' of https: refs #8219//gitea.verdnatura.es/verdnatura/salix-front into 8219-InvoiceOutE2E
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
This commit is contained in:
commit
ec40dc6171
164
CHANGELOG.md
164
CHANGELOG.md
|
@ -1,3 +1,167 @@
|
|||
# Version 24.52 - 2024-01-07
|
||||
|
||||
### Added 🆕
|
||||
|
||||
- chore: refs #8197 remove console log by:alexm
|
||||
- chore: refs #8197 replace name by:alexm
|
||||
- chore: refs #8197 unnecessary file by:alexm
|
||||
- feat: #8110 apply mixin in quasar components by:Javier Segarra
|
||||
- feat(Account & AccountRole): refs #8197 add VnCardMain by:alexm
|
||||
- feat: addDptoLink by:Jtubau
|
||||
- feat: added restore ticket function in ticket descriptor menu by:Jon
|
||||
- feat: add support service wip by:jorgep
|
||||
- feat: focus menu searchbar by:jorgep
|
||||
- feat: make additional data object by:jorgep
|
||||
- feat: message to grant access by:jorgep
|
||||
- feat: refs #6583 add default param by:jorgep
|
||||
- feat: refs #6583 add destination opt filter by:jorgep
|
||||
- feat: refs #6583 add icon by:jorgep
|
||||
- feat: refs #6583 add locale by:jorgep
|
||||
- feat: refs #7072 added test to computed fn total by:Jtubau
|
||||
- feat: refs #7235 update invoice out global form to fetch config based on serial type by:jgallego
|
||||
- feat: refs #7301 add exclude inventory supplier from list by:pablone
|
||||
- feat: refs #7301 enhance VnDateBadge styling and improve ItemLastEntries component by:pablone
|
||||
- feat: refs #7882 Added distribution point by:guillermo
|
||||
- feat: refs #7882 Added longitude & latitude by:guillermo
|
||||
- feat: refs #7936 add autocomplete on tab fn by:jorgep
|
||||
- feat: refs #7936 add company filter by:jorgep
|
||||
- feat: refs #7936 add currency check before fetching by:jorgep
|
||||
- feat: refs #7936 add dueDated field by:jorgep
|
||||
- feat: refs #7936 add number validation to VnInputNumber & new daysAgo filter in InvoiceInFilter by:jorgep
|
||||
- feat: refs #7936 add optionCaption by:jorgep
|
||||
- feat: refs #7936 add row click navigation to InvoiceInSerial by:jorgep
|
||||
- feat: refs #7936 add unit tests by:jorgep
|
||||
- feat: refs #7936 add useAccountShortToStandard composable by:jorgep
|
||||
- feat: refs #7936 calculate exchange & update taxable base by:jorgep
|
||||
- feat: refs #7936 enhance downloadFile function to support opening in a new tab by:jorgep
|
||||
- feat: refs #7936 enhance getTotal fn & add unit tests by:jorgep
|
||||
- feat: refs #7936 enhance vn-select by:jorgep
|
||||
- feat: refs #7936 improve optionLabel logic in InvoiceInVat component for better handling of numeric values by:jorgep
|
||||
- feat: refs #7936 limit decimal places by:jorgep
|
||||
- feat: refs #7936 make fields required by:jorgep
|
||||
- feat: refs #7936 show country code & isVies fields by:jorgep
|
||||
- feat: refs #7936 show id & value by:jorgep
|
||||
- feat: refs #7936 simplify optionLabel wip by:jorgep
|
||||
- feat: refs #7936 update 'isVies' label to use global translation key by:jorgep
|
||||
- feat: refs #7936 update option labels in InvoiceIn components for better clarity by:jorgep
|
||||
- feat: refs #7936 use default invoice data by:jorgep
|
||||
- feat: refs #8001 change request by:robert
|
||||
- feat: refs #8001 ticketExpeditionGrafana by:robert
|
||||
- feat: refs #8194 created VnSelectWorker component and use it in Lilium by:Jon
|
||||
- feat: refs #8197 better leftMenu and VnCardMain improvements by:alexm
|
||||
- feat: refs #8197 default leftMenu by:alexm
|
||||
- feat: refs #8197 default sectionName by:alexm
|
||||
- feat: refs #8197 keepData in VnSection by:alexm
|
||||
- feat: refs #8197 vnTableFilter by:alexm
|
||||
- feat: refs #8197 working rightMenu by:alexm
|
||||
- feat: remove re-fetch when add element by:Javier Segarra
|
||||
- feat: remove search after category by:Javier Segarra
|
||||
- feat: requested changes in item module by:Jon
|
||||
- feat: update quantity by:Javier Segarra
|
||||
- feat(VnPaginate): refs #8197 hold data when change to Card by:alexm
|
||||
|
||||
### Changed 📦
|
||||
|
||||
- perf: #6896 REMOVE COMMENTS by:Javier Segarra
|
||||
- perf: qFormMixin by:Javier Segarra
|
||||
- perf: qFormMixin improvement by:Javier Segarra
|
||||
- perf: refs #8194 select worker component by:Jon
|
||||
- perf: refs #8197 perf by:alexm
|
||||
- perf: remove comments by:Javier Segarra
|
||||
- perf: remove unused variables (origin/warmfix_noUsedVars) by:Javier Segarra
|
||||
- refactor: added again search emit by:Jon
|
||||
- refactor: add useCau composable by:jorgep
|
||||
- refactor: deleted log by:Jon
|
||||
- refactor: deleted onUnmounted code by:Jon
|
||||
- refactor: deleted useless hidden tag by:Jon
|
||||
- refactor: deleted warnings and corrected itemTag by:Jon
|
||||
- refactor: drop logic by:jorgep
|
||||
- refactor: ignore params when searching by id on searchbar (origin/VnSearchbar-SearchRemoveParams) by:Jon
|
||||
- refactor: log error by:Jon
|
||||
- refactor: refs #7936 locale by:jorgep
|
||||
- refactor: refs #7936 simplify getTotal fn by:jorgep
|
||||
- refactor: refs #7936 update label capitalization and replace invoice type options by:jorgep
|
||||
- refactor: refs #8194 deleted unnecessary label by:Jon
|
||||
- refactor: refs #8194 modified select worker template by:Jon
|
||||
- refactor: refs #8194 modified select worker to allow no one filter from monitor ticket by:Jon
|
||||
- refactor: refs #8194 moved translation to the correct place by:Jon
|
||||
- refactor: refs #8194 requested changes by:Jon
|
||||
- refactor: refs #8194 structure changes in component and related files by:Jon
|
||||
- refactor: refs #8197 adapt AccountAcls to VnCardMain by:alexm
|
||||
- refactor: refs #8197 adapt AccountAlias by:alexm
|
||||
- refactor: refs #8197 adapt Ticket to VnCardMain by:alexm
|
||||
- refactor: refs #8197 backward compatible (8197-VnCardMain_backwardCompatibility) by:alexm
|
||||
- refactor: refs #8197 rename VnSectionMain to VnModule and VnCardMain to VnSection by:alexm
|
||||
- refactor: refs #8288 changed invoice out spanish translation by:provira
|
||||
- refactor: use locale keys by:jorgep
|
||||
- refactor: use teleport to avoid qdrawer overlapping by:Jon
|
||||
- refactor: use VnSelectWorker by:Jon
|
||||
|
||||
### Fixed 🛠️
|
||||
|
||||
- fix: account by:carlossa
|
||||
- fix: account create by:carlossa
|
||||
- fix: accountList create by:carlossa
|
||||
- fix(AccountList): use $refs by:alexm
|
||||
- fix: add data-key by:alexm
|
||||
- fix: addLocales by:Jtubau
|
||||
- fix: dated field by:Jon
|
||||
- fix: e2e by:jorgep
|
||||
- fix: fix department filter by:carlossa
|
||||
- fix: fixed translations by:Javier Segarra
|
||||
- fix: fixed translations by:provira
|
||||
- fix: get total from api by:Javier Segarra
|
||||
- fix: handle non-object options by:jorgep
|
||||
- fix: monitorPayMethodFilter by:carlossa
|
||||
- fix: orderBy priority by:Javier Segarra
|
||||
- fix: prevent null by:jorgep
|
||||
- fix: redirection vnTable VnTableFilter by:alexm
|
||||
- fix: refs #6389 fix filter trad by:carlossa
|
||||
- fix: refs #6389 fix front, filters, itp by:carlossa
|
||||
- fix: refs #6389 front add packing filter by:carlossa
|
||||
- fix: refs #6389 front by:carlossa
|
||||
- fix: refs #6389 front filters by:carlossa
|
||||
- fix: refs #6389 ipt by:carlossa
|
||||
- fix: refs #6389 packing by:carlossa
|
||||
- fix: refs #6583 update checkbox for filtering by destination in TicketAdvanceFilter by:jorgep
|
||||
- fix: refs #7031 add test e2e by:carlossa
|
||||
- fix: refs #7031 fix zoneTest by:carlossa
|
||||
- fix: refs #7301 unnecessary console logs from ItemLastEntries.vue by:pablone
|
||||
- fix: refs #7936 changes by:jorgep
|
||||
- fix: refs #7936 decimal places & locale by:jorgep
|
||||
- fix: refs #7936 descriptor & dueday by:jorgep
|
||||
- fix: refs #7936 exclude disabled els on tab by:jorgep
|
||||
- fix: refs #7936 format tax calculation to two decimal places by:jorgep
|
||||
- fix: refs #7936 improve error handling by:jorgep
|
||||
- fix: refs #7936 redirection by:jorgep
|
||||
- fix: refs #7936 rollback by:jorgep
|
||||
- fix: refs #7936 serial by:jorgep
|
||||
- fix: refs #7936 tabulation wip by:jorgep
|
||||
- fix: refs #7936 test by:jorgep
|
||||
- fix: refs #8114 clean by:carlossa
|
||||
- fix: refs #8114 fix agencyList by:carlossa
|
||||
- fix: refs #8114 fix lifeCycle hooks by:carlossa
|
||||
- fix: refs #8114 fix pr by:carlossa
|
||||
- fix: refs #8114 fix removeAddress by:carlossa
|
||||
- fix: refs #8114 orderList by:carlossa
|
||||
- fix: refs #8114 remove logs by:carlossa
|
||||
- fix: refs #8197 mapKey (origin/8197-perf_vnTableInside, 8197-perf_vnTableInside) by:alexm
|
||||
- fix: refs #8197 redirection (8197-perf_redirection) by:alexm
|
||||
- fix: refs #8197 staticParams and redirect by:alexm
|
||||
- fix: refs #8197 vnPaginate onFetch emit by:alexm
|
||||
- fix: refs #8197 vnPaginate when change :id by:alexm
|
||||
- fix: refs #8197 vnTableFilter in vnTable by:alexm
|
||||
- fix: refs #8315 ticketBoxing test by:alexm
|
||||
- fix: remove url by:carlossa
|
||||
- fix: rollback by:jorgep
|
||||
- fix: test by:jorgep
|
||||
- fix(VnDmsList): refs #8197 add mapKey by:alexm
|
||||
- revert: refs #8197 arrayData changes by:alexm
|
||||
- test: refs #8197 fix e2e by:alexm
|
||||
- test: refs #8315 fix claimDevelopment fixtures by:alexm
|
||||
- test: refs #8315 fix clientList by:alexm
|
||||
- test: refs #8315 fix VnSelect in e2e by:alexm
|
||||
|
||||
# Version 24.50 - 2024-12-10
|
||||
|
||||
### Added 🆕
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "salix-front",
|
||||
"version": "25.02.0",
|
||||
"version": "25.04.0",
|
||||
"description": "Salix frontend",
|
||||
"productName": "Salix",
|
||||
"author": "Verdnatura",
|
||||
|
|
|
@ -62,6 +62,7 @@ async function setProvince(id, data) {
|
|||
postcodeFormData.provinceFk = id;
|
||||
await fetchTowns();
|
||||
}
|
||||
|
||||
async function onProvinceCreated(data) {
|
||||
postcodeFormData.provinceFk = data.id;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ const onDataSaved = (data) => {
|
|||
v-model.number="data.quantity"
|
||||
type="number"
|
||||
autofocus
|
||||
data-cy="regularizeStockInput"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
|
|
|
@ -314,7 +314,7 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
|
|||
show-if-above
|
||||
>
|
||||
<QScrollArea class="fit">
|
||||
<VnTableFilter :data-key="$attrs['data-key']" :columns="columns" />
|
||||
<VnTableFilter :data-key="$attrs['data-key']" :columns="columns" :redirect="redirect" />
|
||||
</QScrollArea>
|
||||
</QDrawer>
|
||||
<CrudModel
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import VnFilterPanel from 'components/ui/VnFilterPanel.vue';
|
||||
import VnFilter from 'components/VnTable/VnFilter.vue';
|
||||
|
@ -11,16 +10,11 @@ defineProps({
|
|||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
chipLocale: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
searchUrl: {
|
||||
type: [String, Boolean],
|
||||
default: 'table',
|
||||
},
|
||||
});
|
||||
const { t } = useI18n();
|
||||
|
||||
const tableFilterRef = ref([]);
|
||||
|
||||
|
@ -62,9 +56,9 @@ function columnName(col) {
|
|||
:columns="columns"
|
||||
/>
|
||||
</template>
|
||||
<template #tags="{ tag, formatFn }" v-if="chipLocale">
|
||||
<template #tags="{ tag, formatFn, getLocale }">
|
||||
<div class="q-gutter-x-xs">
|
||||
<strong>{{ t(`${chipLocale}.${tag.label}`) }}: </strong>
|
||||
<strong>{{ getLocale(`${tag.label}`) }}: </strong>
|
||||
<span>{{ formatFn(tag.value) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -14,6 +14,7 @@ defineProps({
|
|||
hide-dropdown-icon
|
||||
focus-on-mount
|
||||
@update:model-value="promise"
|
||||
data-cy="vnBtnSelect_select"
|
||||
/>
|
||||
</QBtnDropdown>
|
||||
</template>
|
||||
|
|
|
@ -11,9 +11,9 @@ function getBadgeAttrs(date) {
|
|||
|
||||
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' };
|
||||
if (timeDiff == 0) return { color: 'warning', class: 'black-text-color' };
|
||||
if (timeDiff < 0) return { color: 'success', class: 'black-text-color' };
|
||||
return { color: 'transparent', class: 'normal-text-color' };
|
||||
}
|
||||
|
||||
function formatShippedDate(date) {
|
||||
|
@ -29,3 +29,11 @@ function formatShippedDate(date) {
|
|||
{{ formatShippedDate(date) }}
|
||||
</QBadge>
|
||||
</template>
|
||||
<style lang="scss">
|
||||
.black-text-color {
|
||||
color: var(--vn-black-text-color);
|
||||
}
|
||||
.normal-text-color {
|
||||
color: var(--vn-text-color);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -297,7 +297,7 @@ defineExpose({
|
|||
ref="dmsRef"
|
||||
:data-key="$props.model"
|
||||
:url="$props.model"
|
||||
:filter="dmsFilter"
|
||||
:user-filter="dmsFilter"
|
||||
:order="['dmsFk DESC']"
|
||||
:auto-load="true"
|
||||
@on-fetch="setData"
|
||||
|
|
|
@ -141,13 +141,16 @@ const handleInsertMode = (e) => {
|
|||
<QIcon
|
||||
name="close"
|
||||
size="xs"
|
||||
v-if="
|
||||
hover &&
|
||||
value &&
|
||||
!$attrs.disabled &&
|
||||
!$attrs.readonly &&
|
||||
$props.clearable
|
||||
"
|
||||
:style="{
|
||||
visibility:
|
||||
hover &&
|
||||
value &&
|
||||
!$attrs.disabled &&
|
||||
!$attrs.readonly &&
|
||||
$props.clearable
|
||||
? 'visible'
|
||||
: 'hidden',
|
||||
}"
|
||||
@click="
|
||||
() => {
|
||||
value = null;
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
<script setup>
|
||||
import { onMounted, watch, computed, ref, useAttrs } from 'vue';
|
||||
import { date } from 'quasar';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import VnDate from './VnDate.vue';
|
||||
import { useRequired } from 'src/composables/useRequired';
|
||||
|
||||
const $attrs = useAttrs();
|
||||
const { isRequired, requiredFieldRule } = useRequired($attrs);
|
||||
const model = defineModel({ type: [String, Date] });
|
||||
const { t } = useI18n();
|
||||
|
||||
const $props = defineProps({
|
||||
isOutlined: {
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
<script setup>
|
||||
import { computed, ref, useAttrs } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { date } from 'quasar';
|
||||
import VnTime from './VnTime.vue';
|
||||
import { useRequired } from 'src/composables/useRequired';
|
||||
|
||||
const $attrs = useAttrs();
|
||||
const { isRequired, requiredFieldRule } = useRequired($attrs);
|
||||
const { t } = useI18n();
|
||||
const model = defineModel({ type: String });
|
||||
const props = defineProps({
|
||||
timeOnly: {
|
||||
|
|
|
@ -20,16 +20,15 @@ const hasContent = ref();
|
|||
let observer;
|
||||
|
||||
onMounted(() => {
|
||||
if (teleportRef.value) {
|
||||
const checkContent = () => {
|
||||
hasContent.value = teleportRef.value.innerHTML.trim() !== '';
|
||||
};
|
||||
if (!teleportRef.value) return;
|
||||
const checkContent = () => {
|
||||
hasContent.value = teleportRef.value?.innerHTML?.trim() !== '';
|
||||
};
|
||||
|
||||
observer = new MutationObserver(checkContent);
|
||||
observer.observe(teleportRef.value, { childList: true, subtree: true });
|
||||
observer = new MutationObserver(checkContent);
|
||||
observer.observe(teleportRef.value, { childList: true, subtree: true });
|
||||
|
||||
checkContent();
|
||||
}
|
||||
checkContent();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -4,11 +4,12 @@ import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
|||
import VnTableFilter from '../VnTable/VnTableFilter.vue';
|
||||
import { onBeforeMount, computed } from 'vue';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const $props = defineProps({
|
||||
section: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
dataKey: {
|
||||
type: String,
|
||||
|
@ -38,14 +39,28 @@ const $props = defineProps({
|
|||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
keepData: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const sectionValue = computed(() => $props.section ?? $props.dataKey);
|
||||
const route = useRoute();
|
||||
let arrayData;
|
||||
const sectionValue = computed(() => $props.section ?? $props.dataKey);
|
||||
const isMainSection = computed(() => {
|
||||
const isSame = sectionValue.value == route.name;
|
||||
if (!isSame && arrayData) {
|
||||
arrayData.reset(['userParams', 'userFilter']);
|
||||
}
|
||||
return isSame;
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
if ($props.dataKey)
|
||||
arrayData = useArrayData($props.dataKey, {
|
||||
searchUrl: 'table',
|
||||
keepData: $props.keepData,
|
||||
...$props.arrayDataProps,
|
||||
navigate: $props.redirect,
|
||||
});
|
||||
|
@ -74,6 +89,6 @@ onBeforeMount(() => {
|
|||
</slot>
|
||||
</template>
|
||||
</RightMenu>
|
||||
<slot name="body" v-if="sectionValue == $route.name" />
|
||||
<slot name="body" v-if="isMainSection" />
|
||||
<RouterView v-else />
|
||||
</template>
|
||||
|
|
|
@ -113,8 +113,15 @@ const $props = defineProps({
|
|||
});
|
||||
|
||||
const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
|
||||
const { optionLabel, optionValue, optionFilter, optionFilterValue, options, modelValue } =
|
||||
toRefs($props);
|
||||
const {
|
||||
optionLabel,
|
||||
optionValue,
|
||||
optionCaption,
|
||||
optionFilter,
|
||||
optionFilterValue,
|
||||
options,
|
||||
modelValue,
|
||||
} = toRefs($props);
|
||||
const myOptions = ref([]);
|
||||
const myOptionsOriginal = ref([]);
|
||||
const vnSelectRef = ref();
|
||||
|
@ -198,10 +205,10 @@ function filter(val, options) {
|
|||
}
|
||||
|
||||
if (!row) return;
|
||||
const id = row[$props.optionValue];
|
||||
const id = String(row[$props.optionValue]);
|
||||
const optionLabel = String(row[$props.optionLabel]).toLowerCase();
|
||||
|
||||
return id == search || optionLabel.includes(search);
|
||||
return id.includes(search) || optionLabel.includes(search);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -321,6 +328,11 @@ function handleKeyDown(event) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getCaption(opt) {
|
||||
if (optionCaption.value === false) return;
|
||||
return opt[optionCaption.value] || opt[optionValue.value];
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -391,8 +403,8 @@ function handleKeyDown(event) {
|
|||
<QItemLabel>
|
||||
{{ opt[optionLabel] }}
|
||||
</QItemLabel>
|
||||
<QItemLabel caption v-if="optionCaption !== false">
|
||||
{{ `#${opt[optionCaption] || opt[optionValue]}` }}
|
||||
<QItemLabel caption v-if="getCaption(opt)">
|
||||
{{ `#${getCaption(opt)}` }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
|
|
|
@ -51,6 +51,7 @@ const url = computed(() => {
|
|||
option-value="id"
|
||||
option-label="nickname"
|
||||
:fields="['id', 'name', 'nickname', 'code']"
|
||||
:filter-options="['id', 'name', 'nickname', 'code']"
|
||||
sort-by="nickname ASC"
|
||||
>
|
||||
<template #prepend v-if="$props.hasAvatar">
|
||||
|
@ -71,7 +72,7 @@ const url = computed(() => {
|
|||
{{ scope.opt.nickname }}
|
||||
</QItemLabel>
|
||||
<QItemLabel caption v-else>
|
||||
{{ scope.opt.nickname }}, {{ scope.opt.code }}
|
||||
#{{ scope.opt.id }}, {{ scope.opt.nickname }}, {{ scope.opt.code }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import VnJsonValue from 'src/components/common/VnJsonValue.vue';
|
||||
import { createWrapper } from 'app/test/vitest/helper';
|
||||
|
||||
const buildComponent = (props) => {
|
||||
return createWrapper(VnJsonValue, {
|
||||
props,
|
||||
}).wrapper;
|
||||
};
|
||||
|
||||
describe('VnJsonValue', () => {
|
||||
it('renders null value correctly', async () => {
|
||||
const wrapper = buildComponent({ value: null });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toBe('∅');
|
||||
expect(span.classes()).toContain('json-null');
|
||||
});
|
||||
|
||||
it('renders boolean true correctly', async () => {
|
||||
const wrapper = buildComponent({ value: true });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toBe('✓');
|
||||
expect(span.classes()).toContain('json-true');
|
||||
});
|
||||
|
||||
it('renders boolean false correctly', async () => {
|
||||
const wrapper = buildComponent({ value: false });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toBe('✗');
|
||||
expect(span.classes()).toContain('json-false');
|
||||
});
|
||||
|
||||
it('renders a short string correctly', async () => {
|
||||
const wrapper = buildComponent({ value: 'Hello' });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toBe('Hello');
|
||||
expect(span.classes()).toContain('json-string');
|
||||
});
|
||||
|
||||
it('renders a long string correctly with ellipsis', async () => {
|
||||
const longString = 'a'.repeat(600);
|
||||
const wrapper = buildComponent({ value: longString });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toContain('...');
|
||||
expect(span.text().length).toBeLessThanOrEqual(515);
|
||||
expect(span.attributes('title')).toBe(longString);
|
||||
expect(span.classes()).toContain('json-string');
|
||||
});
|
||||
|
||||
it('renders a number correctly', async () => {
|
||||
const wrapper = buildComponent({ value: 123.4567 });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toBe('123.457');
|
||||
expect(span.classes()).toContain('json-number');
|
||||
});
|
||||
|
||||
it('renders an integer correctly', async () => {
|
||||
const wrapper = buildComponent({ value: 42 });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toBe('42');
|
||||
expect(span.classes()).toContain('json-number');
|
||||
});
|
||||
|
||||
it('renders a date correctly', async () => {
|
||||
const date = new Date('2023-01-01');
|
||||
const wrapper = buildComponent({ value: date });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toBe('2023-01-01');
|
||||
expect(span.classes()).toContain('json-object');
|
||||
});
|
||||
|
||||
it('renders an object correctly', async () => {
|
||||
const obj = { key: 'value' };
|
||||
const wrapper = buildComponent({ value: obj });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toBe(obj.toString());
|
||||
expect(span.classes()).toContain('json-object');
|
||||
});
|
||||
|
||||
it('renders an array correctly', async () => {
|
||||
const arr = [1, 2, 3];
|
||||
const wrapper = buildComponent({ value: arr });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toBe(arr.toString());
|
||||
expect(span.classes()).toContain('json-object');
|
||||
});
|
||||
|
||||
it('updates value when prop changes', async () => {
|
||||
const wrapper = buildComponent({ value: true });
|
||||
await wrapper.setProps({ value: 123 });
|
||||
const span = wrapper.find('span');
|
||||
expect(span.text()).toBe('123');
|
||||
expect(span.classes()).toContain('json-number');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,107 @@
|
|||
import { describe, it, expect, vi, beforeAll, afterEach, beforeEach } from 'vitest';
|
||||
import { createWrapper, axios } from 'app/test/vitest/helper';
|
||||
import VnNotes from 'src/components/ui/VnNotes.vue';
|
||||
|
||||
describe('VnNotes', () => {
|
||||
let vm;
|
||||
let wrapper;
|
||||
let spyFetch;
|
||||
let postMock;
|
||||
let expectedBody;
|
||||
const mockData= {name: 'Tony', lastName: 'Stark', text: 'Test Note', observationTypeFk: 1};
|
||||
|
||||
function generateExpectedBody() {
|
||||
expectedBody = {...vm.$props.body, ...{ text: vm.newNote.text, observationTypeFk: vm.newNote.observationTypeFk }};
|
||||
}
|
||||
|
||||
async function setTestParams(text, observationType, type){
|
||||
vm.newNote.text = text;
|
||||
vm.newNote.observationTypeFk = observationType;
|
||||
wrapper.setProps({ selectType: type });
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
vi.spyOn(axios, 'get').mockReturnValue({ data: [] });
|
||||
|
||||
wrapper = createWrapper(VnNotes, {
|
||||
propsData: {
|
||||
url: '/test',
|
||||
body: { name: 'Tony', lastName: 'Stark' },
|
||||
}
|
||||
});
|
||||
wrapper = wrapper.wrapper;
|
||||
vm = wrapper.vm;
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
postMock = vi.spyOn(axios, 'post').mockResolvedValue(mockData);
|
||||
spyFetch = vi.spyOn(vm.vnPaginateRef, 'fetch').mockImplementation(() => vi.fn());
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
expectedBody = {};
|
||||
});
|
||||
|
||||
describe('insert', () => {
|
||||
it('should not call axios.post and vnPaginateRef.fetch if newNote.text is null', async () => {
|
||||
await setTestParams( null, null, true );
|
||||
|
||||
await vm.insert();
|
||||
|
||||
expect(postMock).not.toHaveBeenCalled();
|
||||
expect(spyFetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call axios.post and vnPaginateRef.fetch if newNote.text is empty', async () => {
|
||||
await setTestParams( "", null, false );
|
||||
|
||||
await vm.insert();
|
||||
|
||||
expect(postMock).not.toHaveBeenCalled();
|
||||
expect(spyFetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is true', async () => {
|
||||
await setTestParams( "Test Note", null, true );
|
||||
|
||||
await vm.insert();
|
||||
|
||||
expect(postMock).not.toHaveBeenCalled();
|
||||
expect(spyFetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is missing and selectType is false', async () => {
|
||||
await setTestParams( "Test Note", null, false );
|
||||
|
||||
generateExpectedBody();
|
||||
|
||||
await vm.insert();
|
||||
|
||||
expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
|
||||
expect(spyFetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call axios.post and vnPaginateRef.fetch if observationTypeFk is setted and selectType is false', async () => {
|
||||
await setTestParams( "Test Note", 1, false );
|
||||
|
||||
generateExpectedBody();
|
||||
|
||||
await vm.insert();
|
||||
|
||||
expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
|
||||
expect(spyFetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call axios.post and vnPaginateRef.fetch when newNote is valid', async () => {
|
||||
await setTestParams( "Test Note", 1, true );
|
||||
|
||||
generateExpectedBody();
|
||||
|
||||
await vm.insert();
|
||||
|
||||
expect(postMock).toHaveBeenCalledWith(vm.$props.url, expectedBody);
|
||||
expect(spyFetch).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -190,7 +190,7 @@ const getLocale = (label) => {
|
|||
const globalLocale = `globals.params.${param}`;
|
||||
if (te(globalLocale)) return t(globalLocale);
|
||||
else if (te(t(`params.${param}`)));
|
||||
else return t(`${route.meta.moduleName}.params.${param}`);
|
||||
else return t(`${route.meta.moduleName.toLowerCase()}.params.${param}`);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
:url="$props.url"
|
||||
order="created DESC"
|
||||
:limit="0"
|
||||
:filter="$props.filter"
|
||||
:user-filter="$props.filter"
|
||||
auto-load
|
||||
ref="vnPaginateRef"
|
||||
class="show"
|
||||
|
|
|
@ -111,6 +111,7 @@ onMounted(async () => {
|
|||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (!store.keepData) arrayData.reset(['data']);
|
||||
arrayData.resetPagination();
|
||||
});
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
<script setup>
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { onMounted, ref, computed, watch } from 'vue';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { useArrayData } from 'composables/useArrayData';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStateStore } from 'src/stores/useStateStore';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const quasar = useQuasar();
|
||||
const { t } = useI18n();
|
||||
const state = useStateStore();
|
||||
const route = useRoute();
|
||||
|
||||
const props = defineProps({
|
||||
dataKey: {
|
||||
|
@ -83,6 +85,17 @@ if (props.redirect)
|
|||
};
|
||||
let arrayData = useArrayData(props.dataKey, arrayDataProps);
|
||||
let store = arrayData.store;
|
||||
const to = computed(() => {
|
||||
const url = { path: route.path, query: { ...(route.query ?? {}) } };
|
||||
const searchUrl = arrayData.store.searchUrl;
|
||||
const currentFilter = {
|
||||
...arrayData.store.currentFilter,
|
||||
search: searchText.value || undefined,
|
||||
};
|
||||
|
||||
if (searchUrl) url.query[searchUrl] = JSON.stringify(currentFilter);
|
||||
return url;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.dataKey,
|
||||
|
@ -126,28 +139,38 @@ async function search() {
|
|||
delete filter.params.search;
|
||||
}
|
||||
await arrayData.applyFilter(filter);
|
||||
searchText.value = undefined;
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<Teleport to="#searchbar" v-if="state.isHeaderMounted()">
|
||||
<QForm @submit="search" id="searchbarForm">
|
||||
<RouterLink
|
||||
:to="to"
|
||||
@click="
|
||||
!$event.shiftKey && !$event.ctrlKey && search();
|
||||
$refs.input.focus();
|
||||
"
|
||||
>
|
||||
<QIcon
|
||||
v-if="!quasar.platform.is.mobile"
|
||||
class="cursor-pointer"
|
||||
name="search"
|
||||
size="sm"
|
||||
>
|
||||
<QTooltip>{{ t('link') }}</QTooltip>
|
||||
</QIcon>
|
||||
</RouterLink>
|
||||
<VnInput
|
||||
id="searchbar"
|
||||
ref="input"
|
||||
v-model.trim="searchText"
|
||||
:placeholder="t(props.label)"
|
||||
dense
|
||||
standout
|
||||
autofocus
|
||||
data-cy="vnSearchBar"
|
||||
data-cy="vn-searchbar"
|
||||
borderless
|
||||
>
|
||||
<template #prepend>
|
||||
<QIcon
|
||||
v-if="!quasar.platform.is.mobile"
|
||||
class="cursor-pointer"
|
||||
name="search"
|
||||
@click="search"
|
||||
/>
|
||||
</template>
|
||||
<template #append>
|
||||
<QIcon
|
||||
v-if="props.info && $q.screen.gt.xs"
|
||||
|
@ -172,20 +195,52 @@ async function search() {
|
|||
.q-field {
|
||||
transition: width 0.36s;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
:deep(.q-field__native) {
|
||||
padding-top: 10px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
:deep(.q-field--dark .q-field__native:focus) {
|
||||
color: black;
|
||||
}
|
||||
|
||||
:deep(.q-field--focused) {
|
||||
.q-icon {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
.cursor-info {
|
||||
cursor: help;
|
||||
}
|
||||
#searchbar {
|
||||
.q-field--standout.q-field--highlighted .q-field__control {
|
||||
|
||||
.q-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
padding: 0 5px;
|
||||
background-color: var(--vn-search-color);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--vn-search-color-hover);
|
||||
}
|
||||
&:focus-within {
|
||||
background-color: white;
|
||||
color: black;
|
||||
.q-field__native,
|
||||
|
||||
.q-icon {
|
||||
color: black !important;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.q-icon {
|
||||
color: var(--vn-label-color);
|
||||
}
|
||||
</style>
|
||||
<i18n>
|
||||
en:
|
||||
link: click to search, ctrl + click to open in a new tab, shift + click to open in a new window
|
||||
es:
|
||||
link: clic para buscar, ctrl + clic para abrir en una nueva pestaña, shift + clic para abrir en una nueva ventana
|
||||
</i18n>
|
||||
|
|
|
@ -53,6 +53,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
'searchUrl',
|
||||
'navigate',
|
||||
'mapKey',
|
||||
'keepData',
|
||||
];
|
||||
if (typeof userOptions === 'object') {
|
||||
for (const option in userOptions) {
|
||||
|
@ -75,26 +76,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
|
||||
cancelRequest();
|
||||
canceller = new AbortController();
|
||||
|
||||
const filter = {
|
||||
limit: store.limit,
|
||||
};
|
||||
let userParams = { ...store.userParams };
|
||||
|
||||
Object.assign(filter, store.userFilter);
|
||||
|
||||
let where;
|
||||
if (filter?.where || store.filter?.where)
|
||||
where = Object.assign(filter?.where ?? {}, store.filter?.where ?? {});
|
||||
Object.assign(filter, store.filter);
|
||||
filter.where = where;
|
||||
const params = { filter };
|
||||
|
||||
Object.assign(params, userParams);
|
||||
if (params.filter) params.filter.skip = store.skip;
|
||||
if (store?.order && typeof store?.order == 'string') store.order = [store.order];
|
||||
if (store.order?.length) params.filter.order = [...store.order];
|
||||
else delete params.filter.order;
|
||||
const { params, limit } = getCurrentFilter();
|
||||
|
||||
store.currentFilter = JSON.parse(JSON.stringify(params));
|
||||
delete store.currentFilter.filter.include;
|
||||
|
@ -120,7 +102,6 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
params,
|
||||
});
|
||||
|
||||
const { limit } = filter;
|
||||
store.hasMoreData = limit && response.data.length >= limit;
|
||||
|
||||
processData(response.data, { map: !!store.mapKey, append });
|
||||
|
@ -290,6 +271,31 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
router.replace(newUrl);
|
||||
}
|
||||
|
||||
function getCurrentFilter() {
|
||||
const filter = {
|
||||
limit: store.limit,
|
||||
};
|
||||
|
||||
let userParams = { ...store.userParams };
|
||||
|
||||
Object.assign(filter, store.userFilter);
|
||||
|
||||
let where;
|
||||
if (filter?.where || store.filter?.where)
|
||||
where = Object.assign(filter?.where ?? {}, store.filter?.where ?? {});
|
||||
Object.assign(filter, store.filter);
|
||||
filter.where = where;
|
||||
const params = { filter };
|
||||
|
||||
Object.assign(params, userParams);
|
||||
if (params.filter) params.filter.skip = store.skip;
|
||||
if (store?.order && typeof store?.order == 'string') store.order = [store.order];
|
||||
if (store.order?.length) params.filter.order = [...store.order];
|
||||
else delete params.filter.order;
|
||||
|
||||
return { filter, params, limit: filter.limit };
|
||||
}
|
||||
|
||||
function processData(data, { map = true, append = true }) {
|
||||
if (!append) {
|
||||
store.data = [];
|
||||
|
@ -302,7 +308,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
for (const row of data) {
|
||||
const key = row[store.mapKey];
|
||||
const val = { ...row, key };
|
||||
if (store.map.has(key)) {
|
||||
if (key && store.map.has(key)) {
|
||||
const { position } = store.map.get(key);
|
||||
val.position = position;
|
||||
store.map.set(key, val);
|
||||
|
@ -322,6 +328,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
fetch,
|
||||
applyFilter,
|
||||
addFilter,
|
||||
getCurrentFilter,
|
||||
addFilterWhere,
|
||||
addOrder,
|
||||
deleteOrder,
|
||||
|
|
|
@ -3,20 +3,23 @@
|
|||
@import '@quasar/quasar-ui-qcalendar/src/QCalendarMonth.sass';
|
||||
|
||||
body.body--light {
|
||||
--font-color: black;
|
||||
--vn-header-color: #cecece;
|
||||
--vn-page-color: #ffffff;
|
||||
--vn-section-color: #e0e0e0;
|
||||
--vn-section-hover-color: #b9b9b9;
|
||||
--vn-text-color: var(--font-color);
|
||||
--vn-text-color: black;
|
||||
--vn-label-color: #5f5f5f;
|
||||
--vn-accent-color: #e7e3e3;
|
||||
--vn-search-color: #d4d4d4;
|
||||
--vn-search-color-hover: #cfcfcf;
|
||||
--vn-empty-tag: #acacac;
|
||||
--vn-black-text-color: black;
|
||||
--vn-text-color-contrast: white;
|
||||
|
||||
background-color: var(--vn-page-color);
|
||||
|
||||
.q-header .q-toolbar {
|
||||
color: var(--font-color);
|
||||
color: var(--vn-text-color);
|
||||
}
|
||||
}
|
||||
body.body--dark {
|
||||
|
@ -27,7 +30,11 @@ body.body--dark {
|
|||
--vn-text-color: white;
|
||||
--vn-label-color: #a8a8a8;
|
||||
--vn-accent-color: #424242;
|
||||
--vn-search-color: #4b4b4b;
|
||||
--vn-search-color-hover: #5b5b5b;
|
||||
--vn-empty-tag: #2d2d2d;
|
||||
--vn-black-text-color: black;
|
||||
--vn-text-color-contrast: black;
|
||||
|
||||
background-color: var(--vn-page-color);
|
||||
}
|
||||
|
@ -86,6 +93,10 @@ select:-webkit-autofill {
|
|||
background-color: var(--vn-section-hover-color);
|
||||
}
|
||||
|
||||
.bg-vn-page {
|
||||
background-color: var(--vn-page-color);
|
||||
}
|
||||
|
||||
.color-vn-label {
|
||||
color: var(--vn-label-color);
|
||||
}
|
||||
|
@ -189,7 +200,7 @@ select:-webkit-autofill {
|
|||
|
||||
.q-tooltip {
|
||||
background-color: var(--vn-page-color);
|
||||
color: var(--font-color);
|
||||
color: var(--vn-text-color);
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
|
|
|
@ -456,6 +456,11 @@ entry:
|
|||
landing: Landing
|
||||
isExcludedFromAvailable: Es inventory
|
||||
ticket:
|
||||
params:
|
||||
ticketFk: Ticket ID
|
||||
weekDay: Weekday
|
||||
agencyModeFk: Agency
|
||||
id: Worker
|
||||
card:
|
||||
customerId: Customer ID
|
||||
customerCard: Customer card
|
||||
|
@ -698,6 +703,11 @@ wagon:
|
|||
minHeightBetweenTrays: 'The minimum height between trays is '
|
||||
maxWagonHeight: 'The maximum height of the wagon is '
|
||||
uncompleteTrays: There are incomplete trays
|
||||
params:
|
||||
label: Label
|
||||
plate: Plate
|
||||
volume: Volume
|
||||
name: Name
|
||||
|
||||
supplier:
|
||||
list:
|
||||
|
|
|
@ -457,6 +457,11 @@ entry:
|
|||
landing: Llegada
|
||||
isExcludedFromAvailable: Es inventario
|
||||
ticket:
|
||||
params:
|
||||
ticketFk: ID de ticket
|
||||
weekDay: Salida
|
||||
agencyModeFk: Agencia
|
||||
id: Comercial
|
||||
card:
|
||||
customerId: ID cliente
|
||||
customerCard: Ficha del cliente
|
||||
|
@ -700,6 +705,11 @@ wagon:
|
|||
minHeightBetweenTrays: 'La distancia mínima entre bandejas es '
|
||||
maxWagonHeight: 'La altura máxima del vagón es '
|
||||
uncompleteTrays: Hay bandejas sin completar
|
||||
params:
|
||||
label: Etiqueta
|
||||
plate: Matrícula
|
||||
volume: Volumen
|
||||
name: Nombre
|
||||
supplier:
|
||||
list:
|
||||
payMethod: Método de pago
|
||||
|
|
|
@ -1,4 +1,18 @@
|
|||
account:
|
||||
params:
|
||||
id: Id
|
||||
name: Name
|
||||
roleFk: Role
|
||||
nickname: Nickname
|
||||
password: Password
|
||||
active: Active
|
||||
search: Id
|
||||
description: Description
|
||||
alias: Alias
|
||||
model: Model
|
||||
principalId: Role
|
||||
property: Property
|
||||
accessType: Access
|
||||
card:
|
||||
nickname: User
|
||||
role: Role
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
accessType: Acceso
|
||||
property: Propiedad
|
||||
account:
|
||||
params:
|
||||
id: Id
|
||||
name: Nombre
|
||||
roleFk: Rol
|
||||
nickname: Nickname
|
||||
password: Contraseña
|
||||
active: Activo
|
||||
search: Id
|
||||
description: Descripción
|
||||
alias: Alias
|
||||
model: Modelo
|
||||
principalId: Rol
|
||||
property: Propiedad
|
||||
accessType: Acceso
|
||||
card:
|
||||
nickname: Usuario
|
||||
role: Rol
|
||||
|
|
|
@ -93,16 +93,7 @@ defineExpose({ states });
|
|||
outlined
|
||||
rounded
|
||||
dense
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel> #{{ scope.opt?.id }} </QItemLabel>
|
||||
<QItemLabel caption>{{ scope.opt?.name }}</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
/>
|
||||
<VnSelect
|
||||
:label="t('claim.responsible')"
|
||||
v-model="params.claimResponsibleFk"
|
||||
|
|
|
@ -63,9 +63,10 @@ const columns = computed(() => [
|
|||
<template>
|
||||
<QPage class="column items-center q-pa-md">
|
||||
<VnTable
|
||||
data-key="Mandates"
|
||||
url="Mandates"
|
||||
:filter="filter"
|
||||
auto-load
|
||||
url="Mandates"
|
||||
:columns="columns"
|
||||
class="full-width q-mt-md"
|
||||
:right-search="false"
|
||||
|
|
|
@ -94,3 +94,12 @@ customer:
|
|||
hasToInvoiceByAddress: Invoice by address
|
||||
isToBeMailed: Mailing
|
||||
hasSepaVnl: VNL B2B received
|
||||
params:
|
||||
isWorker: Is Worker
|
||||
payMethod: Payment Method
|
||||
workerFk: Author
|
||||
observation: Last Observation
|
||||
created: Last Update Date
|
||||
creditInsurance: Credit Insurance
|
||||
defaulterSinced: Defaulted Since
|
||||
hasRecovery: Has Recovery
|
|
@ -96,3 +96,12 @@ customer:
|
|||
hasToInvoiceByAddress: Factura por consigna
|
||||
isToBeMailed: Env. emails
|
||||
hasSepaVnl: Recibido B2B VNL
|
||||
params:
|
||||
isWorker: Es trabajador
|
||||
payMethod: F. Pago
|
||||
workerFk: Autor
|
||||
observation: Última observación
|
||||
created: Fecha Ú. O.
|
||||
creditInsurance: Crédito A.
|
||||
defaulterSinced: Desde
|
||||
hasRecovery: Tiene recobro
|
|
@ -1,13 +1,13 @@
|
|||
<script setup>
|
||||
import VnCard from 'components/common/VnCard.vue';
|
||||
import VnCardBeta from 'components/common/VnCardBeta.vue';
|
||||
import DepartmentDescriptor from 'pages/Department/Card/DepartmentDescriptor.vue';
|
||||
</script>
|
||||
<template>
|
||||
<VnCard
|
||||
<VnCardBeta
|
||||
class="q-pa-md column items-center"
|
||||
v-bind="{ ...$attrs }"
|
||||
data-key="Department"
|
||||
base-url="Departments"
|
||||
:descriptor="DepartmentDescriptor"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
|
@ -40,7 +40,7 @@ onMounted(async () => {
|
|||
<template #body="{ entity: department }">
|
||||
<QCard class="column">
|
||||
<VnTitle
|
||||
:url="`#/department/department/${entityId}/basic-data`"
|
||||
:url="`#/worker/department/${entityId}/basic-data`"
|
||||
:text="t('Basic data')"
|
||||
/>
|
||||
<div class="full-width row wrap justify-between content-between">
|
||||
|
|
|
@ -12,6 +12,8 @@ import { getUrl } from 'src/composables/getUrl';
|
|||
import axios from 'axios';
|
||||
import FetchedTags from 'src/components/ui/FetchedTags.vue';
|
||||
import VnToSummary from 'src/components/ui/VnToSummary.vue';
|
||||
import VnRow from 'src/components/ui/VnRow.vue';
|
||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
@ -147,9 +149,8 @@ async function setEntryData(data) {
|
|||
}
|
||||
|
||||
const fetchEntryBuys = async () => {
|
||||
const { data } = await axios.get(`Entries/${entry.value.id}/getBuys`);
|
||||
if (data) entryBuys.value = data;
|
||||
|
||||
const { data } = await axios.get(`Entries/${entry.value.id}/getBuys`);
|
||||
if (data) entryBuys.value = data;
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -173,13 +174,10 @@ const fetchEntryBuys = async () => {
|
|||
</template>
|
||||
<template #body>
|
||||
<QCard class="vn-one">
|
||||
<router-link
|
||||
:to="{ name: 'EntryBasicData', params: { id: entityId } }"
|
||||
class="header header-link"
|
||||
>
|
||||
{{ t('globals.summary.basicData') }}
|
||||
<QIcon name="open_in_new" />
|
||||
</router-link>
|
||||
<VnTitle
|
||||
:url="`#/entry/${entityId}/basic-data`"
|
||||
:text="t('globals.summary.basicData')"
|
||||
/>
|
||||
<VnLv :label="t('entry.summary.commission')" :value="entry.commission" />
|
||||
<VnLv
|
||||
:label="t('entry.summary.currency')"
|
||||
|
@ -193,13 +191,10 @@ const fetchEntryBuys = async () => {
|
|||
/>
|
||||
</QCard>
|
||||
<QCard class="vn-one">
|
||||
<router-link
|
||||
:to="{ name: 'EntryBasicData', params: { id: entityId } }"
|
||||
class="header header-link"
|
||||
>
|
||||
{{ t('globals.summary.basicData') }}
|
||||
<QIcon name="open_in_new" />
|
||||
</router-link>
|
||||
<VnTitle
|
||||
:url="`#/entry/${entityId}/basic-data`"
|
||||
:text="t('globals.summary.basicData')"
|
||||
/>
|
||||
<VnLv :label="t('entry.summary.travelReference')">
|
||||
<template #value>
|
||||
<span class="link">
|
||||
|
@ -217,56 +212,37 @@ const fetchEntryBuys = async () => {
|
|||
:label="t('globals.warehouseOut')"
|
||||
:value="entry.travel.warehouseOut?.name"
|
||||
/>
|
||||
<QCheckbox
|
||||
<VnLv
|
||||
:label="t('entry.summary.travelDelivered')"
|
||||
v-model="entry.travel.isDelivered"
|
||||
:disable="true"
|
||||
:value="entry.travel.isDelivered"
|
||||
/>
|
||||
<VnLv :label="t('globals.landed')" :value="toDate(entry.travel.landed)" />
|
||||
<VnLv
|
||||
:label="t('globals.warehouseIn')"
|
||||
:value="entry.travel.warehouseIn?.name"
|
||||
/>
|
||||
<QCheckbox
|
||||
<VnLv
|
||||
:label="t('entry.summary.travelReceived')"
|
||||
v-model="entry.travel.isReceived"
|
||||
:disable="true"
|
||||
:value="entry.travel.isReceived"
|
||||
/>
|
||||
</QCard>
|
||||
<QCard class="vn-one">
|
||||
<router-link
|
||||
:to="{ name: 'TravelSummary', params: { id: entry.travel.id } }"
|
||||
class="header header-link"
|
||||
>
|
||||
{{ t('Travel data') }}
|
||||
<QIcon name="open_in_new" />
|
||||
</router-link>
|
||||
<QCheckbox
|
||||
:label="t('entry.summary.ordered')"
|
||||
v-model="entry.isOrdered"
|
||||
:disable="true"
|
||||
/>
|
||||
<QCheckbox
|
||||
:label="t('globals.confirmed')"
|
||||
v-model="entry.isConfirmed"
|
||||
:disable="true"
|
||||
/>
|
||||
<QCheckbox
|
||||
:label="t('entry.summary.booked')"
|
||||
v-model="entry.isBooked"
|
||||
:disable="true"
|
||||
/>
|
||||
<QCheckbox
|
||||
:label="t('entry.summary.excludedFromAvailable')"
|
||||
v-model="entry.isExcludedFromAvailable"
|
||||
:disable="true"
|
||||
/>
|
||||
<VnTitle :url="`#/travel/${entityId}/summary`" :text="t('Travel data')" />
|
||||
<VnRow class="block">
|
||||
<VnLv :label="t('entry.summary.ordered')" :value="entry.isOrdered" />
|
||||
<VnLv :label="t('globals.confirmed')" :value="entry.isConfirmed" />
|
||||
<VnLv :label="t('entry.summary.booked')" :value="entry.isBooked" />
|
||||
<VnLv
|
||||
:label="t('entry.summary.excludedFromAvailable')"
|
||||
:value="entry.isExcludedFromAvailable"
|
||||
/>
|
||||
</VnRow>
|
||||
</QCard>
|
||||
<QCard class="vn-two" style="min-width: 100%">
|
||||
<a class="header header-link">
|
||||
{{ t('entry.summary.buys') }}
|
||||
<QIcon name="open_in_new" />
|
||||
</a>
|
||||
<QCard class="vn-max">
|
||||
<VnTitle
|
||||
:url="`#/entry/${entityId}/buys`"
|
||||
:text="t('entry.summary.buys')"
|
||||
/>
|
||||
<QTable
|
||||
:rows="entryBuys"
|
||||
:columns="entriesTableColumns"
|
||||
|
|
|
@ -123,6 +123,7 @@ const companiesOptions = ref([]);
|
|||
option-value="id"
|
||||
option-label="name"
|
||||
:fields="['id', 'name', 'nickname']"
|
||||
:filter-options="['id', 'name', 'nickname']"
|
||||
sort-by="nickname"
|
||||
hide-selected
|
||||
dense
|
||||
|
@ -132,9 +133,12 @@ const companiesOptions = ref([]);
|
|||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{
|
||||
scope.opt?.name + ': ' + scope.opt?.nickname
|
||||
}}</QItemLabel>
|
||||
<QItemLabel>
|
||||
{{ scope.opt?.name}}
|
||||
</QItemLabel>
|
||||
<QItemLabel caption>
|
||||
{{ `#${scope.opt?.id } , ${ scope.opt?.nickname}` }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
|
|
|
@ -69,12 +69,14 @@ const tagValues = ref([]);
|
|||
use-input
|
||||
@update:model-value="searchFn()"
|
||||
>
|
||||
<template #option="{ itemProps, opt }">
|
||||
<QItem v-bind="itemProps">
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ opt.name }}</QItemLabel>
|
||||
<QItemLabel>
|
||||
{{ scope.opt?.name}}
|
||||
</QItemLabel>
|
||||
<QItemLabel caption>
|
||||
{{ opt.nickname }}
|
||||
{{ `#${scope.opt?.id } , ${ scope.opt?.nickname}` }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<script setup>
|
||||
import { onMounted, ref, computed } from 'vue';
|
||||
import { ref, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import EntryFilter from './EntryFilter.vue';
|
||||
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import VnTable from 'components/VnTable/VnTable.vue';
|
||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
import { toDate } from 'src/filters';
|
||||
|
@ -12,7 +11,6 @@ import EntrySummary from './Card/EntrySummary.vue';
|
|||
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
|
||||
|
||||
const stateStore = useStateStore();
|
||||
const { t } = useI18n();
|
||||
const tableRef = ref();
|
||||
|
||||
|
|
|
@ -19,3 +19,11 @@ myEntries:
|
|||
daysAgo: Days ago
|
||||
wasteRecalc:
|
||||
recalcOk: The wastes were successfully recalculated
|
||||
entry:
|
||||
params:
|
||||
toShipped: To
|
||||
fromShipped: From
|
||||
warehouseiNFk: Warehouse
|
||||
daysOnward: Days onward
|
||||
daysAgo: Days ago
|
||||
|
|
@ -22,3 +22,11 @@ myEntries:
|
|||
daysAgo: Días atras
|
||||
wasteRecalc:
|
||||
recalcOk: Se han recalculado las mermas correctamente
|
||||
entry:
|
||||
params:
|
||||
toShipped: Hasta
|
||||
fromShipped: Desde
|
||||
warehouseInFk: Alm. entrada
|
||||
daysOnward: Días adelante
|
||||
daysAgo: Días atras
|
||||
|
|
@ -68,13 +68,26 @@ function handleDaysAgo(params, daysAgo) {
|
|||
<VnSelect
|
||||
v-model="params.supplierFk"
|
||||
url="Suppliers"
|
||||
:fields="['id', 'nickname']"
|
||||
:fields="['id', 'nickname', 'name']"
|
||||
:label="getLocale('supplierFk')"
|
||||
option-label="nickname"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
/>
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>
|
||||
{{ scope.opt?.name}}
|
||||
</QItemLabel>
|
||||
<QItemLabel caption>
|
||||
{{ `#${scope.opt?.id } , ${ scope.opt?.nickname}` }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
|
|
|
@ -165,18 +165,18 @@ const cols = computed(() => [
|
|||
<VnSelect
|
||||
v-model="data.supplierFk"
|
||||
url="Suppliers"
|
||||
:fields="['id', 'nickname']"
|
||||
:fields="['id', 'nickname', 'name']"
|
||||
:label="t('globals.supplier')"
|
||||
option-value="id"
|
||||
option-label="nickname"
|
||||
:filter-options="['id', 'name']"
|
||||
:filter-options="['id', 'name', 'nickname']"
|
||||
:required="true"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.nickname }}</QItemLabel>
|
||||
<QItemLabel caption> #{{ scope.opt?.id }} </QItemLabel>
|
||||
<QItemLabel caption> #{{ scope.opt?.id }}, {{ scope.opt?.name }} </QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
|
|
|
@ -126,6 +126,13 @@ const columns = computed(() => [
|
|||
columnField: { component: null },
|
||||
format: (row) => toDate(row.dued),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
name: 'customsAgentFk',
|
||||
label: t('invoiceOutList.tableVisibleColumns.customsAgent'),
|
||||
cardVisible: true,
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(row.customsAgentName),
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
name: 'tableActions',
|
||||
|
|
|
@ -13,6 +13,7 @@ invoiceOutList:
|
|||
invoiceOutSerial: Serial
|
||||
ticket: Ticket
|
||||
taxArea: Tax area
|
||||
customsAgent: Custom Agent
|
||||
DownloadPdf: Download PDF
|
||||
InvoiceOutSummary: Summary
|
||||
negativeBases:
|
||||
|
@ -24,3 +25,15 @@ negativeBases:
|
|||
hasToInvoice: Has to invoice
|
||||
verifiedData: Verified data
|
||||
commercial: Commercial
|
||||
invoiceout:
|
||||
params:
|
||||
company: Company
|
||||
country: Country
|
||||
clientId: Client ID
|
||||
clientSocialName: Client
|
||||
taxableBase: Base
|
||||
ticketFk: Ticket
|
||||
isActive: Active
|
||||
hasToInvoice: Has to invoice
|
||||
hasVerifiedData: Verified data
|
||||
workerName: Worker
|
|
@ -15,6 +15,7 @@ invoiceOutList:
|
|||
invoiceOutSerial: Serial
|
||||
ticket: Ticket
|
||||
taxArea: Area
|
||||
customsAgent: Agente de aduanas
|
||||
DownloadPdf: Descargar PDF
|
||||
InvoiceOutSummary: Resumen
|
||||
negativeBases:
|
||||
|
@ -27,3 +28,15 @@ negativeBases:
|
|||
hasToInvoice: Debe facturar
|
||||
verifiedData: Datos verificados
|
||||
commercial: Comercial
|
||||
invoiceout:
|
||||
params:
|
||||
company: Empresa
|
||||
country: País
|
||||
clientId: ID del cliente
|
||||
clientSocialName: Cliente
|
||||
taxableBase: Base
|
||||
ticketFk: Ticket
|
||||
isActive: Activo
|
||||
hasToInvoice: Debe facturar
|
||||
hasVerifiedData: Datos verificados
|
||||
workerName: Comercial
|
|
@ -52,6 +52,7 @@ const entityId = computed(() => {
|
|||
:fields="['id', 'name']"
|
||||
sort-by="name ASC"
|
||||
hide-selected
|
||||
data-cy="AddGenusSelectDialog"
|
||||
>
|
||||
<template #form>
|
||||
<CreateGenusForm
|
||||
|
@ -68,6 +69,7 @@ const entityId = computed(() => {
|
|||
:fields="['id', 'name']"
|
||||
sort-by="name ASC"
|
||||
hide-selected
|
||||
data-cy="AddSpeciesSelectDialog"
|
||||
>
|
||||
<template #form>
|
||||
<CreateSpecieForm
|
||||
|
|
|
@ -233,7 +233,7 @@ async function updateWarehouse(warehouseFk) {
|
|||
</div>
|
||||
</template>
|
||||
</VnSubToolbar>
|
||||
<QPage class="column items-center q-pa-md">
|
||||
<QPage class="column items-center">
|
||||
<QTable
|
||||
:rows="itemBalances"
|
||||
:columns="columns"
|
||||
|
|
|
@ -10,21 +10,12 @@ import { dashIfEmpty } from 'src/filters';
|
|||
import { toCurrency } from 'filters/index';
|
||||
import { useArrayData } from 'composables/useArrayData';
|
||||
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 route = useRoute();
|
||||
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) => {
|
||||
switch (param) {
|
||||
|
@ -49,10 +40,6 @@ const where = {
|
|||
itemFk: route.params.id,
|
||||
};
|
||||
|
||||
if (hideInventory.value) {
|
||||
where.supplierFk = { neq: inventorySupplierFk };
|
||||
}
|
||||
|
||||
const arrayData = useArrayData('ItemLastEntries', {
|
||||
url: 'Items/lastEntriesFilter',
|
||||
order: ['landed DESC', 'buyFk DESC'],
|
||||
|
@ -110,7 +97,7 @@ const columns = computed(() => [
|
|||
format: (val) => dashIfEmpty(val),
|
||||
},
|
||||
{
|
||||
label: t('shelvings.packing'),
|
||||
label: 'Packing',
|
||||
name: 'packing',
|
||||
field: 'packing',
|
||||
align: 'center',
|
||||
|
@ -182,15 +169,11 @@ const updateFilter = async () => {
|
|||
const userFilter = arrayData.store.userFilter.where;
|
||||
|
||||
userFilter.landed = filter;
|
||||
if (hideInventory.value) userFilter.supplierFk = { neq: inventorySupplierFk };
|
||||
else delete userFilter.supplierFk;
|
||||
|
||||
await fetchItemLastEntries();
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getInventorySupplier();
|
||||
|
||||
const _from = Date.vnNew();
|
||||
_from.setDate(_from.getDate() - 75);
|
||||
from.value = getDate(_from, 'from');
|
||||
|
@ -200,12 +183,16 @@ onMounted(async () => {
|
|||
|
||||
updateFilter();
|
||||
|
||||
watch([from, to, hideInventory], ([nFrom, nTo], [oFrom, oTo]) => {
|
||||
watch([from, to], ([nFrom, nTo], [oFrom, oTo]) => {
|
||||
if (nFrom && nFrom != oFrom) nFrom = getDate(new Date(nFrom), 'from');
|
||||
if (nTo && nTo != oTo) nTo = getDate(new Date(nTo), 'to');
|
||||
updateFilter();
|
||||
});
|
||||
});
|
||||
|
||||
function getBadgeClass(groupingMode, expectedGrouping) {
|
||||
return groupingMode === expectedGrouping ? 'accent-badge' : 'simple-badge';
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<VnSubToolbar>
|
||||
|
@ -224,13 +211,6 @@ onMounted(async () => {
|
|||
class="q-mr-lg"
|
||||
data-cy="to"
|
||||
/>
|
||||
<QCheckbox
|
||||
:label="t('Hide inventory supplier')"
|
||||
v-model="hideInventory"
|
||||
dense
|
||||
class="q-mr-lg"
|
||||
data-cy="hideInventory"
|
||||
/>
|
||||
</template>
|
||||
</VnSubToolbar>
|
||||
<QPage class="column items-center q-pa-xd">
|
||||
|
@ -249,6 +229,11 @@ onMounted(async () => {
|
|||
/>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-warehouse="{ row }">
|
||||
<QTd>
|
||||
<span>{{ row.warehouse }}</span>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-date="{ row }">
|
||||
<QTd class="text-center">
|
||||
<VnDateBadge :date="row.landed" />
|
||||
|
@ -262,32 +247,37 @@ onMounted(async () => {
|
|||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-pvp="{ value }">
|
||||
<QTd @click.stop class="text-center">
|
||||
<span> {{ value }}</span>
|
||||
<QTooltip> {{ t('lastEntries.grouping') }}/Packing </QTooltip></QTd
|
||||
>
|
||||
</template>
|
||||
<template #body-cell-printedStickers="{ row }">
|
||||
<QTd @click.stop class="text-center">
|
||||
<span style="color: var(--vn-label-color)">
|
||||
{{ row.printedStickers }}</span
|
||||
>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-packing="{ row }">
|
||||
<QTd @click.stop>
|
||||
<QBadge
|
||||
class="center-content"
|
||||
:class="getBadgeClass(row.groupingMode, 'packing')"
|
||||
rounded
|
||||
:color="row.groupingMode == 'packing' ? 'grey-13' : 'black'"
|
||||
>
|
||||
{{ dashIfEmpty(row.packing) }}
|
||||
<QTooltip>{{ t('lastEntries.packing') }}</QTooltip>
|
||||
<QTooltip>Packing</QTooltip>
|
||||
</QBadge>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-pvp="{ value }">
|
||||
<QTd @click.stop class="text-center">
|
||||
<span> {{ value }}</span>
|
||||
<QTooltip>
|
||||
{{ t('lastEntries.grouping') }}/{{ t('lastEntries.packing') }}
|
||||
</QTooltip></QTd
|
||||
>
|
||||
</template>
|
||||
<template #body-cell-grouping="{ row }">
|
||||
<QTd @click.stop>
|
||||
<QBadge
|
||||
class="center-content"
|
||||
:class="getBadgeClass(row.groupingMode, 'grouping')"
|
||||
rounded
|
||||
:color="row.groupingMode == 'grouping' ? 'grey-13' : 'black'"
|
||||
>
|
||||
{{ dashIfEmpty(row.grouping) }}
|
||||
<QTooltip>{{ t('lastEntries.grouping') }}</QTooltip>
|
||||
|
@ -315,13 +305,16 @@ onMounted(async () => {
|
|||
</template>
|
||||
<template #body-cell-supplier="{ row }">
|
||||
<QTd @click.stop>
|
||||
<div class="full-width flex justify-center">
|
||||
<SupplierDescriptorProxy
|
||||
:id="row.supplierFk"
|
||||
class="q-ma-none"
|
||||
<div class="full-width flex justify-left">
|
||||
<QBadge
|
||||
:class="
|
||||
row.isInventorySupplier ? 'bg-vn-page' : 'transparent'
|
||||
"
|
||||
dense
|
||||
/>
|
||||
<span class="link">{{ row.supplier }}</span>
|
||||
>
|
||||
<SupplierDescriptorProxy :id="row.supplierFk" />
|
||||
<span class="link">{{ row.supplier }}</span>
|
||||
</QBadge>
|
||||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
|
@ -349,4 +342,13 @@ onMounted(async () => {
|
|||
background-color: red;
|
||||
}
|
||||
}
|
||||
.accent-badge {
|
||||
background-color: var(--vn-label-color);
|
||||
color: var(--vn-text-color-contrast);
|
||||
}
|
||||
.simple-badge {
|
||||
background-color: transparent;
|
||||
color: var(--vn-text-color);
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -107,7 +107,7 @@ const submitTags = async (data) => {
|
|||
@on-fetch="onItemTagsFetched"
|
||||
>
|
||||
<template #body="{ rows, validate }">
|
||||
<QCard class="q-px-lg q-pt-md q-pb-sm">
|
||||
<QCard class="q-px-lg q-pt-md q-pb-sm" data-cy="itemTags">
|
||||
<VnRow
|
||||
v-for="(row, index) in rows"
|
||||
:key="index"
|
||||
|
|
|
@ -35,6 +35,7 @@ const editTableCellDialogRef = ref(null);
|
|||
const user = state.getUser();
|
||||
const fixedPrices = ref([]);
|
||||
const warehousesOptions = ref([]);
|
||||
const hasSelectedRows = computed(() => rowsSelected.value.length > 0);
|
||||
const rowsSelected = ref([]);
|
||||
const itemFixedPriceFilterRef = ref();
|
||||
|
||||
|
@ -53,7 +54,6 @@ const columns = computed(() => [
|
|||
name: 'itemFk',
|
||||
...defaultColumnAttrs,
|
||||
isId: true,
|
||||
cardVisible: true,
|
||||
columnField: {
|
||||
component: 'input',
|
||||
type: 'number',
|
||||
|
@ -65,14 +65,12 @@ const columns = computed(() => [
|
|||
name: 'name',
|
||||
...defaultColumnAttrs,
|
||||
create: true,
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
label: t('item.fixedPrice.groupingPrice'),
|
||||
field: 'rate2',
|
||||
name: 'rate2',
|
||||
...defaultColumnAttrs,
|
||||
cardVisible: true,
|
||||
component: 'input',
|
||||
type: 'number',
|
||||
},
|
||||
|
@ -81,7 +79,6 @@ const columns = computed(() => [
|
|||
field: 'rate3',
|
||||
name: 'rate3',
|
||||
...defaultColumnAttrs,
|
||||
cardVisible: true,
|
||||
component: 'input',
|
||||
type: 'number',
|
||||
},
|
||||
|
@ -91,7 +88,6 @@ const columns = computed(() => [
|
|||
field: 'minPrice',
|
||||
name: 'minPrice',
|
||||
...defaultColumnAttrs,
|
||||
cardVisible: true,
|
||||
component: 'input',
|
||||
type: 'number',
|
||||
},
|
||||
|
@ -100,7 +96,6 @@ const columns = computed(() => [
|
|||
field: 'started',
|
||||
name: 'started',
|
||||
format: ({ started }) => toDate(started),
|
||||
cardVisible: true,
|
||||
...defaultColumnAttrs,
|
||||
columnField: {
|
||||
component: 'date',
|
||||
|
@ -116,7 +111,6 @@ const columns = computed(() => [
|
|||
field: 'ended',
|
||||
name: 'ended',
|
||||
...defaultColumnAttrs,
|
||||
cardVisible: true,
|
||||
columnField: {
|
||||
component: 'date',
|
||||
class: 'shrink',
|
||||
|
@ -251,11 +245,14 @@ const upsertPrice = async (props, resetMinPrice = false) => {
|
|||
}
|
||||
if (!changes.updates && !changes.creates) return;
|
||||
const data = await upsertFixedPrice(row);
|
||||
tableRef.value.CrudModelRef.formData[props.rowIndex] = data;
|
||||
Object.assign(tableRef.value.CrudModelRef.formData[props.rowIndex], data);
|
||||
notify(t('globals.dataSaved'), 'positive');
|
||||
tableRef.value.reload();
|
||||
};
|
||||
|
||||
async function upsertFixedPrice(row) {
|
||||
const { data } = await axios.patch('FixedPrices/upsertFixedPrice', row);
|
||||
data.hasMinPrice = data.hasMinPrice ? 1 : 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -372,9 +369,9 @@ function handleOnDataSave({ CrudModelRef }) {
|
|||
</template>
|
||||
</RightMenu>
|
||||
<VnSubToolbar>
|
||||
<template #st-data>
|
||||
<template #st-actions>
|
||||
<QBtn
|
||||
v-if="rowsSelected.length"
|
||||
:disable="!hasSelectedRows"
|
||||
@click="openEditTableCellDialog()"
|
||||
color="primary"
|
||||
icon="edit"
|
||||
|
@ -384,29 +381,23 @@ function handleOnDataSave({ CrudModelRef }) {
|
|||
</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
:disable="!hasSelectedRows"
|
||||
:label="tMobile('globals.remove')"
|
||||
color="primary"
|
||||
icon="delete"
|
||||
flat
|
||||
@click="(row) => confirmRemove(row, true)"
|
||||
:title="t('globals.remove')"
|
||||
v-if="rowsSelected.length"
|
||||
/>
|
||||
</template>
|
||||
</VnSubToolbar>
|
||||
<VnTable
|
||||
@on-fetch="
|
||||
(data) =>
|
||||
data.forEach((item) => {
|
||||
item.hasMinPrice = `${item.hasMinPrice !== 0}`;
|
||||
})
|
||||
"
|
||||
:default-remove="false"
|
||||
:default-reset="false"
|
||||
:default-save="false"
|
||||
data-key="ItemFixedPrices"
|
||||
url="FixedPrices/filter"
|
||||
:order="['itemFk DESC', 'name DESC']"
|
||||
:order="['name DESC', 'itemFk DESC']"
|
||||
save-url="FixedPrices/crud"
|
||||
ref="tableRef"
|
||||
dense
|
||||
|
@ -498,14 +489,15 @@ function handleOnDataSave({ CrudModelRef }) {
|
|||
<QCheckbox
|
||||
:model-value="props.row.hasMinPrice"
|
||||
@update:model-value="updateMinPrice($event, props)"
|
||||
:false-value="'false'"
|
||||
:true-value="'true'"
|
||||
:false-value="0"
|
||||
:true-value="1"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
<VnInput
|
||||
class="col"
|
||||
type="currency"
|
||||
mask="###.##"
|
||||
:disable="props.row.hasMinPrice === 1"
|
||||
:disable="props.row.hasMinPrice === 0"
|
||||
v-model.number="props.row.minPrice"
|
||||
v-on="getRowUpdateInputEvents(props)"
|
||||
>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, onBeforeMount } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
import VnImg from 'src/components/ui/VnImg.vue';
|
||||
|
@ -15,6 +15,9 @@ import ItemTypeDescriptorProxy from './ItemType/Card/ItemTypeDescriptorProxy.vue
|
|||
import { cloneItem } from 'src/pages/Item/composables/cloneItem';
|
||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
import ItemListFilter from './ItemListFilter.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import axios from 'axios';
|
||||
|
||||
const entityId = computed(() => route.params.id);
|
||||
const { openCloneDialog } = cloneItem();
|
||||
|
@ -22,7 +25,9 @@ const { viewSummary } = useSummaryDialog();
|
|||
const { t } = useI18n();
|
||||
const tableRef = ref();
|
||||
const route = useRoute();
|
||||
|
||||
const validPriorities = ref([]);
|
||||
const defaultTag = ref();
|
||||
const defaultPriority = ref();
|
||||
const itemFilter = {
|
||||
include: [
|
||||
{
|
||||
|
@ -90,7 +95,6 @@ const columns = computed(() => [
|
|||
label: t('globals.description'),
|
||||
name: 'description',
|
||||
align: 'left',
|
||||
create: true,
|
||||
columnFilter: {
|
||||
name: 'search',
|
||||
},
|
||||
|
@ -132,13 +136,23 @@ const columns = computed(() => [
|
|||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
create: true,
|
||||
visible: false,
|
||||
},
|
||||
{
|
||||
label: t('item.list.typeName'),
|
||||
name: 'typeName',
|
||||
align: 'left',
|
||||
component: 'select',
|
||||
columnFilter: {
|
||||
name: 'typeFk',
|
||||
attrs: {
|
||||
url: 'ItemTypes',
|
||||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
columnField: {
|
||||
component: null,
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('item.list.category'),
|
||||
|
@ -161,6 +175,11 @@ const columns = computed(() => [
|
|||
name: 'intrastat',
|
||||
align: 'left',
|
||||
component: 'select',
|
||||
attrs: {
|
||||
url: 'Intrastats',
|
||||
optionValue: 'description',
|
||||
optionLabel: 'description',
|
||||
},
|
||||
columnFilter: {
|
||||
name: 'intrastat',
|
||||
attrs: {
|
||||
|
@ -172,7 +191,6 @@ const columns = computed(() => [
|
|||
columnField: {
|
||||
component: null,
|
||||
},
|
||||
create: true,
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
|
@ -198,7 +216,6 @@ const columns = computed(() => [
|
|||
columnField: {
|
||||
component: null,
|
||||
},
|
||||
create: true,
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
|
@ -297,12 +314,21 @@ const columns = computed(() => [
|
|||
],
|
||||
},
|
||||
]);
|
||||
|
||||
onBeforeMount(async () => {
|
||||
const { data } = await axios.get('ItemConfigs');
|
||||
defaultTag.value = data[0].defaultTag;
|
||||
defaultPriority.value = data[0].defaultPriority;
|
||||
data.forEach((priority) => {
|
||||
validPriorities.value = priority.validPriorities;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<VnSearchbar
|
||||
data-key="ItemList"
|
||||
:label="t('item.searchbar.label')"
|
||||
:info="t('You can search by id')"
|
||||
:info="t('item.searchbar.info')"
|
||||
/>
|
||||
<RightMenu>
|
||||
<template #right-panel>
|
||||
|
@ -310,15 +336,18 @@ const columns = computed(() => [
|
|||
</template>
|
||||
</RightMenu>
|
||||
<VnTable
|
||||
v-if="defaultTag"
|
||||
ref="tableRef"
|
||||
data-key="ItemList"
|
||||
url="Items/filter"
|
||||
:create="{
|
||||
urlCreate: 'Items',
|
||||
title: t('Create Item'),
|
||||
onDataSaved: () => tableRef.redirect(),
|
||||
urlCreate: 'Items/new',
|
||||
title: t('item.list.newItem'),
|
||||
onDataSaved: ({ id }) => tableRef.redirect(`${id}/basic-data`),
|
||||
formInitialData: {
|
||||
editorFk: entityId,
|
||||
tag: defaultTag,
|
||||
priority: defaultPriority,
|
||||
},
|
||||
}"
|
||||
:order="['isActive DESC', 'name', 'id']"
|
||||
|
@ -364,6 +393,96 @@ const columns = computed(() => [
|
|||
</div>
|
||||
<FetchedTags :item="row" :columns="3" />
|
||||
</template>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<VnInput
|
||||
v-model="data.provisionalName"
|
||||
:label="t('globals.description')"
|
||||
:is-required="true"
|
||||
/>
|
||||
<VnSelect
|
||||
url="Tags"
|
||||
v-model="data.tag"
|
||||
:label="t('globals.tag')"
|
||||
:fields="['id', 'name']"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
:is-required="true"
|
||||
:sort-by="['name ASC']"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
||||
<QItemLabel caption> #{{ scope.opt?.id }} </QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
<VnSelect
|
||||
:options="validPriorities"
|
||||
v-model="data.priority"
|
||||
:label="t('item.create.priority')"
|
||||
:is-required="true"
|
||||
/>
|
||||
<VnSelect
|
||||
url="ItemTypes"
|
||||
v-model="data.typeFk"
|
||||
:label="t('item.list.typeName')"
|
||||
:fields="['id', 'code', 'name']"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
:is-required="true"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
||||
<QItemLabel caption>
|
||||
{{ scope.opt?.code }} #{{ scope.opt?.id }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
<VnSelect
|
||||
url="Intrastats"
|
||||
v-model="data.intrastatFk"
|
||||
:label="t('globals.intrastat')"
|
||||
:fields="['id', 'description']"
|
||||
option-label="description"
|
||||
option-value="id"
|
||||
:is-required="true"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.description }}</QItemLabel>
|
||||
<QItemLabel caption> #{{ scope.opt?.id }} </QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
<VnSelect
|
||||
url="Origins"
|
||||
v-model="data.originFk"
|
||||
:label="t('globals.origin')"
|
||||
:fields="['id', 'code', 'name']"
|
||||
option-label="code"
|
||||
option-value="id"
|
||||
:is-required="true"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
||||
<QItemLabel caption>
|
||||
{{ scope.opt?.code }} #{{ scope.opt?.id }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
</template>
|
||||
</VnTable>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -199,17 +199,7 @@ onMounted(async () => {
|
|||
dense
|
||||
outlined
|
||||
rounded
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{
|
||||
t(`params.${scope.opt?.name}`)
|
||||
}}</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
|
@ -265,6 +255,7 @@ onMounted(async () => {
|
|||
option-value="id"
|
||||
option-label="name"
|
||||
:fields="['id', 'name', 'nickname']"
|
||||
:filter-options="['id', 'name', 'nickname']"
|
||||
sort-by="name ASC"
|
||||
hide-selected
|
||||
dense
|
||||
|
@ -274,9 +265,12 @@ onMounted(async () => {
|
|||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{
|
||||
scope.opt?.name + ': ' + scope.opt?.nickname
|
||||
}}</QItemLabel>
|
||||
<QItemLabel>
|
||||
{{ scope.opt?.name}}
|
||||
</QItemLabel>
|
||||
<QItemLabel caption>
|
||||
{{ `#${scope.opt?.id } , ${ scope.opt?.nickname}` }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
|
@ -375,6 +369,7 @@ onMounted(async () => {
|
|||
:model-value="fieldFilter.selectedField"
|
||||
:options="moreFields"
|
||||
option-label="label"
|
||||
option-value="label"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
|
|
|
@ -149,7 +149,6 @@ onMounted(async () => {
|
|||
:label="t('params.requesterFk')"
|
||||
v-model="params.requesterFk"
|
||||
@update:model-value="searchFn()"
|
||||
:fields="['id', 'name']"
|
||||
:params="{ departmentCodes: ['VT'] }"
|
||||
hide-selected
|
||||
dense
|
||||
|
|
|
@ -107,6 +107,7 @@ item:
|
|||
scopeDays: Scope days
|
||||
searchbar:
|
||||
label: Search item
|
||||
info: You can search by id
|
||||
descriptor:
|
||||
item: Item
|
||||
buyer: Buyer
|
||||
|
@ -139,6 +140,7 @@ item:
|
|||
stemMultiplier: Multiplier
|
||||
producer: Producer
|
||||
landed: Landed
|
||||
newItem: New item
|
||||
basicData:
|
||||
type: Type
|
||||
reference: Reference
|
||||
|
|
|
@ -109,6 +109,7 @@ item:
|
|||
scopeDays: Días en adelante
|
||||
searchbar:
|
||||
label: Buscar artículo
|
||||
info: Puedes buscar por id
|
||||
descriptor:
|
||||
item: Artículo
|
||||
buyer: Comprador
|
||||
|
@ -141,6 +142,7 @@ item:
|
|||
stemMultiplier: Multiplicador
|
||||
producer: Productor
|
||||
landed: F. entrega
|
||||
newItem: Nuevo artículo
|
||||
basicData:
|
||||
type: Tipo
|
||||
reference: Referencia
|
||||
|
|
|
@ -110,15 +110,13 @@ const columns = computed(() => [
|
|||
name: 'salesPersonFk',
|
||||
field: 'userName',
|
||||
align: 'left',
|
||||
optionFilter: 'firstName',
|
||||
columnFilter: {
|
||||
component: 'select',
|
||||
attrs: {
|
||||
url: 'Workers/activeWithInheritedRole',
|
||||
fields: ['id', 'name'],
|
||||
url: 'Workers/search?departmentCodes=["VT"]',
|
||||
fields: ['id', 'name', 'nickname', 'code'],
|
||||
sortBy: 'nickname ASC',
|
||||
where: { role: 'salesPerson' },
|
||||
useLike: false,
|
||||
optionLabel: 'nickname',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -97,6 +97,7 @@ const sourceList = ref([]);
|
|||
v-model="params.sourceApp"
|
||||
:options="sourceList"
|
||||
option-label="value"
|
||||
option-value="value"
|
||||
dense
|
||||
outlined
|
||||
rounded
|
||||
|
|
|
@ -221,7 +221,7 @@ async function handleConfirm() {
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<FetchedTags :item="props.row.item" />
|
||||
<FetchedTags :item="props.row.item" :columns="3" />
|
||||
</QTd>
|
||||
<QTd key="quantity" :props="props">
|
||||
{{ props.row.quantity }}
|
||||
|
|
|
@ -10,3 +10,4 @@ agency:
|
|||
searchBar:
|
||||
info: Puedes buscar por nombre o id
|
||||
label: Buscar agencia...
|
||||
|
||||
|
|
|
@ -1,4 +1,18 @@
|
|||
route:
|
||||
params:
|
||||
agencyModeName: Agencia Ruta
|
||||
agencyAgreement: Agencia Acuerdo
|
||||
id: Id
|
||||
name: Troncal
|
||||
etd: ETD
|
||||
tractorPlate: Matrícula
|
||||
price: Precio
|
||||
observations: Observaciones
|
||||
cmrFk: Id CMR
|
||||
hasCmrDms: Gestdoc
|
||||
ticketFk: Id ticket
|
||||
routeFK: Id ruta
|
||||
shipped: Fecha preparación
|
||||
Worker: Trabajador
|
||||
Agency: Agencia
|
||||
Vehicle: Vehículo
|
||||
|
|
|
@ -319,6 +319,7 @@ onMounted(async () => {
|
|||
}
|
||||
}
|
||||
"
|
||||
:redirect="false"
|
||||
order="created DESC"
|
||||
>
|
||||
<template #column-freightItemName="{ row }">
|
||||
|
|
|
@ -101,7 +101,7 @@ const getGroupedStates = (data) => {
|
|||
<QSkeleton type="QInput" class="full-width" />
|
||||
</QItemSection>
|
||||
<QItemSection v-if="states">
|
||||
<QSelect
|
||||
<VnSelect
|
||||
:label="t('State')"
|
||||
v-model="params.stateFk"
|
||||
@update:model-value="searchFn()"
|
||||
|
@ -122,7 +122,7 @@ const getGroupedStates = (data) => {
|
|||
<QSkeleton type="QInput" class="full-width" />
|
||||
</QItemSection>
|
||||
<QItemSection v-if="groupedStates">
|
||||
<QSelect
|
||||
<VnSelect
|
||||
:label="t('Grouped state')"
|
||||
v-model="params.groupedStates"
|
||||
@update:model-value="searchFn()"
|
||||
|
@ -217,7 +217,7 @@ const getGroupedStates = (data) => {
|
|||
<QSkeleton type="QInput" class="full-width" />
|
||||
</QItemSection>
|
||||
<QItemSection v-if="provinces">
|
||||
<QSelect
|
||||
<VnSelect
|
||||
:label="t('Province')"
|
||||
v-model="params.provinceFk"
|
||||
@update:model-value="searchFn()"
|
||||
|
@ -238,7 +238,7 @@ const getGroupedStates = (data) => {
|
|||
<QSkeleton type="QInput" class="full-width" />
|
||||
</QItemSection>
|
||||
<QItemSection v-if="agencies">
|
||||
<QSelect
|
||||
<VnSelect
|
||||
:label="t('Agency')"
|
||||
v-model="params.agencyModeFk"
|
||||
@update:model-value="searchFn()"
|
||||
|
@ -259,7 +259,7 @@ const getGroupedStates = (data) => {
|
|||
<QSkeleton type="QInput" class="full-width" />
|
||||
</QItemSection>
|
||||
<QItemSection v-if="warehouses">
|
||||
<QSelect
|
||||
<VnSelect
|
||||
:label="t('Warehouse')"
|
||||
v-model="params.warehouseFk"
|
||||
@update:model-value="searchFn()"
|
||||
|
|
|
@ -221,7 +221,20 @@ warehouses();
|
|||
dense
|
||||
outlined
|
||||
rounded
|
||||
/>
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>
|
||||
{{ scope.opt?.name}}
|
||||
</QItemLabel>
|
||||
<QItemLabel caption>
|
||||
{{ `#${scope.opt?.id } , ${ scope.opt?.nickname}` }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
|
@ -232,6 +245,7 @@ warehouses();
|
|||
:options="continentsOptions"
|
||||
option-value="code"
|
||||
option-label="name"
|
||||
:filter-options="['code', 'name']"
|
||||
hide-selected
|
||||
dense
|
||||
outlined
|
||||
|
|
|
@ -140,10 +140,10 @@ en:
|
|||
Id: Contains
|
||||
ref: Reference
|
||||
agency: Agency
|
||||
warehouseInFk: W. In
|
||||
warehouseInFk: Warehouse In
|
||||
shipped: Shipped
|
||||
shipmentHour: Shipment Hour
|
||||
warehouseOut: W. Out
|
||||
warehouseOut: Warehouse Out
|
||||
landed: Landed
|
||||
landingHour: Landing Hour
|
||||
totalEntries: Σ
|
||||
|
@ -156,7 +156,7 @@ es:
|
|||
warehouseInFk: Alm.Entrada
|
||||
shipped: F.Envío
|
||||
shipmentHour: Hora de envío
|
||||
warehouseOut: Alm.Entrada
|
||||
warehouseOut: Alm.Salida
|
||||
landed: F.Entrega
|
||||
landingHour: Hora de entrega
|
||||
totalEntries: Σ
|
||||
|
|
|
@ -1,21 +1,7 @@
|
|||
<script setup>
|
||||
import VnCard from 'components/common/VnCard.vue';
|
||||
import WorkerDescriptor from './WorkerDescriptor.vue';
|
||||
import WorkerFilter from '../WorkerFilter.vue';
|
||||
import VnCardBeta from 'src/components/common/VnCardBeta.vue';
|
||||
</script>
|
||||
<template>
|
||||
<VnCard
|
||||
data-key="Worker"
|
||||
custom-url="Workers/summary"
|
||||
:descriptor="WorkerDescriptor"
|
||||
:filter-panel="WorkerFilter"
|
||||
search-data-key="WorkerList"
|
||||
:searchbar-props="{
|
||||
url: 'Workers/filter',
|
||||
label: 'Search worker',
|
||||
info: 'You can search by worker id or name',
|
||||
order: 'id DESC',
|
||||
}"
|
||||
:redirect-on-error="true"
|
||||
/>
|
||||
<VnCardBeta data-key="Worker" custom-url="Workers/summary" :descriptor="WorkerDescriptor" />
|
||||
</template>
|
||||
|
|
|
@ -208,13 +208,30 @@ const getWorkedHours = async (from, to) => {
|
|||
};
|
||||
|
||||
const getAbsences = async () => {
|
||||
const params = {
|
||||
workerFk: route.params.id,
|
||||
businessFk: null,
|
||||
year: startOfWeek.value.getFullYear(),
|
||||
const startYear = startOfWeek.value.getFullYear();
|
||||
const endYear = endOfWeek.value.getFullYear();
|
||||
const defaultParams = { workerFk: route.params.id, businessFk: null };
|
||||
|
||||
const startData = (
|
||||
await axios.get('Calendars/absences', {
|
||||
params: { ...defaultParams, year: startYear },
|
||||
})
|
||||
).data;
|
||||
|
||||
let endData;
|
||||
if (startYear !== endYear) {
|
||||
endData = (
|
||||
await axios.get('Calendars/absences', {
|
||||
params: { ...defaultParams, year: endYear },
|
||||
})
|
||||
).data;
|
||||
}
|
||||
|
||||
const data = {
|
||||
holidays: [...(startData?.holidays || []), ...(endData?.holidays || [])],
|
||||
absences: [...(startData?.absences || []), ...(endData?.absences || [])],
|
||||
};
|
||||
|
||||
const { data } = await axios.get('Calendars/absences', { params });
|
||||
if (data) addEvents(data);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,254 +0,0 @@
|
|||
<script setup>
|
||||
import { onBeforeMount, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import axios from 'axios';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnLocation from 'src/components/common/VnLocation.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import FormModel from 'components/FormModel.vue';
|
||||
import CreateBankEntityForm from 'src/components/CreateBankEntityForm.vue';
|
||||
import VnRadio from 'src/components/common/VnRadio.vue';
|
||||
import { useState } from 'src/composables/useState';
|
||||
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const user = useState().getUser();
|
||||
|
||||
const companiesOptions = ref([]);
|
||||
const payMethodsOptions = ref([]);
|
||||
const bankEntitiesOptions = ref([]);
|
||||
const formData = ref({ companyFk: user.value.companyFk, isFreelance: false });
|
||||
const defaultPayMethod = ref();
|
||||
|
||||
onBeforeMount(async () => {
|
||||
defaultPayMethod.value = (
|
||||
await axios.get('WorkerConfigs/findOne', {
|
||||
params: { field: ['payMethodFk'] },
|
||||
})
|
||||
).data.payMethodFk;
|
||||
formData.value.payMethodFk = defaultPayMethod.value;
|
||||
});
|
||||
|
||||
function handleLocation(data, location) {
|
||||
const { town, code, provinceFk, countryFk } = location ?? {};
|
||||
data.postcode = code;
|
||||
data.city = town;
|
||||
data.provinceFk = provinceFk;
|
||||
data.countryFk = countryFk;
|
||||
}
|
||||
|
||||
function generateCodeUser(worker) {
|
||||
if (!worker.firstName || !worker.lastNames) return;
|
||||
|
||||
const totalName = worker.firstName.concat(' ' + worker.lastNames).toLowerCase();
|
||||
const totalNameArray = totalName.split(' ');
|
||||
let newCode = '';
|
||||
|
||||
for (let part of totalNameArray) newCode += part.charAt(0);
|
||||
|
||||
worker.code = newCode.toUpperCase().slice(0, 3);
|
||||
worker.name = totalNameArray[0] + newCode.slice(1);
|
||||
|
||||
if (!worker.companyFk) worker.companyFk = user.companyFk;
|
||||
}
|
||||
|
||||
async function autofillBic(worker) {
|
||||
if (!worker || !worker.iban) return;
|
||||
|
||||
let bankEntityId = parseInt(worker.iban.substr(4, 4));
|
||||
let filter = { where: { id: bankEntityId } };
|
||||
|
||||
const { data } = await axios.get(`BankEntities`, { params: { filter } });
|
||||
const hasData = data && data[0];
|
||||
if (hasData) worker.bankEntityFk = data[0].id;
|
||||
else if (!hasData) worker.bankEntityFk = undefined;
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
url="Companies"
|
||||
@on-fetch="(data) => (companiesOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="Paymethods"
|
||||
@on-fetch="(data) => (payMethodsOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="BankEntities"
|
||||
@on-fetch="(data) => (bankEntitiesOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<QPage>
|
||||
<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
|
||||
url-create="Workers/new"
|
||||
model="worker"
|
||||
:form-initial-data="formData"
|
||||
@on-data-saved="(__, { id }) => $router.push({ path: `/worker/${id}` })"
|
||||
>
|
||||
<template #form="{ data, validate }">
|
||||
<VnRow>
|
||||
<VnInput
|
||||
v-model="data.firstName"
|
||||
:label="t('globals.name')"
|
||||
:rules="validate('Worker.firstName')"
|
||||
@update:model-value="generateCodeUser(data)"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.lastNames"
|
||||
:label="t('worker.create.lastName')"
|
||||
:rules="validate('Worker.lastNames')"
|
||||
@update:model-value="generateCodeUser(data)"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.code"
|
||||
:label="t('worker.create.code')"
|
||||
:rules="validate('Worker.code')"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
v-model="data.name"
|
||||
:label="t('worker.create.webUser')"
|
||||
:rules="validate('Worker.name')"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.email"
|
||||
:label="t('worker.create.personalEmail')"
|
||||
:rules="validate('Worker.email')"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('globals.company')"
|
||||
v-model="data.companyFk"
|
||||
:options="companiesOptions"
|
||||
option-value="id"
|
||||
option-label="code"
|
||||
hide-selected
|
||||
:rules="validate('Worker.company')"
|
||||
/>
|
||||
<VnSelectWorker
|
||||
:label="t('worker.summary.boss')"
|
||||
v-model="data.bossFk"
|
||||
:rules="validate('Worker.boss')"
|
||||
/>
|
||||
</VnRow>
|
||||
<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('globals.phone')"
|
||||
:rules="validate('Worker.phone')"
|
||||
:disable="formData.isFreelance"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnLocation
|
||||
:rules="validate('Worker.postcode')"
|
||||
:roles-allowed-to-create="['deliveryAssistant']"
|
||||
@update:model-value="(location) => handleLocation(data, location)"
|
||||
:disable="formData.isFreelance"
|
||||
>
|
||||
</VnLocation>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
:label="t('globals.street')"
|
||||
v-model="data.street"
|
||||
:rules="validate('Worker.street')"
|
||||
:disable="formData.isFreelance"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('worker.create.payMethods')"
|
||||
v-model="data.payMethodFk"
|
||||
:options="payMethodsOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
map-options
|
||||
hide-selected
|
||||
:rules="validate('Worker.payMethodFk')"
|
||||
:disable="formData.isFreelance"
|
||||
@update:model-value="(val) => !val && delete formData.payMethodFk"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.iban"
|
||||
:label="t('worker.create.iban')"
|
||||
:rules="validate('Worker.iban')"
|
||||
:disable="formData.isFreelance"
|
||||
@update:model-value="autofillBic(data)"
|
||||
>
|
||||
<template #append>
|
||||
<QIcon name="info" class="cursor-info">
|
||||
<QTooltip>{{ t('components.iban_tooltip') }}</QTooltip>
|
||||
</QIcon>
|
||||
</template>
|
||||
</VnInput>
|
||||
<VnSelectDialog
|
||||
:label="t('worker.create.bankEntity')"
|
||||
v-model="data.bankEntityFk"
|
||||
:options="bankEntitiesOptions"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
hide-selected
|
||||
:roles-allowed-to-create="['salesAssistant', 'hr']"
|
||||
:rules="validate('Worker.bankEntity')"
|
||||
:disable="formData.isFreelance"
|
||||
@update:model-value="autofillBic(data)"
|
||||
:filter-options="['bic', 'name']"
|
||||
>
|
||||
<template #form>
|
||||
<CreateBankEntityForm
|
||||
@on-data-saved="(data) => bankEntitiesOptions.push(data)"
|
||||
/>
|
||||
</template>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection v-if="scope.opt">
|
||||
<QItemLabel
|
||||
>{{ scope.opt.bic }}
|
||||
{{ scope.opt.name }}</QItemLabel
|
||||
>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelectDialog>
|
||||
</VnRow>
|
||||
</template>
|
||||
</FormModel>
|
||||
</QPage>
|
||||
</template>
|
|
@ -1,11 +1,16 @@
|
|||
<script setup>
|
||||
import VnSection from 'src/components/common/VnSection.vue';
|
||||
import WorkerDepartmentTree from './WorkerDepartmentTree.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QPage class="column items-center q-pa-md">
|
||||
<WorkerDepartmentTree />
|
||||
</QPage>
|
||||
<VnSection data-key="WorkerDepartment">
|
||||
<template #body>
|
||||
<div class="flex flex-center q-pa-md">
|
||||
<WorkerDepartmentTree />
|
||||
</div>
|
||||
</template>
|
||||
</VnSection>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
|
|
|
@ -111,18 +111,16 @@ function handleEvent(type, event, node) {
|
|||
switch (type) {
|
||||
case 'path':
|
||||
state.set('TreeState', lastId);
|
||||
node.id && router.push({ path: `/department/department/${node.id}/summary` });
|
||||
node.id && router.push({ path: `/worker/department/${node.id}/summary` });
|
||||
break;
|
||||
|
||||
case 'tab':
|
||||
state.set('TreeState', lastId);
|
||||
node.id &&
|
||||
window.open(`#/department/department/${node.id}/summary`, '_blank');
|
||||
node.id && window.open(`#/worker/department/${node.id}/summary`, '_blank');
|
||||
break;
|
||||
|
||||
default:
|
||||
node.id &&
|
||||
router.push({ path: `#/department/department/${node.id}/summary` });
|
||||
node.id && router.push({ path: `#/worker/department/${node.id}/summary` });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import { onBeforeMount, computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
import WorkerSummary from './Card/WorkerSummary.vue';
|
||||
import VnRow from 'src/components/ui/VnRow.vue';
|
||||
|
@ -14,12 +13,11 @@ import VnLocation from 'src/components/common/VnLocation.vue';
|
|||
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
||||
import CreateBankEntityForm from 'src/components/CreateBankEntityForm.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
import WorkerFilter from './WorkerFilter.vue';
|
||||
import { useState } from 'src/composables/useState';
|
||||
import axios from 'axios';
|
||||
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
|
||||
|
||||
import VnSection from 'src/components/common/VnSection.vue';
|
||||
const { t } = useI18n();
|
||||
const tableRef = ref();
|
||||
const { viewSummary } = useSummaryDialog();
|
||||
|
@ -31,6 +29,7 @@ const postcodesOptions = ref([]);
|
|||
const user = useState().getUser();
|
||||
const defaultPayMethod = ref();
|
||||
const bankEntitiesRef = ref();
|
||||
const dataKey = 'WorkerList';
|
||||
const columns = computed(() => [
|
||||
{
|
||||
align: 'left',
|
||||
|
@ -170,11 +169,6 @@ async function autofillBic(worker) {
|
|||
}
|
||||
</script>
|
||||
<template>
|
||||
<VnSearchbar
|
||||
data-key="WorkerList"
|
||||
:label="t('Search worker')"
|
||||
:info="t('You can search by worker id or name')"
|
||||
/>
|
||||
<FetchData
|
||||
url="Companies"
|
||||
@on-fetch="(data) => (companiesOptions = data)"
|
||||
|
@ -191,173 +185,202 @@ async function autofillBic(worker) {
|
|||
@on-fetch="(data) => (bankEntitiesOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<RightMenu>
|
||||
<template #right-panel>
|
||||
|
||||
<VnSection
|
||||
:data-key="dataKey"
|
||||
:columns="columns"
|
||||
prefix="workerSearch"
|
||||
:array-data-props="{
|
||||
url: 'Workers/filter',
|
||||
order: ['id DESC'],
|
||||
}"
|
||||
>
|
||||
<template #rightMenu>
|
||||
<WorkerFilter data-key="WorkerList" />
|
||||
</template>
|
||||
</RightMenu>
|
||||
<VnTable
|
||||
v-if="defaultPayMethod"
|
||||
ref="tableRef"
|
||||
data-key="WorkerList"
|
||||
url="Workers/filter"
|
||||
:create="{
|
||||
urlCreate: 'Workers/new',
|
||||
title: t('Create worker'),
|
||||
onDataSaved: ({ id }) => tableRef.redirect(id),
|
||||
formInitialData: {
|
||||
payMethodFk: defaultPayMethod,
|
||||
companyFk: user.companyFk,
|
||||
isFreelance: false,
|
||||
},
|
||||
}"
|
||||
:columns="columns"
|
||||
default-mode="table"
|
||||
redirect="worker"
|
||||
:right-search="false"
|
||||
:order="['id DESC']"
|
||||
>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<div class="q-pa-lg full-width">
|
||||
<VnRadio
|
||||
v-model="data.isFreelance"
|
||||
:val="false"
|
||||
:label="`${t('Internal')}`"
|
||||
@update:model-value="data.payMethodFk = defaultPayMethod"
|
||||
/>
|
||||
<VnRadio
|
||||
v-model="data.isFreelance"
|
||||
:val="true"
|
||||
:label="`${t('External')}`"
|
||||
@update:model-value="delete data.payMethodFk"
|
||||
/>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
next
|
||||
v-model="data.firstName"
|
||||
:label="t('globals.name')"
|
||||
@update:model-value="generateCodeUser(data)"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.lastNames"
|
||||
:label="t('worker.create.lastName')"
|
||||
@update:model-value="generateCodeUser(data)"
|
||||
/>
|
||||
<VnInput v-model="data.code" :label="t('worker.create.code')" />
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput v-model="data.name" :label="t('worker.create.webUser')" />
|
||||
<VnInput
|
||||
v-model="data.email"
|
||||
type="email"
|
||||
:label="t('worker.create.personalEmail')"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('globals.company')"
|
||||
v-model="data.companyFk"
|
||||
:options="companiesOptions"
|
||||
option-value="id"
|
||||
option-label="code"
|
||||
hide-selected
|
||||
/>
|
||||
<VnSelectWorker
|
||||
:label="t('worker.summary.boss')"
|
||||
v-model="data.bossFk"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput v-model="data.fi" :label="t('worker.create.fi')" />
|
||||
<VnInputDate
|
||||
v-model="data.birth"
|
||||
:label="t('worker.create.birth')"
|
||||
:disable="data.isFreelance"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.phone"
|
||||
:label="t('globals.phone')"
|
||||
:disable="data.isFreelance"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnLocation
|
||||
:roles-allowed-to-create="['deliveryAssistant']"
|
||||
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||
:options="postcodesOptions"
|
||||
@update:model-value="(location) => handleLocation(data, location)"
|
||||
:disable="data.isFreelance"
|
||||
>
|
||||
</VnLocation>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
:label="t('globals.street')"
|
||||
:model-value="uppercaseStreetModel(data).get()"
|
||||
@update:model-value="uppercaseStreetModel(data).set"
|
||||
:disable="data.isFreelance"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('worker.create.payMethods')"
|
||||
v-model="data.payMethodFk"
|
||||
:options="payMethodsOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
map-options
|
||||
hide-selected
|
||||
:disable="data.isFreelance"
|
||||
@update:model-value="(val) => !val && delete data.payMethodFk"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.iban"
|
||||
:label="t('worker.create.iban')"
|
||||
:disable="data.isFreelance"
|
||||
@update:model-value="autofillBic(data)"
|
||||
>
|
||||
<template #append>
|
||||
<QIcon name="info" class="cursor-info">
|
||||
<QTooltip>{{ t('components.iban_tooltip') }}</QTooltip>
|
||||
</QIcon>
|
||||
</template>
|
||||
</VnInput>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelectDialog
|
||||
:label="t('worker.create.bankEntity')"
|
||||
v-model="data.bankEntityFk"
|
||||
:options="bankEntitiesOptions"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
hide-selected
|
||||
:acls="[{ model: 'BankEntity', props: '*', accessType: 'WRITE' }]"
|
||||
:disable="data.isFreelance"
|
||||
@update:model-value="autofillBic(data)"
|
||||
:filter-options="['bic', 'name']"
|
||||
>
|
||||
<template #form>
|
||||
<CreateBankEntityForm
|
||||
@on-data-saved="
|
||||
(_, resp) => handleNewBankEntity(data, resp)
|
||||
<template #body>
|
||||
<VnTable
|
||||
v-if="defaultPayMethod"
|
||||
ref="tableRef"
|
||||
:data-key="dataKey"
|
||||
:create="{
|
||||
urlCreate: 'Workers/new',
|
||||
title: t('Create worker'),
|
||||
onDataSaved: ({ id }) => tableRef.redirect(id),
|
||||
formInitialData: {
|
||||
payMethodFk: defaultPayMethod,
|
||||
companyFk: user.companyFk,
|
||||
isFreelance: false,
|
||||
},
|
||||
}"
|
||||
default-mode="table"
|
||||
:columns="columns"
|
||||
redirect="worker"
|
||||
:right-search="false"
|
||||
>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<div class="q-pa-lg full-width">
|
||||
<VnRadio
|
||||
v-model="data.isFreelance"
|
||||
:val="false"
|
||||
:label="`${t('Internal')}`"
|
||||
@update:model-value="data.payMethodFk = defaultPayMethod"
|
||||
/>
|
||||
<VnRadio
|
||||
v-model="data.isFreelance"
|
||||
:val="true"
|
||||
:label="`${t('External')}`"
|
||||
@update:model-value="delete data.payMethodFk"
|
||||
/>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
next
|
||||
v-model="data.firstName"
|
||||
:label="t('globals.name')"
|
||||
@update:model-value="generateCodeUser(data)"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.lastNames"
|
||||
:label="t('worker.create.lastName')"
|
||||
@update:model-value="generateCodeUser(data)"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.code"
|
||||
:label="t('worker.create.code')"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
v-model="data.name"
|
||||
:label="t('worker.create.webUser')"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.email"
|
||||
type="email"
|
||||
:label="t('worker.create.personalEmail')"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('globals.company')"
|
||||
v-model="data.companyFk"
|
||||
:options="companiesOptions"
|
||||
option-value="id"
|
||||
option-label="code"
|
||||
hide-selected
|
||||
/>
|
||||
<VnSelectWorker
|
||||
:label="t('worker.summary.boss')"
|
||||
v-model="data.bossFk"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput v-model="data.fi" :label="t('worker.create.fi')" />
|
||||
<VnInputDate
|
||||
v-model="data.birth"
|
||||
:label="t('worker.create.birth')"
|
||||
:disable="data.isFreelance"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.phone"
|
||||
:label="t('globals.phone')"
|
||||
:disable="data.isFreelance"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnLocation
|
||||
:roles-allowed-to-create="['deliveryAssistant']"
|
||||
:acls="[
|
||||
{ model: 'Town', props: '*', accessType: 'WRITE' },
|
||||
]"
|
||||
:options="postcodesOptions"
|
||||
@update:model-value="
|
||||
(location) => handleLocation(data, location)
|
||||
"
|
||||
:disable="data.isFreelance"
|
||||
>
|
||||
</VnLocation>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
:label="t('globals.street')"
|
||||
:model-value="uppercaseStreetModel(data).get()"
|
||||
@update:model-value="uppercaseStreetModel(data).set"
|
||||
:disable="data.isFreelance"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('worker.create.payMethods')"
|
||||
v-model="data.payMethodFk"
|
||||
:options="payMethodsOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
map-options
|
||||
hide-selected
|
||||
:disable="data.isFreelance"
|
||||
@update:model-value="
|
||||
(val) => !val && delete data.payMethodFk
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection v-if="scope.opt">
|
||||
<QItemLabel
|
||||
>{{ scope.opt.bic }}
|
||||
{{ scope.opt.name }}</QItemLabel
|
||||
>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelectDialog>
|
||||
</VnRow>
|
||||
</div>
|
||||
<VnInput
|
||||
v-model="data.iban"
|
||||
:label="t('worker.create.iban')"
|
||||
:disable="data.isFreelance"
|
||||
@update:model-value="autofillBic(data)"
|
||||
>
|
||||
<template #append>
|
||||
<QIcon name="info" class="cursor-info">
|
||||
<QTooltip>{{
|
||||
t('components.iban_tooltip')
|
||||
}}</QTooltip>
|
||||
</QIcon>
|
||||
</template>
|
||||
</VnInput>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelectDialog
|
||||
:label="t('worker.create.bankEntity')"
|
||||
v-model="data.bankEntityFk"
|
||||
:options="bankEntitiesOptions"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
hide-selected
|
||||
:acls="[
|
||||
{
|
||||
model: 'BankEntity',
|
||||
props: '*',
|
||||
accessType: 'WRITE',
|
||||
},
|
||||
]"
|
||||
:disable="data.isFreelance"
|
||||
@update:model-value="autofillBic(data)"
|
||||
:filter-options="['bic', 'name']"
|
||||
>
|
||||
<template #form>
|
||||
<CreateBankEntityForm
|
||||
@on-data-saved="
|
||||
(_, resp) => handleNewBankEntity(data, resp)
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection v-if="scope.opt">
|
||||
<QItemLabel
|
||||
>{{ scope.opt.bic }}
|
||||
{{ scope.opt.name }}</QItemLabel
|
||||
>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelectDialog>
|
||||
</VnRow>
|
||||
</div>
|
||||
</template>
|
||||
</VnTable>
|
||||
</template>
|
||||
</VnTable>
|
||||
</VnSection>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
workerSearch:
|
||||
search: Search worker
|
||||
searchInfo: Search worker by id or name
|
||||
passwordRequirements: 'The password must have at least { length } length characters, {nAlpha} alphabetic characters, {nUpper} capital letters, {nDigits} digits and {nPunct} symbols (Ex: $%&.)\n'
|
||||
tableColumns:
|
||||
id: ID
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
Search worker: Buscar trabajador
|
||||
You can search by worker id or name: Puedes buscar por id o nombre del trabajador
|
||||
workerSearch:
|
||||
search: Buscar trabajador
|
||||
searchInfo: Buscar trabajador por id o nombre
|
||||
Locker: Taquilla
|
||||
Internal: Interno
|
||||
External: Externo
|
||||
|
|
|
@ -59,7 +59,7 @@ const arrayData = useArrayData('ZoneEvents');
|
|||
const exclusionGeoCreate = async () => {
|
||||
const params = {
|
||||
zoneFk: parseInt(route.params.id),
|
||||
date: dated.value,
|
||||
date: dated,
|
||||
geoIds: tickedNodes.value,
|
||||
};
|
||||
await axios.post('Zones/exclusionGeo', params);
|
||||
|
|
|
@ -17,6 +17,7 @@ import VnInputTime from 'src/components/common/VnInputTime.vue';
|
|||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
import ZoneFilterPanel from './ZoneFilterPanel.vue';
|
||||
import ZoneSearchbar from './Card/ZoneSearchbar.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
|
@ -25,6 +26,7 @@ const { viewSummary } = useSummaryDialog();
|
|||
const { openConfirmationModal } = useVnConfirm();
|
||||
const tableRef = ref();
|
||||
const warehouseOptions = ref([]);
|
||||
const validAddresses = ref([]);
|
||||
|
||||
const tableFilter = {
|
||||
include: [
|
||||
|
@ -34,6 +36,32 @@ const tableFilter = {
|
|||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
{
|
||||
relation: 'address',
|
||||
scope: {
|
||||
fields: ['id', 'nickname', 'provinceFk', 'postalCode'],
|
||||
include: [
|
||||
{
|
||||
relation: 'province',
|
||||
scope: {
|
||||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
{
|
||||
relation: 'postcode',
|
||||
scope: {
|
||||
fields: ['code', 'townFk'],
|
||||
include: {
|
||||
relation: 'town',
|
||||
scope: {
|
||||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -95,7 +123,14 @@ const columns = computed(() => [
|
|||
label: t('list.close'),
|
||||
cardVisible: true,
|
||||
format: (row) => toTimeFormat(row.hour),
|
||||
hidden: true,
|
||||
columnFilter: false,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
name: 'addressFk',
|
||||
label: t('list.addressFk'),
|
||||
cardVisible: true,
|
||||
columnFilter: false,
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
|
@ -129,9 +164,27 @@ const handleClone = (id) => {
|
|||
() => clone(id)
|
||||
);
|
||||
};
|
||||
|
||||
function showValidAddresses(row) {
|
||||
if (row.addressFk) {
|
||||
const isValid = validAddresses.value.some(
|
||||
(address) => address.addressFk === row.addressFk
|
||||
);
|
||||
if (isValid)
|
||||
return `${row.address?.nickname},
|
||||
${row.address?.postcode?.town?.name} (${row.address?.province?.name})`;
|
||||
else return '-';
|
||||
}
|
||||
return '-';
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="RoadmapAddresses"
|
||||
auto-load
|
||||
@on-fetch="(data) => (validAddresses = data)"
|
||||
/>
|
||||
<ZoneSearchbar />
|
||||
<RightMenu>
|
||||
<template #right-panel>
|
||||
|
@ -153,6 +206,9 @@ const handleClone = (id) => {
|
|||
redirect="zone"
|
||||
:right-search="false"
|
||||
>
|
||||
<template #column-addressFk="{ row }">
|
||||
{{ showValidAddresses(row) }}
|
||||
</template>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<VnSelect
|
||||
url="AgencyModes"
|
||||
|
|
|
@ -32,6 +32,7 @@ list:
|
|||
warehouse: Warehouse
|
||||
createZone: Create zone
|
||||
zoneSummary: Summary
|
||||
addressFk: Address
|
||||
create:
|
||||
name: Name
|
||||
closingHour: Closing hour
|
||||
|
|
|
@ -33,6 +33,7 @@ list:
|
|||
isVolumetric: Volumétrico
|
||||
createZone: Crear zona
|
||||
zoneSummary: Resumen
|
||||
addressFk: Consignatario
|
||||
create:
|
||||
closingHour: Hora de cierre
|
||||
itemMaxSize: Medida máxima
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
import { RouterView } from 'vue-router';
|
||||
|
||||
export default {
|
||||
path: '/department',
|
||||
name: 'Department',
|
||||
meta: {
|
||||
title: 'department',
|
||||
icon: 'vn:greuge',
|
||||
moduleName: 'Department',
|
||||
},
|
||||
component: RouterView,
|
||||
redirect: { name: 'WorkerDepartment' },
|
||||
menus: {
|
||||
main: [],
|
||||
card: ['DepartmentBasicData'],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'DepartmentCard',
|
||||
path: 'department/:id',
|
||||
component: () => import('src/pages/Department/Card/DepartmentCard.vue'),
|
||||
redirect: { name: 'DepartmentSummary' },
|
||||
children: [
|
||||
{
|
||||
name: 'DepartmentSummary',
|
||||
path: 'summary',
|
||||
meta: {
|
||||
title: 'summary',
|
||||
icon: 'launch',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Department/Card/DepartmentSummary.vue'),
|
||||
},
|
||||
{
|
||||
name: 'DepartmentBasicData',
|
||||
path: 'basic-data',
|
||||
meta: {
|
||||
title: 'basicData',
|
||||
icon: 'vn:settings',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Department/Card/DepartmentBasicData.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
|
@ -11,7 +11,6 @@ import Route from './route';
|
|||
import Supplier from './supplier';
|
||||
import Travel from './travel';
|
||||
import Order from './order';
|
||||
import Department from './department';
|
||||
import Entry from './entry';
|
||||
import roadmap from './roadmap';
|
||||
import Parking from './parking';
|
||||
|
@ -35,7 +34,6 @@ export default [
|
|||
Travel,
|
||||
Order,
|
||||
invoiceIn,
|
||||
Department,
|
||||
Entry,
|
||||
roadmap,
|
||||
Parking,
|
||||
|
|
|
@ -1,19 +1,12 @@
|
|||
import { RouterView } from 'vue-router';
|
||||
|
||||
export default {
|
||||
path: '/worker',
|
||||
name: 'Worker',
|
||||
const workerCard = {
|
||||
name: 'WorkerCard',
|
||||
path: ':id',
|
||||
component: () => import('src/pages/Worker/Card/WorkerCard.vue'),
|
||||
redirect: { name: 'WorkerSummary' },
|
||||
meta: {
|
||||
title: 'workers',
|
||||
icon: 'vn:worker',
|
||||
moduleName: 'Worker',
|
||||
keyBinding: 'w',
|
||||
},
|
||||
component: RouterView,
|
||||
redirect: { name: 'WorkerMain' },
|
||||
menus: {
|
||||
main: ['WorkerList', 'WorkerDepartment'],
|
||||
card: [
|
||||
menu: [
|
||||
'WorkerBasicData',
|
||||
'WorkerNotes',
|
||||
'WorkerPda',
|
||||
|
@ -33,207 +26,247 @@ export default {
|
|||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'WorkerMain',
|
||||
component: () => import('src/components/common/VnModule.vue'),
|
||||
redirect: { name: 'WorkerList' },
|
||||
name: 'WorkerSummary',
|
||||
path: 'summary',
|
||||
meta: {
|
||||
title: 'summary',
|
||||
icon: 'launch',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerSummary.vue'),
|
||||
},
|
||||
{
|
||||
path: 'basic-data',
|
||||
name: 'WorkerBasicData',
|
||||
meta: {
|
||||
title: 'basicData',
|
||||
icon: 'vn:settings',
|
||||
acls: [
|
||||
{
|
||||
model: 'Worker',
|
||||
props: 'updateAttributes',
|
||||
accessType: 'WRITE',
|
||||
},
|
||||
],
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerBasicData.vue'),
|
||||
},
|
||||
{
|
||||
path: 'notes',
|
||||
name: 'NotesCard',
|
||||
redirect: { name: 'WorkerNotes' },
|
||||
children: [
|
||||
{
|
||||
path: 'list',
|
||||
name: 'WorkerList',
|
||||
path: '',
|
||||
name: 'WorkerNotes',
|
||||
meta: {
|
||||
title: 'list',
|
||||
icon: 'view_list',
|
||||
title: 'notes',
|
||||
icon: 'vn:notes',
|
||||
},
|
||||
component: () => import('src/pages/Worker/WorkerList.vue'),
|
||||
},
|
||||
{
|
||||
path: 'department',
|
||||
name: 'WorkerDepartment',
|
||||
meta: {
|
||||
title: 'department',
|
||||
icon: 'vn:greuge',
|
||||
},
|
||||
component: () => import('src/pages/Worker/WorkerDepartment.vue'),
|
||||
},
|
||||
{
|
||||
path: 'create',
|
||||
name: 'WorkerCreate',
|
||||
meta: {
|
||||
title: 'workerCreate',
|
||||
icon: 'add',
|
||||
},
|
||||
component: () => import('src/pages/Worker/WorkerCreate.vue'),
|
||||
component: () => import('src/pages/Worker/Card/WorkerNotes.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'WorkerCard',
|
||||
path: ':id',
|
||||
component: () => import('src/pages/Worker/Card/WorkerCard.vue'),
|
||||
redirect: { name: 'WorkerSummary' },
|
||||
name: 'WorkerTimeControl',
|
||||
path: 'time-control',
|
||||
meta: {
|
||||
title: 'timeControl',
|
||||
icon: 'access_time',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerTimeControl.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerCalendar',
|
||||
path: 'calendar',
|
||||
meta: {
|
||||
title: 'calendar',
|
||||
icon: 'calendar_today',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerCalendar.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerPda',
|
||||
path: 'pda',
|
||||
meta: {
|
||||
title: 'pda',
|
||||
icon: 'phone_android',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerPda.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerNotificationsManager',
|
||||
path: 'notifications',
|
||||
meta: {
|
||||
title: 'notifications',
|
||||
icon: 'notifications',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Worker/Card/WorkerNotificationsManager.vue'),
|
||||
},
|
||||
{
|
||||
path: 'pbx',
|
||||
name: 'WorkerPBX',
|
||||
meta: {
|
||||
title: 'pbx',
|
||||
icon: 'vn:pbx',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerPBX.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerDms',
|
||||
path: 'dms',
|
||||
meta: {
|
||||
title: 'dms',
|
||||
icon: 'cloud_upload',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerDms.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerLog',
|
||||
path: 'log',
|
||||
meta: {
|
||||
title: 'log',
|
||||
icon: 'vn:History',
|
||||
acls: [{ model: 'WorkerLog', props: 'find', accessType: 'READ' }],
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerLog.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerLocker',
|
||||
path: 'locker',
|
||||
meta: {
|
||||
title: 'locker',
|
||||
icon: 'lock',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerLocker.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerBalance',
|
||||
path: 'balance',
|
||||
meta: {
|
||||
title: 'balance',
|
||||
icon: 'balance',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerBalance.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerFormation',
|
||||
path: 'formation',
|
||||
meta: {
|
||||
title: 'formation',
|
||||
icon: 'clinical_notes',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerFormation.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerMedical',
|
||||
path: 'medical',
|
||||
meta: {
|
||||
title: 'medical',
|
||||
icon: 'medical_information',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerMedical.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerPit',
|
||||
path: 'pit',
|
||||
meta: {
|
||||
title: 'pit',
|
||||
icon: 'lock',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerPit.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerOperator',
|
||||
path: 'operator',
|
||||
meta: {
|
||||
title: 'operator',
|
||||
icon: 'person',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerOperator.vue'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const departmentCard = {
|
||||
name: 'DepartmentCard',
|
||||
path: ':id',
|
||||
component: () => import('src/pages/Department/Card/DepartmentCard.vue'),
|
||||
redirect: { name: 'DepartmentSummary' },
|
||||
meta: {
|
||||
menu: ['DepartmentBasicData'],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'summary',
|
||||
name: 'DepartmentSummary',
|
||||
meta: {
|
||||
title: 'summary',
|
||||
icon: 'launch',
|
||||
},
|
||||
component: () => import('src/pages/Department/Card/DepartmentSummary.vue'),
|
||||
},
|
||||
{
|
||||
path: 'basic-data',
|
||||
name: 'DepartmentBasicData',
|
||||
meta: {
|
||||
title: 'basicData',
|
||||
icon: 'vn:settings',
|
||||
},
|
||||
component: () => import('src/pages/Department/Card/DepartmentBasicData.vue'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'Worker',
|
||||
path: '/worker',
|
||||
meta: {
|
||||
title: 'workers',
|
||||
icon: 'vn:worker',
|
||||
moduleName: 'Worker',
|
||||
keyBinding: 'w',
|
||||
menu: ['WorkerList', 'WorkerDepartment'],
|
||||
},
|
||||
component: RouterView,
|
||||
redirect: { name: 'WorkerMain' },
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'WorkerMain',
|
||||
component: () => import('src/components/common/VnModule.vue'),
|
||||
redirect: { name: 'WorkerIndexMain' },
|
||||
children: [
|
||||
{
|
||||
name: 'WorkerSummary',
|
||||
path: 'summary',
|
||||
meta: {
|
||||
title: 'summary',
|
||||
icon: 'launch',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerSummary.vue'),
|
||||
},
|
||||
{
|
||||
path: 'basic-data',
|
||||
name: 'WorkerBasicData',
|
||||
meta: {
|
||||
title: 'basicData',
|
||||
icon: 'vn:settings',
|
||||
acls: [
|
||||
{
|
||||
model: 'Worker',
|
||||
props: 'updateAttributes',
|
||||
accessType: 'WRITE',
|
||||
},
|
||||
],
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerBasicData.vue'),
|
||||
},
|
||||
{
|
||||
path: 'notes',
|
||||
name: 'NotesCard',
|
||||
redirect: { name: 'WorkerNotes' },
|
||||
path: '',
|
||||
name: 'WorkerIndexMain',
|
||||
redirect: { name: 'WorkerList' },
|
||||
component: () => import('src/pages/Worker/WorkerList.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'WorkerNotes',
|
||||
name: 'WorkerList',
|
||||
path: 'list',
|
||||
meta: {
|
||||
title: 'notes',
|
||||
icon: 'vn:notes',
|
||||
title: 'list',
|
||||
icon: 'view_list',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Worker/Card/WorkerNotes.vue'),
|
||||
},
|
||||
workerCard,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'WorkerTimeControl',
|
||||
path: 'time-control',
|
||||
meta: {
|
||||
title: 'timeControl',
|
||||
icon: 'access_time',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Worker/Card/WorkerTimeControl.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerCalendar',
|
||||
path: 'calendar',
|
||||
meta: {
|
||||
title: 'calendar',
|
||||
icon: 'calendar_today',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerCalendar.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerPda',
|
||||
path: 'pda',
|
||||
meta: {
|
||||
title: 'pda',
|
||||
icon: 'phone_android',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerPda.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerNotificationsManager',
|
||||
path: 'notifications',
|
||||
meta: {
|
||||
title: 'notifications',
|
||||
icon: 'notifications',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Worker/Card/WorkerNotificationsManager.vue'),
|
||||
},
|
||||
{
|
||||
path: 'pbx',
|
||||
name: 'WorkerPBX',
|
||||
meta: {
|
||||
title: 'pbx',
|
||||
icon: 'vn:pbx',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerPBX.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerDms',
|
||||
path: 'dms',
|
||||
meta: {
|
||||
title: 'dms',
|
||||
icon: 'cloud_upload',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerDms.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerLog',
|
||||
path: 'log',
|
||||
meta: {
|
||||
title: 'log',
|
||||
icon: 'vn:History',
|
||||
acls: [{ model: 'WorkerLog', props: 'find', accessType: 'READ' }],
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerLog.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerLocker',
|
||||
path: 'locker',
|
||||
meta: {
|
||||
title: 'locker',
|
||||
icon: 'lock',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerLocker.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerBalance',
|
||||
path: 'balance',
|
||||
meta: {
|
||||
title: 'balance',
|
||||
icon: 'balance',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerBalance.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerFormation',
|
||||
path: 'formation',
|
||||
meta: {
|
||||
title: 'formation',
|
||||
icon: 'clinical_notes',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerFormation.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerMedical',
|
||||
path: 'medical',
|
||||
meta: {
|
||||
title: 'medical',
|
||||
icon: 'medical_information',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerMedical.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerPit',
|
||||
path: 'pit',
|
||||
meta: {
|
||||
title: 'pit',
|
||||
icon: 'lock',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerPit.vue'),
|
||||
},
|
||||
{
|
||||
name: 'WorkerOperator',
|
||||
path: 'operator',
|
||||
meta: {
|
||||
title: 'operator',
|
||||
icon: 'person',
|
||||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerOperator.vue'),
|
||||
path: 'department',
|
||||
name: 'Department',
|
||||
redirect: { name: 'WorkerDepartment' },
|
||||
component: () => import('src/pages/Worker/WorkerDepartment.vue'),
|
||||
children: [
|
||||
{
|
||||
name: 'WorkerDepartment',
|
||||
path: 'list',
|
||||
meta: { title: 'department', icon: 'vn:greuge' },
|
||||
},
|
||||
departmentCard,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -9,7 +9,6 @@ import invoiceIn from './modules/invoiceIn';
|
|||
import wagon from './modules/wagon';
|
||||
import supplier from './modules/supplier';
|
||||
import travel from './modules/travel';
|
||||
import department from './modules/department';
|
||||
import ItemType from './modules/itemType';
|
||||
import shelving from 'src/router/modules/shelving';
|
||||
import order from 'src/router/modules/order';
|
||||
|
@ -85,7 +84,6 @@ const routes = [
|
|||
route,
|
||||
supplier,
|
||||
travel,
|
||||
department,
|
||||
roadmap,
|
||||
entry,
|
||||
parking,
|
||||
|
|
|
@ -18,6 +18,7 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
|
|||
navigate: null,
|
||||
page: 1,
|
||||
mapKey: 'id',
|
||||
keepData: false,
|
||||
};
|
||||
|
||||
function get(key) {
|
||||
|
|
|
@ -11,21 +11,6 @@ describe('OrderCatalog', () => {
|
|||
cy.dataCy('catalogFilterCustomTag').contains(filterName);
|
||||
};
|
||||
|
||||
const checkFilterTag = (filterName = 'Plant') => {
|
||||
cy.dataCy('vnFilterPanelChip').should('exist');
|
||||
cy.dataCy('vnFilterPanelChip').contains(filterName);
|
||||
};
|
||||
|
||||
const selectCategory = (categoryIndex = 1, categoryName = 'Plant') => {
|
||||
cy.get(
|
||||
`div.q-page-container div:nth-of-type(${categoryIndex}) > [data-cy='catalogFilterCategory']`
|
||||
).should('exist');
|
||||
cy.get(
|
||||
`div.q-page-container div:nth-of-type(${categoryIndex}) > [data-cy='catalogFilterCategory']`
|
||||
).click();
|
||||
checkCustomFilterTag(categoryName);
|
||||
};
|
||||
|
||||
const searchByCustomTagInput = (option) => {
|
||||
cy.dataCy('catalogFilterValueInput').find('input').last().focus();
|
||||
cy.dataCy('catalogFilterValueInput').find('input').last().type(option);
|
||||
|
@ -33,31 +18,19 @@ describe('OrderCatalog', () => {
|
|||
checkCustomFilterTag(option);
|
||||
};
|
||||
|
||||
const selectTypeFilter = (option) => {
|
||||
cy.selectOption(
|
||||
'div.q-page-container div.list > div:nth-of-type(2) div:nth-of-type(3)',
|
||||
option
|
||||
);
|
||||
checkFilterTag(option);
|
||||
};
|
||||
|
||||
it('Shows empty state', () => {
|
||||
cy.dataCy('orderCatalogPage').should('exist');
|
||||
cy.dataCy('orderCatalogPage').contains('No data to display');
|
||||
});
|
||||
|
||||
it('filter by category', () => {
|
||||
selectCategory();
|
||||
it('filter by category and type', () => {
|
||||
cy.get(':nth-child(1) > [data-cy="catalogFilterCategory"]').click();
|
||||
cy.selectOption('[data-cy="catalogFilterType"]', 'Anthurium');
|
||||
cy.dataCy('orderCatalogItem').should('exist');
|
||||
});
|
||||
|
||||
it('filters by type', () => {
|
||||
selectCategory();
|
||||
selectTypeFilter('Anthurium');
|
||||
});
|
||||
|
||||
it('filters by custom value select', () => {
|
||||
selectCategory();
|
||||
cy.get(':nth-child(1) > [data-cy="catalogFilterCategory"]').click();
|
||||
searchByCustomTagInput('Silver');
|
||||
});
|
||||
|
||||
|
@ -67,10 +40,12 @@ describe('OrderCatalog', () => {
|
|||
return false;
|
||||
}
|
||||
});
|
||||
selectCategory();
|
||||
cy.dataCy('catalogFilterValueDialogBtn').should('exist');
|
||||
cy.get(
|
||||
'[data-cy="vn-searchbar"] > .q-field > .q-field__inner > .q-field__control'
|
||||
).type('{enter}');
|
||||
cy.get(':nth-child(1) > [data-cy="catalogFilterCategory"]').click();
|
||||
cy.dataCy('catalogFilterValueDialogBtn').last().click();
|
||||
cy.dataCy('catalogFilterValueDialogTagSelect').should('exist');
|
||||
cy.get('[data-cy="catalogFilterValueDialogTagSelect"]').click();
|
||||
cy.selectOption("[data-cy='catalogFilterValueDialogTagSelect']", 'Tallos');
|
||||
cy.dataCy('catalogFilterValueDialogValueInput').find('input').focus();
|
||||
cy.dataCy('catalogFilterValueDialogValueInput').find('input').type('2');
|
||||
|
@ -79,34 +54,16 @@ describe('OrderCatalog', () => {
|
|||
});
|
||||
|
||||
it('removes a secondary tag', () => {
|
||||
selectCategory();
|
||||
selectTypeFilter('Anthurium');
|
||||
cy.get(':nth-child(1) > [data-cy="catalogFilterCategory"]').click();
|
||||
cy.selectOption('[data-cy="catalogFilterType"]', 'Anthurium');
|
||||
cy.dataCy('vnFilterPanelChip').should('exist');
|
||||
cy.get(
|
||||
"div.q-page-container [data-cy='vnFilterPanelChip'] > i.q-chip__icon--remove"
|
||||
)
|
||||
.contains('cancel')
|
||||
.should('exist');
|
||||
cy.get(
|
||||
"div.q-page-container [data-cy='vnFilterPanelChip'] > i.q-chip__icon--remove"
|
||||
)
|
||||
.contains('cancel')
|
||||
.click();
|
||||
cy.get('[data-cy="catalogFilterCustomTag"] > .q-chip__icon--remove').click();
|
||||
cy.dataCy('vnFilterPanelChip').should('not.exist');
|
||||
});
|
||||
|
||||
it('Removes category tag', () => {
|
||||
selectCategory();
|
||||
cy.get(
|
||||
"div.q-page-container [data-cy='catalogFilterCustomTag'] > i.q-chip__icon--remove"
|
||||
)
|
||||
.contains('cancel')
|
||||
.should('exist');
|
||||
cy.get(
|
||||
"div.q-page-container [data-cy='catalogFilterCustomTag'] > i.q-chip__icon--remove"
|
||||
)
|
||||
.contains('cancel')
|
||||
.click();
|
||||
cy.get(':nth-child(1) > [data-cy="catalogFilterCategory"]').click();
|
||||
cy.get('.q-chip__icon--remove').click();
|
||||
cy.dataCy('catalogFilterCustomTag').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,7 +15,7 @@ describe('Client list', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('Client list create new client', () => {
|
||||
it.skip('Client list create new client', () => {
|
||||
cy.addBtnClick();
|
||||
const randomInt = Math.floor(Math.random() * 90) + 10;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ describe('Handle Items FixedPrice', () => {
|
|||
'.q-header > .q-toolbar > :nth-child(1) > .q-btn__content > .q-icon'
|
||||
).click();
|
||||
});
|
||||
it('filter', function () {
|
||||
it.skip('filter', function () {
|
||||
cy.get('.category-filter > :nth-child(1) > .q-btn__content > .q-icon').click();
|
||||
cy.selectOption('.list > :nth-child(2)', 'Alstroemeria');
|
||||
cy.get('.q-gutter-x-sm > .q-btn > .q-btn__content > .q-icon').click();
|
||||
|
@ -27,7 +27,7 @@ describe('Handle Items FixedPrice', () => {
|
|||
cy.get('.q-notification__message').should('have.text', 'Data saved');
|
||||
/* ==== End Cypress Studio ==== */
|
||||
});
|
||||
it('Create and delete ', function () {
|
||||
it.skip('Create and delete ', function () {
|
||||
cy.get('.q-gutter-x-sm > .q-btn > .q-btn__content > .q-icon').click();
|
||||
cy.addBtnClick();
|
||||
cy.selectOption(`${firstRow} > :nth-child(2)`, '#11');
|
||||
|
@ -43,7 +43,7 @@ describe('Handle Items FixedPrice', () => {
|
|||
cy.get('.q-notification__message').should('have.text', 'Data saved');
|
||||
});
|
||||
|
||||
it('Massive edit', function () {
|
||||
it.skip('Massive edit', function () {
|
||||
cy.get(' .bg-header > :nth-child(1) > .q-checkbox > .q-checkbox__inner ').click();
|
||||
cy.get('#subToolbar > .q-btn--standard').click();
|
||||
cy.selectOption("[data-cy='field-to-edit']", 'Min price');
|
||||
|
@ -52,7 +52,7 @@ describe('Handle Items FixedPrice', () => {
|
|||
cy.get('.q-mt-lg > .q-btn--standard').click();
|
||||
cy.get('.q-notification__message').should('have.text', 'Data saved');
|
||||
});
|
||||
it('Massive remove', function () {
|
||||
it.skip('Massive remove', function () {
|
||||
cy.get(' .bg-header > :nth-child(1) > .q-checkbox > .q-checkbox__inner ').click();
|
||||
cy.get('#subToolbar > .q-btn--flat').click();
|
||||
cy.get(
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/// <reference types="cypress" />
|
||||
describe('Item shelving', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/item/list`);
|
||||
cy.typeSearchbar('1{enter}');
|
||||
});
|
||||
|
||||
it('should throw an error if the barcode exists', () => {
|
||||
cy.get('[href="#/item/1/barcode"]').click();
|
||||
cy.get('.q-card > .q-btn > .q-btn__content > .q-icon').click();
|
||||
cy.dataCy('Code_input').eq(3).type('1111111111');
|
||||
cy.dataCy('crudModelDefaultSaveBtn').click();
|
||||
cy.checkNotification('Codes can not be repeated');
|
||||
});
|
||||
|
||||
it('should create a new barcode', () => {
|
||||
cy.get('[href="#/item/1/barcode"]').click();
|
||||
cy.get('.q-card > .q-btn > .q-btn__content > .q-icon').click();
|
||||
cy.dataCy('Code_input').eq(3).type('1231231231');
|
||||
cy.dataCy('crudModelDefaultSaveBtn').click();
|
||||
cy.checkNotification('Data saved');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,31 @@
|
|||
/// <reference types="cypress" />
|
||||
describe('Item botanical', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/item/1/botanical`);
|
||||
});
|
||||
|
||||
it('should modify the botanical', () => {
|
||||
cy.dataCy('AddGenusSelectDialog').type('Abies');
|
||||
cy.get('.q-menu .q-item').contains('Abies').click();
|
||||
cy.dataCy('AddSpeciesSelectDialog').type('dealbata');
|
||||
cy.get('.q-menu .q-item').contains('dealbata').click();
|
||||
cy.get('.q-btn-group > .q-btn--standard').click();
|
||||
cy.checkNotification('Data saved');
|
||||
});
|
||||
|
||||
it('should create a new Genus', () => {
|
||||
cy.dataCy('Genus_icon').click();
|
||||
cy.dataCy('Latin genus name_input').type('Test');
|
||||
cy.dataCy('FormModelPopup_save').click();
|
||||
cy.checkNotification('Data created');
|
||||
});
|
||||
|
||||
it('should create a new specie', () => {
|
||||
cy.dataCy('Species_icon').click();
|
||||
cy.dataCy('Latin species name_input').type('Test specie');
|
||||
cy.dataCy('FormModelPopup_save').click();
|
||||
cy.checkNotification('Data created');
|
||||
});
|
||||
});
|
|
@ -1,20 +0,0 @@
|
|||
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);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,34 @@
|
|||
/// <reference types="cypress" />
|
||||
|
||||
describe('Item list', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/item/list`);
|
||||
cy.typeSearchbar('{enter}');
|
||||
});
|
||||
|
||||
it('should filter the items and redirect to the summary', () => {
|
||||
cy.dataCy('Category_select').type('Plant');
|
||||
cy.get('.q-menu .q-item').contains('Plant').click();
|
||||
cy.dataCy('Type_select').type('Anthurium');
|
||||
cy.get('.q-menu .q-item').contains('Anthurium').click();
|
||||
cy.get('.q-virtual-scroll__content > :nth-child(4) > :nth-child(4)').click();
|
||||
});
|
||||
|
||||
it('should create an item', () => {
|
||||
const data = {
|
||||
Description: { val: `Test item` },
|
||||
Type: { val: `Crisantemo`, type: 'select' },
|
||||
Intrastat: { val: `Coral y materiales similares`, type: 'select' },
|
||||
Origin: { val: `SPA`, type: 'select' },
|
||||
};
|
||||
cy.dataCy('vnTableCreateBtn').click();
|
||||
cy.fillInForm(data);
|
||||
cy.dataCy('FormModelPopup_save').click();
|
||||
cy.checkNotification('Data created');
|
||||
cy.get(
|
||||
':nth-child(2) > .q-drawer > .q-drawer__content > .q-scrollarea > .q-scrollarea__container > .q-scrollarea__content'
|
||||
).should('be.visible');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
/// <reference types="cypress" />
|
||||
describe('Item summary', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/item/1/summary`);
|
||||
});
|
||||
|
||||
it('should clone the item', () => {
|
||||
cy.dataCy('descriptor-more-opts').click();
|
||||
cy.get('.q-menu > .q-list > :nth-child(2) > .q-item__section').click();
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.waitForElement('[data-cy="itemTags"]');
|
||||
cy.dataCy('itemTags').should('be.visible');
|
||||
});
|
||||
|
||||
it('should regularize stock', () => {
|
||||
cy.dataCy('descriptor-more-opts').click();
|
||||
cy.get('.q-menu > .q-list > :nth-child(1) > .q-item__section').click();
|
||||
cy.dataCy('regularizeStockInput').type('10');
|
||||
cy.dataCy('Warehouse_select').type('Warehouse One{enter}');
|
||||
cy.checkNotification('Data created');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
/// <reference types="cypress" />
|
||||
describe('Item tag', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/item/1/tags`);
|
||||
});
|
||||
|
||||
it('should throw an error adding an existent tag', () => {
|
||||
cy.get('.q-page').should('be.visible');
|
||||
cy.get('.q-page-sticky > div').click();
|
||||
cy.get('.q-page-sticky > div').click();
|
||||
cy.dataCy('Tag_select').eq(7).type('Tallos');
|
||||
cy.get('.q-menu .q-item').contains('Tallos').click();
|
||||
cy.get(
|
||||
':nth-child(8) > [label="Value"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Value_input"]'
|
||||
).type('1');
|
||||
+cy.dataCy('crudModelDefaultSaveBtn').click();
|
||||
cy.checkNotification("The tag or priority can't be repeated for an item");
|
||||
});
|
||||
|
||||
it('should add a new tag', () => {
|
||||
cy.get('.q-page').should('be.visible');
|
||||
cy.get('.q-page-sticky > div').click();
|
||||
cy.get('.q-page-sticky > div').click();
|
||||
cy.dataCy('Tag_select').eq(7).click();
|
||||
cy.get('.q-menu .q-item').contains('Ancho de la base').click();
|
||||
cy.get(
|
||||
':nth-child(8) > [label="Value"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Value_input"]'
|
||||
).type('50');
|
||||
cy.dataCy('crudModelDefaultSaveBtn').click();
|
||||
cy.checkNotification('Data saved');
|
||||
cy.get(
|
||||
'[data-cy="itemTags"] > :nth-child(7) > .justify-center > .q-icon'
|
||||
).click();
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.checkNotification('Data saved');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
/// <reference types="cypress" />
|
||||
describe('Item tax', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/item/1/tax`);
|
||||
});
|
||||
|
||||
it('should modify the tax for Spain', () => {
|
||||
cy.dataCy('Class_select').eq(1).type('General VAT{enter}');
|
||||
cy.dataCy('crudModelDefaultSaveBtn').click();
|
||||
cy.checkNotification('Data saved');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,40 @@
|
|||
/// <reference types="cypress" />
|
||||
describe('Item type', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/item/item-type`);
|
||||
});
|
||||
|
||||
it('should throw an error if the code already exists', () => {
|
||||
cy.dataCy('vnTableCreateBtn').click();
|
||||
cy.get(
|
||||
'div.fit > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Code_input"]'
|
||||
).type('ALS');
|
||||
cy.get(
|
||||
'div.fit > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Name_input"]'
|
||||
).type('Alstroemeria');
|
||||
cy.dataCy('Worker_select').type('employeeNick');
|
||||
cy.get('.q-menu .q-item').contains('employeeNick').click();
|
||||
cy.dataCy('ItemCategory_select').type('Artificial');
|
||||
cy.get('.q-menu .q-item').contains('Artificial').click();
|
||||
cy.dataCy('FormModelPopup_save').click();
|
||||
cy.checkNotification('An item type with the same code already exists');
|
||||
});
|
||||
|
||||
it('should create a new type', () => {
|
||||
cy.dataCy('vnTableCreateBtn').click();
|
||||
cy.get(
|
||||
'div.fit > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Code_input"]'
|
||||
).type('LIL');
|
||||
cy.get(
|
||||
'div.fit > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Name_input"]'
|
||||
).type('Lilium');
|
||||
cy.dataCy('Worker_select').type('buyerNick');
|
||||
cy.get('.q-menu .q-item').contains('buyerNick').click();
|
||||
cy.dataCy('ItemCategory_select').type('Flower');
|
||||
cy.get('.q-menu .q-item').contains('Flower').click();
|
||||
cy.dataCy('FormModelPopup_save').click();
|
||||
cy.checkNotification('Data created');
|
||||
});
|
||||
});
|
|
@ -16,7 +16,9 @@ describe('Ticket expedtion', () => {
|
|||
|
||||
cy.wait('@show');
|
||||
cy.selectRows([1, 2]);
|
||||
cy.selectOption('[data-cy="change-state"]', 'Perdida');
|
||||
|
||||
cy.dataCy('change-state').click();
|
||||
cy.selectOption('[data-cy="vnBtnSelect_select"]', 'Perdida');
|
||||
cy.wait('@add');
|
||||
|
||||
cy.get(`${tableContent} tr:nth-child(-n+2) ${stateTd}`).each(($el) => {
|
||||
|
|
|
@ -9,9 +9,9 @@ describe('TicketList', () => {
|
|||
});
|
||||
|
||||
const searchResults = (search) => {
|
||||
cy.dataCy('vnSearchBar').find('input').focus();
|
||||
if (search) cy.dataCy('vnSearchBar').find('input').type(search);
|
||||
cy.dataCy('vnSearchBar').find('input').type('{enter}');
|
||||
cy.dataCy('vn-searchbar').find('input').focus();
|
||||
if (search) cy.dataCy('vn-searchbar').find('input').type(search);
|
||||
cy.dataCy('vn-searchbar').find('input').type('{enter}');
|
||||
cy.dataCy('ticketListTable').should('exist');
|
||||
cy.get(firstRow).should('exist');
|
||||
};
|
||||
|
@ -37,7 +37,7 @@ describe('TicketList', () => {
|
|||
cy.dataCy('ticketSummary').should('exist');
|
||||
});
|
||||
|
||||
it('Client list create new client', () => {
|
||||
it.skip('Client list create new client', () => {
|
||||
cy.dataCy('vnTableCreateBtn').should('exist');
|
||||
cy.dataCy('vnTableCreateBtn').click();
|
||||
const data = {
|
||||
|
|
|
@ -6,7 +6,7 @@ describe('TicketRequest', () => {
|
|||
cy.visit('/#/ticket/31/request');
|
||||
});
|
||||
|
||||
it('Creates a new request', () => {
|
||||
it.skip('Creates a new request', () => {
|
||||
cy.dataCy('vnTableCreateBtn').should('exist');
|
||||
cy.dataCy('vnTableCreateBtn').click();
|
||||
const data = {
|
||||
|
|
|
@ -66,7 +66,7 @@ describe('TicketSale', () => {
|
|||
cy.dataCy('ticketSaleMoreActionsDropdown').click();
|
||||
cy.dataCy('createClaimItem').click();
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.url().should('match', /\/claim\/\d+\/basic-data/);
|
||||
cy.url().should('contain', 'claim/');
|
||||
// Delete created claim to avoid cluttering the database
|
||||
cy.dataCy('descriptor-more-opts').click();
|
||||
cy.dataCy('deleteClaim').click();
|
||||
|
@ -106,22 +106,15 @@ describe('TicketSale', () => {
|
|||
cy.checkNotification('The following refund ticket have been created');
|
||||
});
|
||||
|
||||
it('transfers ticket', () => {
|
||||
it('transfer sale to a new ticket', () => {
|
||||
cy.visit('/#/ticket/32/sale');
|
||||
cy.get('.q-item > .q-item__label').should('have.text', ' #32');
|
||||
selectFirstRow();
|
||||
cy.dataCy('ticketSaleTransferBtn').click();
|
||||
cy.dataCy('ticketTransferPopup').should('exist');
|
||||
cy.dataCy('ticketTransferNewTicketBtn').click();
|
||||
// existen 3 elementos "tbody" necesito checkear que el segundo elemento tbody tenga una row sola
|
||||
cy.get('tbody').eq(1).find('tr').should('have.length', 1);
|
||||
selectFirstRow();
|
||||
cy.dataCy('ticketSaleTransferBtn').click();
|
||||
cy.dataCy('ticketTransferPopup').should('exist');
|
||||
cy.dataCy('ticketTransferDestinationTicketInput').find('input').focus();
|
||||
cy.dataCy('ticketTransferDestinationTicketInput').find('input').type('32');
|
||||
cy.dataCy('ticketTransferTransferBtn').click();
|
||||
// checkear que la url contenga /ticket/1000002/sale
|
||||
cy.url().should('match', /\/ticket\/32\/sale/);
|
||||
//check the new ticket has been created succesfully
|
||||
cy.get('.q-item > .q-item__label').should('not.have.text', ' #32');
|
||||
});
|
||||
|
||||
it('should redirect to ticket logs', () => {
|
||||
|
|
|
@ -38,10 +38,7 @@ describe('VnLocation', () => {
|
|||
const province = 'Province five';
|
||||
|
||||
cy.selectOption(countrySelector, country);
|
||||
cy.selectOption(
|
||||
`${createForm.prefix} > :nth-child(4) > .q-select > ${createForm.sufix}`,
|
||||
province
|
||||
);
|
||||
cy.dataCy('locationProvince').type(`${province}{enter}`);
|
||||
cy.get(
|
||||
`${createForm.prefix} > :nth-child(4) > .q-select > ${createForm.sufix} > :nth-child(3) `
|
||||
).click();
|
||||
|
@ -134,13 +131,9 @@ describe('VnLocation', () => {
|
|||
it('Create city with country', () => {
|
||||
const cityName = 'Saskatchew'.concat(Math.random(1 * 100));
|
||||
cy.get(createLocationButton).click();
|
||||
cy.selectOption(
|
||||
`${createForm.prefix} > :nth-child(5) > :nth-child(3) `,
|
||||
'Italia'
|
||||
);
|
||||
cy.dataCy('locationCountry').type('Italia{enter}');
|
||||
cy.dataCy('City_icon').click();
|
||||
cy.selectOption('[data-cy="locationProvince"]:last', 'Province four');
|
||||
cy.countSelectOptions('[data-cy="locationProvince"]:last', 1);
|
||||
|
||||
cy.dataCy('cityName').type(cityName);
|
||||
cy.dataCy('FormModelPopup_save').eq(1).click();
|
||||
|
|
|
@ -10,14 +10,14 @@ describe('VnLog', () => {
|
|||
cy.openRightMenu();
|
||||
});
|
||||
|
||||
it('should filter by insert actions', () => {
|
||||
it.skip('should filter by insert actions', () => {
|
||||
cy.checkOption(':nth-child(7) > .q-checkbox');
|
||||
cy.get('.q-page').click();
|
||||
cy.validateContent(chips[0], 'Document');
|
||||
cy.validateContent(chips[1], 'Beginning');
|
||||
});
|
||||
|
||||
it('should filter by entity', () => {
|
||||
it.skip('should filter by entity', () => {
|
||||
cy.selectOption('.q-drawer--right .q-item > .q-select', 'Claim');
|
||||
cy.get('.q-page').click();
|
||||
cy.validateContent(chips[0], 'Claim');
|
||||
|
|
|
@ -16,6 +16,7 @@ describe('VnSearchBar', () => {
|
|||
});
|
||||
|
||||
it('should stay on the list page if there are several results or none', () => {
|
||||
cy.typeSearchbar('salesA{enter}');
|
||||
cy.typeSearchbar('salesA{enter}');
|
||||
checkTableLength(2);
|
||||
|
||||
|
@ -28,6 +29,7 @@ describe('VnSearchBar', () => {
|
|||
const searchAndCheck = (searchTerm, expectedText) => {
|
||||
cy.clearSearchbar();
|
||||
cy.typeSearchbar(`${searchTerm}{enter}`);
|
||||
cy.typeSearchbar(`${searchTerm}{enter}`);
|
||||
cy.get(idGap).should('have.text', expectedText);
|
||||
};
|
||||
|
||||
|
|
|
@ -2,41 +2,22 @@ describe('WagonCreate', () => {
|
|||
beforeEach(() => {
|
||||
cy.viewport(1280, 720);
|
||||
cy.login('developer');
|
||||
cy.visit('/#/wagon/create');
|
||||
cy.visit('/#/wagon');
|
||||
});
|
||||
|
||||
it('should create and delete a new wagon', () => {
|
||||
cy.waitForElement('.q-card');
|
||||
cy.get('input').eq(0).type('1234');
|
||||
cy.get('input').eq(1).type('1234ABCD');
|
||||
cy.get('input').eq(2).type('100');
|
||||
cy.get('input').eq(3).click();
|
||||
cy.get('.q-select > .q-field__inner > .q-field__control').type(
|
||||
'{downarrow}{enter}'
|
||||
);
|
||||
|
||||
// Save
|
||||
cy.get('button[type="submit"]').click();
|
||||
|
||||
// Check data has been saved successfully
|
||||
cy.waitForElement('.q-card');
|
||||
|
||||
cy.dataCy('vnTableCreateBtn').click();
|
||||
cy.get(
|
||||
'[to="/null/1"] > .q-card > .no-padding > .q-py-none > .cursor-text'
|
||||
).should('have.text', '1234');
|
||||
'.grid-create > [label="Label"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Label_input"]'
|
||||
).type('1234');
|
||||
cy.get(
|
||||
'[to="/null/1"] > .q-card > .no-padding > .q-pr-lg > :nth-child(1) > .vn-label-value > .value > :nth-child(1) > .row > span'
|
||||
).should('have.text', '1234ABCD');
|
||||
'.grid-create > [label="Plate"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Plate_input"]'
|
||||
).type('1234ABCD');
|
||||
cy.get(
|
||||
'[to="/null/1"] > .q-card > .no-padding > .q-pr-lg > :nth-child(2) > .vn-label-value > .value > :nth-child(1) > .row > span'
|
||||
).should('have.text', '100');
|
||||
cy.get(
|
||||
'[to="/null/1"] > .q-card > .no-padding > .q-pr-lg > :nth-child(3) > .vn-label-value > .value > :nth-child(1) > .row > span'
|
||||
).should('have.text', 'Wagon Type #1');
|
||||
|
||||
// Delete wagon type created
|
||||
cy.get(
|
||||
'[to="/null/2"] > .q-card > .column > [title="Remove"] > .q-btn__content > .q-icon'
|
||||
).click();
|
||||
'.grid-create > [label="Volume"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="Volume_input"]'
|
||||
).type('100');
|
||||
cy.dataCy('Type_select').type('{downarrow}{enter}');
|
||||
// // Delete wagon type created
|
||||
cy.get('[to="/null/1"] > .q-card > .column > [title="Remove"]').click();
|
||||
});
|
||||
});
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue