Compare commits

..

No commits in common. "dev" and "8441-warmfix-includeTest" have entirely different histories.

31 changed files with 173 additions and 143 deletions

2
Jenkinsfile vendored
View File

@ -126,7 +126,7 @@ pipeline {
sh "docker-compose ${env.COMPOSE_PARAMS} up -d" sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") { image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") {
sh 'sh test/cypress/cypressParallel.sh 2' sh 'sh test/cypress/cypressParallel.sh 1'
} }
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "salix-front", "name": "salix-front",
"version": "25.16.0", "version": "25.14.0",
"description": "Salix frontend", "description": "Salix frontend",
"productName": "Salix", "productName": "Salix",
"author": "Verdnatura", "author": "Verdnatura",
@ -76,4 +76,4 @@
"vite": "^6.0.11", "vite": "^6.0.11",
"vitest": "^0.31.1" "vitest": "^0.31.1"
} }
} }

View File

@ -60,7 +60,7 @@ async function confirm() {
v-model="address" v-model="address"
is-outlined is-outlined
autofocus autofocus
data-cy="SendEmailNotificationDialogInput" data-cy="SendEmailNotifiactionDialogInput"
/> />
</QCardSection> </QCardSection>
<QCardActions align="right"> <QCardActions align="right">

View File

@ -10,7 +10,6 @@ import { useFilterParams } from 'src/composables/useFilterParams';
import FetchData from '../FetchData.vue'; import FetchData from '../FetchData.vue';
import { useValidator } from 'src/composables/useValidator'; import { useValidator } from 'src/composables/useValidator';
import { useCapitalize } from 'src/composables/useCapitalize'; import { useCapitalize } from 'src/composables/useCapitalize';
import VnAvatar from '../ui/VnAvatar.vue';
const $props = defineProps({ const $props = defineProps({
dataKey: { dataKey: {
@ -100,6 +99,7 @@ function getActions() {
:columns="columns" :columns="columns"
:redirect="false" :redirect="false"
:hiddenTags="['originFk', 'creationDate']" :hiddenTags="['originFk', 'creationDate']"
:exprBuilder
search-url="logs" search-url="logs"
:showTagChips="false" :showTagChips="false"
> >

View File

@ -159,7 +159,6 @@ async function fetch() {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
margin-top: 2px; margin-top: 2px;
align-items: start;
.label { .label {
color: var(--vn-label-color); color: var(--vn-label-color);
width: 9em; width: 9em;
@ -170,15 +169,9 @@ async function fetch() {
flex-grow: 0; flex-grow: 0;
flex-shrink: 0; flex-shrink: 0;
} }
&.ellipsis > .value {
text-overflow: ellipsis;
white-space: pre;
}
.value { .value {
color: var(--vn-text-color); color: var(--vn-text-color);
overflow: hidden; overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
} }
} }
.header { .header {
@ -210,21 +203,27 @@ async function fetch() {
} }
.vn-card-group { .vn-card-group {
display: grid; display: flex;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); flex-direction: column;
gap: 16px;
} }
.vn-card-content { .vn-card-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
> div { > div {
max-height: 70px; max-height: 70px;
} }
} }
@media (min-width: 1010px) {
.vn-card-group {
flex-direction: row;
}
.vn-card-content {
flex: 1;
}
}
</style> </style>
<style lang="scss" scoped> <style lang="scss" scoped>
.summaryHeader .vn-label-value { .summaryHeader .vn-label-value {

View File

@ -252,10 +252,6 @@ const toModule = computed(() => {
content: ':'; content: ':';
} }
} }
&.ellipsis > .value {
text-overflow: ellipsis;
white-space: pre;
}
.value { .value {
color: var(--vn-text-color); color: var(--vn-text-color);
font-size: 14px; font-size: 14px;

View File

@ -1,11 +1,8 @@
<script setup> <script setup>
import { dashIfEmpty } from 'src/filters';
defineProps({ email: { type: [String], default: null } }); defineProps({ email: { type: [String], default: null } });
</script> </script>
<template> <template>
<QBtn <QBtn
class="q-pr-xs"
v-if="email" v-if="email"
flat flat
round round
@ -16,5 +13,4 @@ defineProps({ email: { type: [String], default: null } });
:href="`mailto:${email}`" :href="`mailto:${email}`"
@click.stop @click.stop
/> />
<span>{{ dashIfEmpty(email) }}</span>
</template> </template>

View File

@ -1,7 +1,7 @@
<script setup> <script setup>
import { ref, reactive, useAttrs, onBeforeMount, capitalize } from 'vue'; import { ref, reactive, useAttrs, onBeforeMount, capitalize } from 'vue';
import axios from 'axios'; import axios from 'axios';
import { dashIfEmpty, parsePhone } from 'src/filters'; import { parsePhone } from 'src/filters';
import useOpenURL from 'src/composables/useOpenURL'; import useOpenURL from 'src/composables/useOpenURL';
const props = defineProps({ const props = defineProps({
@ -12,65 +12,50 @@ const props = defineProps({
const phone = ref(props.phoneNumber); const phone = ref(props.phoneNumber);
const config = reactive({ const config = reactive({
sip: { icon: 'phone', href: `sip:${props.phoneNumber}` },
'say-simple': { 'say-simple': {
icon: 'vn:saysimple', icon: 'vn:saysimple',
url: null, url: null,
channel: props.channel, channel: props.channel,
}, },
sip: { icon: 'phone', href: `sip:${props.phoneNumber}` },
}); });
const type = Object.keys(config).find((key) => key in useAttrs()) || 'sip';
const attrs = useAttrs();
const types = Object.keys(config)
.filter((key) => key in attrs)
.sort();
const activeTypes = types.length ? types : ['sip'];
onBeforeMount(async () => { onBeforeMount(async () => {
if (!phone.value) return; if (!phone.value) return;
let { channel } = config[type];
for (const type of activeTypes) { if (type === 'say-simple') {
if (type === 'say-simple') { const { url, defaultChannel } = (await axios.get('SaySimpleConfigs/findOne'))
let { channel } = config[type]; .data;
const { url, defaultChannel } = (await axios.get('SaySimpleConfigs/findOne')) if (!channel) channel = defaultChannel;
.data;
if (!channel) channel = defaultChannel;
phone.value = await parsePhone( phone.value = await parsePhone(props.phoneNumber, props.country?.toLowerCase());
props.phoneNumber, config[
props.country?.toLowerCase(), type
); ].url = `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`;
config[type].url =
`${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`;
}
} }
}); });
function handleClick(type) { function handleClick() {
if (config[type].url) useOpenURL(config[type].url); if (config[type].url) useOpenURL(config[type].url);
else if (config[type].href) window.location.href = config[type].href; else if (config[type].href) window.location.href = config[type].href;
} }
</script> </script>
<template> <template>
<div class="flex items-center gap-2"> <QBtn
<template v-for="type in activeTypes"> v-if="phone"
<QBtn flat
:key="type" round
v-if="phone" :icon="config[type].icon"
flat size="sm"
round color="primary"
:icon="config[type].icon" padding="none"
size="sm" @click.stop="handleClick"
color="primary" >
padding="none" <QTooltip>
@click.stop="() => handleClick(type)" {{ capitalize(type).replace('-', '') }}
> </QTooltip>
<QTooltip> </QBtn>
{{ capitalize(type).replace('-', '') }} {{ phoneNumber }}
</QTooltip>
</QBtn></template
>
<span>{{ dashIfEmpty(phone) }}</span>
</div>
</template> </template>

View File

@ -30,16 +30,9 @@ export function useAcl() {
return false; return false;
} }
function hasAcl(model, prop, accessType) {
const modelAcl = state.getAcls().value[model];
const propAcl = modelAcl?.[prop] || modelAcl?.['*'];
return !!(propAcl?.[accessType] || propAcl?.['*']);
}
return { return {
fetch, fetch,
hasAny, hasAny,
state, state,
hasAcl,
}; };
} }

View File

@ -13,7 +13,7 @@ export function useRole() {
name: data.user.name, name: data.user.name,
nickname: data.user.nickname, nickname: data.user.nickname,
lang: data.user.lang || 'es', lang: data.user.lang || 'es',
departmentFk: data.user?.worker?.department?.departmentFk, departmentFk: data.user.worker.department.departmentFk,
}; };
state.setUser(userData); state.setUser(userData);
state.setRoles(roles); state.setRoles(roles);

View File

@ -100,8 +100,12 @@ const onChangePass = (oldPass) => {
}; };
onMounted(() => { onMounted(() => {
hasitManagementAccess.value = useAcl().hasAcl('VnUser', 'higherPrivileges', 'WRITE'); hasitManagementAccess.value = useAcl().hasAny([
hasSysadminAccess.value = useAcl().hasAcl('VnUser', 'adminUser', 'WRITE'); { model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' },
]);
hasSysadminAccess.value = useAcl().hasAny([
{ model: 'VnUser', props: 'adminUser', accessType: 'WRITE' },
]);
}); });
</script> </script>
<template> <template>
@ -223,7 +227,7 @@ onMounted(() => {
<QItemSection>{{ t('account.card.actions.deactivateUser.name') }}</QItemSection> <QItemSection>{{ t('account.card.actions.deactivateUser.name') }}</QItemSection>
</QItem> </QItem>
<QItem <QItem
v-if="useAcl().hasAcl('VnRole', '*', 'WRITE')" v-if="useAcl().hasAny([{ model: 'VnRole', props: '*', accessType: 'WRITE' }])"
v-ripple v-ripple
clickable clickable
@click="showSyncDialog = true" @click="showSyncDialog = true"

View File

@ -25,7 +25,7 @@ import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.v
const { openConfirmationModal } = useVnConfirm(); const { openConfirmationModal } = useVnConfirm();
const { sendEmail, openReport } = usePrintService(); const { sendEmail, openReport } = usePrintService();
const { t } = useI18n(); const { t } = useI18n();
const { hasAcl } = useAcl(); const { hasAny } = useAcl();
const quasar = useQuasar(); const quasar = useQuasar();
const route = useRoute(); const route = useRoute();
@ -276,7 +276,9 @@ const showBalancePdf = ({ id }) => {
> >
<VnInput <VnInput
v-model="scope.value" v-model="scope.value"
:disable="!hasAcl('Receipt', '*', 'WRITE')" :disable="
!hasAny([{ model: 'Receipt', props: '*', accessType: 'WRITE' }])
"
@keypress.enter="scope.set" @keypress.enter="scope.set"
autofocus autofocus
/> />

View File

@ -84,31 +84,29 @@ const sumRisk = ({ clientRisks }) => {
<VnLv :label="t('customer.summary.customerId')" :value="entity.id" /> <VnLv :label="t('customer.summary.customerId')" :value="entity.id" />
<VnLv :label="t('globals.name')" :value="entity.name" /> <VnLv :label="t('globals.name')" :value="entity.name" />
<VnLv :label="t('customer.summary.contact')" :value="entity.contact" /> <VnLv :label="t('customer.summary.contact')" :value="entity.contact" />
<VnLv :label="t('customer.extendedList.tableVisibleColumns.phone')"> <VnLv :value="entity.phone">
<template #value> <template #label>
{{ t('customer.extendedList.tableVisibleColumns.phone') }}
<VnLinkPhone :phone-number="entity.phone" /> <VnLinkPhone :phone-number="entity.phone" />
</template> </template>
</VnLv> </VnLv>
<VnLv :label="t('customer.summary.mobile')"> <VnLv :value="entity.mobile">
<template #value> <template #label>
{{ t('customer.summary.mobile') }}
<VnLinkPhone :phone-number="entity.mobile" />
<VnLinkPhone <VnLinkPhone
sip
say-simple say-simple
:phone-number="entity.mobile" :phone-number="entity.mobile"
:channel="entity.country?.saySimpleCountry?.channel" :channel="entity.country?.saySimpleCountry?.channel"
class="q-ml-xs"
/> />
</template> </template>
</VnLv> </VnLv>
<VnLv <VnLv :value="entity.email" copy
:label="t('globals.params.email')" ><template #label>
:value="entity.email" {{ t('globals.params.email') }}
class="ellipsis" <VnLinkMail email="entity.email"></VnLinkMail> </template
copy ></VnLv>
>
<template #value>
<VnLinkMail :email="entity.email" />
</template>
</VnLv>
<VnLv :label="t('globals.department')"> <VnLv :label="t('globals.department')">
<template #value> <template #value>
<span class="link" v-text="entity.department?.name" /> <span class="link" v-text="entity.department?.name" />

View File

@ -70,8 +70,8 @@ onMounted(async () => {
:url="`#/entry/${entityId}/basic-data`" :url="`#/entry/${entityId}/basic-data`"
:text="t('globals.summary.basicData')" :text="t('globals.summary.basicData')"
/> />
<div class="vn-card-group"> <div class="card-group">
<div class="vn-card-content"> <div class="card-content">
<VnLv <VnLv
:label="t('entry.summary.commission')" :label="t('entry.summary.commission')"
:value="entry?.commission" :value="entry?.commission"
@ -93,7 +93,7 @@ onMounted(async () => {
:value="entry?.invoiceNumber" :value="entry?.invoiceNumber"
/> />
</div> </div>
<div class="vn-card-content"> <div class="card-content">
<VnCheckbox <VnCheckbox
:label="t('entry.list.tableVisibleColumns.isOrdered')" :label="t('entry.list.tableVisibleColumns.isOrdered')"
v-model="entry.isOrdered" v-model="entry.isOrdered"
@ -130,8 +130,8 @@ onMounted(async () => {
:url="`#/travel/${entry.travel.id}/summary`" :url="`#/travel/${entry.travel.id}/summary`"
:text="t('Travel')" :text="t('Travel')"
/> />
<div class="vn-card-group"> <div class="card-group">
<div class="vn-card-content"> <div class="card-content">
<VnLv :label="t('entry.summary.travelReference')"> <VnLv :label="t('entry.summary.travelReference')">
<template #value> <template #value>
<span class="link"> <span class="link">
@ -161,7 +161,7 @@ onMounted(async () => {
:value="entry.travel.warehouseIn?.name" :value="entry.travel.warehouseIn?.name"
/> />
</div> </div>
<div class="vn-card-content"> <div class="card-content">
<VnLv :label="t('travel.awbFk')" :value="entry.travel.awbFk" /> <VnLv :label="t('travel.awbFk')" :value="entry.travel.awbFk" />
<VnCheckbox <VnCheckbox
:label="t('entry.summary.travelDelivered')" :label="t('entry.summary.travelDelivered')"
@ -193,6 +193,31 @@ onMounted(async () => {
</template> </template>
</CardSummary> </CardSummary>
</template> </template>
<style lang="scss" scoped>
.card-group {
display: flex;
flex-direction: column;
}
.card-content {
display: flex;
flex-direction: column;
text-overflow: ellipsis;
> div {
max-height: 24px;
}
}
@media (min-width: 1010px) {
.card-group {
flex-direction: row;
}
.card-content {
flex: 1;
margin-right: 16px;
}
}
</style>
<i18n> <i18n>
es: es:
Travel: Envío Travel: Envío

View File

@ -22,7 +22,7 @@ const routes = reactive({
getSupplier: (id) => { getSupplier: (id) => {
return { name: 'SupplierCard', params: { id } }; return { name: 'SupplierCard', params: { id } };
}, },
getInvoices: (id) => { getTickets: (id) => {
return { return {
name: 'InvoiceInList', name: 'InvoiceInList',
query: { query: {
@ -131,11 +131,11 @@ async function setInvoiceCorrection(id) {
</QBtn> </QBtn>
<QBtn <QBtn
size="md" size="md"
icon="vn:invoice-in" icon="vn:ticket"
color="primary" color="primary"
:to="routes.getInvoices(entity.supplierFk)" :to="routes.getTickets(entity.supplierFk)"
> >
<QTooltip>{{ t('invoiceIn.descriptor.invoices') }}</QTooltip> <QTooltip>{{ t('globals.ticketList') }}</QTooltip>
</QBtn> </QBtn>
<QBtn <QBtn
v-if=" v-if="

View File

@ -15,7 +15,6 @@ invoiceIn:
amount: Amount amount: Amount
descriptor: descriptor:
ticketList: Ticket list ticketList: Ticket list
invoices: Supplier invoices
descriptorMenu: descriptorMenu:
book: Book book: Book
unbook: Unbook unbook: Unbook

View File

@ -14,7 +14,7 @@ invoiceIn:
awb: AWB awb: AWB
amount: Importe amount: Importe
descriptor: descriptor:
invoices: Facturas de proveedor ticketList: Listado de tickets
descriptorMenu: descriptorMenu:
book: Contabilizar book: Contabilizar
unbook: Descontabilizar unbook: Descontabilizar

View File

@ -112,9 +112,12 @@ const filter = {
:label="t('Trailer Plate')" :label="t('Trailer Plate')"
:value="dashIfEmpty(entity?.trailerPlate)" :value="dashIfEmpty(entity?.trailerPlate)"
/> />
<VnLv :label="t('Phone')"> <VnLv :label="t('Phone')" :value="dashIfEmpty(entity?.phone)">
<template #value> <template #value>
<VnLinkPhone :phone-number="entity?.phone" /> <span>
{{ dashIfEmpty(entity?.phone) }}
<VnLinkPhone :phone-number="entity?.phone" />
</span>
</template> </template>
</VnLv> </VnLv>
<VnLv <VnLv

View File

@ -25,7 +25,9 @@ const { validate } = useValidator();
const { notify } = useNotify(); const { notify } = useNotify();
const router = useRouter(); const router = useRouter();
const { t } = useI18n(); const { t } = useI18n();
const canEditZone = useAcl().hasAcl('Ticket', 'editZone', 'WRITE'); const canEditZone = useAcl().hasAny([
{ model: 'Ticket', props: 'editZone', accessType: 'WRITE' },
]);
const agencyFetchRef = ref(); const agencyFetchRef = ref();
const warehousesOptions = ref([]); const warehousesOptions = ref([]);

View File

@ -55,7 +55,9 @@ const isClaimable = computed(() => {
if (ticket.value) { if (ticket.value) {
const landedPlusWeek = new Date(ticket.value.landed); const landedPlusWeek = new Date(ticket.value.landed);
landedPlusWeek.setDate(landedPlusWeek.getDate() + 7); landedPlusWeek.setDate(landedPlusWeek.getDate() + 7);
const createAfterDeadline = acl.hasAcl('Claim', 'createAfterDeadline', 'WRITE'); const createAfterDeadline = acl.hasAny([
{ model: 'Claim', props: 'createAfterDeadline', accessType: 'WRITE' },
]);
return landedPlusWeek >= Date.vnNew() || createAfterDeadline; return landedPlusWeek >= Date.vnNew() || createAfterDeadline;
} }
return false; return false;

View File

@ -113,7 +113,7 @@ const columns = computed(() => [
}, },
{ {
align: 'left', align: 'left',
name: 'shippedDate', name: 'shipped',
cardVisible: true, cardVisible: true,
label: t('ticketList.shipped'), label: t('ticketList.shipped'),
columnFilter: { columnFilter: {
@ -123,7 +123,7 @@ const columns = computed(() => [
}, },
{ {
align: 'left', align: 'left',
name: 'shippedHour', name: 'shipped',
component: 'time', component: 'time',
columnFilter: false, columnFilter: false,
label: t('ticketList.hour'), label: t('ticketList.hour'),

View File

@ -205,7 +205,6 @@ ticketList:
toLines: Go to lines toLines: Go to lines
addressNickname: Address nickname addressNickname: Address nickname
ref: Reference ref: Reference
hour: Hour
rounding: Rounding rounding: Rounding
noVerifiedData: No verified data noVerifiedData: No verified data
purchaseRequest: Purchase request purchaseRequest: Purchase request

View File

@ -37,7 +37,7 @@ const cloneTravelWithEntries = async () => {
router.push({ name: 'TravelBasicData', params: { id: data.id } }); router.push({ name: 'TravelBasicData', params: { id: data.id } });
}; };
const canDelete = computed(() => useAcl().hasAcl('Travel', '*', 'WRITE')); const canDelete = computed(() => useAcl().hasAny('Travel', '*', 'WRITE'));
const openDeleteEntryDialog = (id) => { const openDeleteEntryDialog = (id) => {
quasar quasar

View File

@ -18,7 +18,9 @@ const router = useRouter();
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const acl = useAcl(); const acl = useAcl();
const canSeeNotes = computed(() => acl.hasAcl('Worker', '__get__business', 'READ')); const canSeeNotes = computed(() =>
acl.hasAny([{ model: 'Worker', props: '__get__business', accessType: 'READ' }]),
);
const workerIsFreelance = ref(); const workerIsFreelance = ref();
const WorkerFreelanceRef = ref(); const WorkerFreelanceRef = ref();
const workerCalendarFilterRef = ref(null); const workerCalendarFilterRef = ref(null);

View File

@ -116,7 +116,7 @@ const handlePhotoUpdated = (evt = false) => {
<template #body="{ entity }"> <template #body="{ entity }">
<VnLv :label="t('globals.user')" :value="entity.user?.name" /> <VnLv :label="t('globals.user')" :value="entity.user?.name" />
<VnLv <VnLv
class="ellipsis" class="ellipsis-text"
:label="t('globals.params.email')" :label="t('globals.params.email')"
:value="entity.user?.emailUser?.email" :value="entity.user?.emailUser?.email"
copy copy
@ -128,13 +128,15 @@ const handlePhotoUpdated = (evt = false) => {
</template> </template>
</VnLv> </VnLv>
<VnLv :label="t('globals.phone')"> <VnLv :value="entity.phone">
<template #value> <template #label>
{{ t('globals.phone') }}
<VnLinkPhone :phone-number="entity.phone" /> <VnLinkPhone :phone-number="entity.phone" />
</template> </template>
</VnLv> </VnLv>
<VnLv :label="t('worker.summary.sipExtension')"> <VnLv :value="entity?.sip?.extension">
<template #value> <template #label>
{{ t('worker.summary.sipExtension') }}
<VnLinkPhone :phone-number="entity?.sip?.extension" /> <VnLinkPhone :phone-number="entity?.sip?.extension" />
</template> </template>
</VnLv> </VnLv>

View File

@ -9,7 +9,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
import { useArrayData } from 'src/composables/useArrayData'; import { useArrayData } from 'src/composables/useArrayData';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
const { hasAcl } = useAcl(); const { hasAny } = useAcl();
const { t } = useI18n(); const { t } = useI18n();
const fetchData = ref(); const fetchData = ref();
const originaLockerId = ref(); const originaLockerId = ref();
@ -58,7 +58,11 @@ const init = async (data) => {
option-label="code" option-label="code"
option-value="id" option-value="id"
hide-selected hide-selected
:readonly="!hasAcl('Worker', '__get__locker', 'READ')" :readonly="
!hasAny([
{ model: 'Worker', props: '__get__locker', accessType: 'READ' },
])
"
/> />
</template> </template>
</FormModel> </FormModel>

View File

@ -73,18 +73,21 @@ onBeforeMount(async () => {
/> />
</template> </template>
</VnLv> </VnLv>
<VnLv :label="t('worker.summary.phoneExtension')"> <VnLv :value="worker.mobileExtension">
<template #value> <template #label>
{{ t('worker.summary.phoneExtension') }}
<VnLinkPhone :phone-number="worker.mobileExtension" /> <VnLinkPhone :phone-number="worker.mobileExtension" />
</template> </template>
</VnLv> </VnLv>
<VnLv :label="t('worker.summary.entPhone')"> <VnLv :value="worker.phone">
<template #value> <template #label>
{{ t('worker.summary.entPhone') }}
<VnLinkPhone :phone-number="worker.phone" /> <VnLinkPhone :phone-number="worker.phone" />
</template> </template>
</VnLv> </VnLv>
<VnLv :label="t('worker.summary.personalPhone')"> <VnLv :value="advancedSummary?.client?.phone">
<template #value> <template #label>
{{ t('worker.summary.personalPhone') }}
<VnLinkPhone <VnLinkPhone
:phone-number="advancedSummary?.client?.phone" :phone-number="advancedSummary?.client?.phone"
/> />
@ -132,7 +135,6 @@ onBeforeMount(async () => {
<VnTitle :text="t('worker.summary.userData')" /> <VnTitle :text="t('worker.summary.userData')" />
<VnLv :label="t('globals.name')" :value="worker?.user?.nickname" /> <VnLv :label="t('globals.name')" :value="worker?.user?.nickname" />
<VnLv <VnLv
class="ellipsis"
:label="t('globals.params.email')" :label="t('globals.params.email')"
:value="worker.user?.emailUser?.email" :value="worker.user?.emailUser?.email"
copy copy
@ -145,8 +147,9 @@ onBeforeMount(async () => {
</span> </span>
</template> </template>
</VnLv> </VnLv>
<VnLv :label="t('worker.summary.sipExtension')"> <VnLv :value="worker?.sip?.extension">
<template #value> <template #label>
{{ t('worker.summary.sipExtension') }}
<VnLinkPhone :phone-number="worker?.sip?.extension" /> <VnLinkPhone :phone-number="worker?.sip?.extension" />
</template> </template>
</VnLv> </VnLv>

View File

@ -68,9 +68,13 @@ const arrayData = useArrayData('Worker');
const acl = useAcl(); const acl = useAcl();
const selectedDateYear = computed(() => moment(selectedDate.value).isoWeekYear()); const selectedDateYear = computed(() => moment(selectedDate.value).isoWeekYear());
const worker = computed(() => arrayData.store?.data); const worker = computed(() => arrayData.store?.data);
const canSend = computed(() => acl.hasAcl('WorkerTimeControl', 'sendMail', 'WRITE')); const canSend = computed(() =>
acl.hasAny([{ model: 'WorkerTimeControl', props: 'sendMail', accessType: 'WRITE' }]),
);
const canUpdate = computed(() => const canUpdate = computed(() =>
acl.hasAcl('WorkerTimeControl', 'updateMailState', 'WRITE'), acl.hasAny([
{ model: 'WorkerTimeControl', props: 'updateMailState', accessType: 'WRITE' },
]),
); );
const isHimself = computed(() => user.value.id === Number(route.params.id)); const isHimself = computed(() => user.value.id === Number(route.params.id));

View File

@ -75,13 +75,13 @@ onMounted(async () => {
<template #body="{ entity: zone }"> <template #body="{ entity: zone }">
<QCard class="vn-one"> <QCard class="vn-one">
<VnTitle :url="zoneUrl + `basic-data`" :text="t('summary.basicData')" /> <VnTitle :url="zoneUrl + `basic-data`" :text="t('summary.basicData')" />
<div class="vn-card-group"> <div class="card-group">
<div class="vn-card-content"> <div class="card-content">
<VnLv :label="t('list.agency')" :value="zone.agencyMode?.name" /> <VnLv :label="t('list.agency')" :value="zone.agencyMode?.name" />
<VnLv :label="t('list.price')" :value="toCurrency(zone.price)" /> <VnLv :label="t('list.price')" :value="toCurrency(zone.price)" />
<VnLv :label="t('zone.bonus')" :value="toCurrency(zone.bonus)" /> <VnLv :label="t('zone.bonus')" :value="toCurrency(zone.bonus)" />
</div> </div>
<div class="vn-card-content"> <div class="card-content">
<VnLv <VnLv
:label="t('summary.closeHour')" :label="t('summary.closeHour')"
:value="toTimeFormat(zone.hour)" :value="toTimeFormat(zone.hour)"
@ -98,7 +98,7 @@ onMounted(async () => {
</div> </div>
</div> </div>
</QCard> </QCard>
<QCard class="vn-max"> <QCard class="vn-one">
<VnTitle :url="zoneUrl + `warehouses`" :text="t('list.warehouse')" /> <VnTitle :url="zoneUrl + `warehouses`" :text="t('list.warehouse')" />
<QTable <QTable
:columns="columns" :columns="columns"
@ -109,3 +109,15 @@ onMounted(async () => {
</template> </template>
</CardSummary> </CardSummary>
</template> </template>
<style lang="scss" scoped>
.card-group {
display: flex;
flex-direction: column;
}
.card-content {
display: flex;
flex-direction: column;
}
</style>

View File

@ -40,7 +40,7 @@ describe('InvoiceInDescriptor', () => {
cy.visit('/#/invoice-in/6/summary'); cy.visit('/#/invoice-in/6/summary');
cy.selectDescriptorOption(5); cy.selectDescriptorOption(5);
cy.dataCy('SendEmailNotificationDialogInput_input').type( cy.dataCy('SendEmailNotifiactionDialogInput_input').type(
'{selectall}jorgito@gmail.mx', '{selectall}jorgito@gmail.mx',
); );
cy.clickConfirm(); cy.clickConfirm();

View File

@ -37,7 +37,7 @@ describe('InvoiceOut summary', () => {
}); });
}); });
it.skip('should transfer the invoice ', () => { it('should transfer the invoice ', () => {
cy.typeSearchbar('T1111111{enter}'); cy.typeSearchbar('T1111111{enter}');
cy.dataCy('descriptor-more-opts').click(); cy.dataCy('descriptor-more-opts').click();
cy.get(selectMenuOption(1)).click(); cy.get(selectMenuOption(1)).click();
@ -50,7 +50,7 @@ describe('InvoiceOut summary', () => {
cy.dataCy('descriptor-more-opts').click(); cy.dataCy('descriptor-more-opts').click();
cy.get(selectMenuOption(3)).click(); cy.get(selectMenuOption(3)).click();
cy.dataCy('InvoiceOutDescriptorMenuSendPdfOption').click(); cy.dataCy('InvoiceOutDescriptorMenuSendPdfOption').click();
cy.dataCy('SendEmailNotificationDialogInput').should('be.visible'); cy.dataCy('SendEmailNotifiactionDialogInput').should('be.visible');
cy.get(confirmSend).click(); cy.get(confirmSend).click();
cy.checkNotification('Notification sent'); cy.checkNotification('Notification sent');
}); });
@ -59,7 +59,7 @@ describe('InvoiceOut summary', () => {
cy.dataCy('descriptor-more-opts').click(); cy.dataCy('descriptor-more-opts').click();
cy.get(selectMenuOption(3)).click(); cy.get(selectMenuOption(3)).click();
cy.dataCy('InvoiceOutDescriptorMenuSendCsvOption').click(); cy.dataCy('InvoiceOutDescriptorMenuSendCsvOption').click();
cy.dataCy('SendEmailNotificationDialogInput').should('be.visible'); cy.dataCy('SendEmailNotifiactionDialogInput').should('be.visible');
cy.get(confirmSend).click(); cy.get(confirmSend).click();
cy.checkNotification('Notification sent'); cy.checkNotification('Notification sent');
}); });