Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 7869-ModifyZones

This commit is contained in:
Jon Elias 2025-03-18 07:57:45 +01:00
commit ff39addd67
21 changed files with 273 additions and 112 deletions

View File

@ -180,6 +180,7 @@ const toModule = computed(() => {
color="white"
class="link"
v-if="summary"
data-cy="openSummaryBtn"
>
<QTooltip>
{{ t('components.smartCard.openSummary') }}
@ -194,6 +195,7 @@ const toModule = computed(() => {
icon="launch"
round
size="md"
data-cy="goToSummaryBtn"
>
<QTooltip>
{{ t('components.cardDescriptor.summary') }}

View File

@ -81,6 +81,7 @@ async function fetch() {
name: `${moduleName ?? route.meta.moduleName}Summary`,
params: { id: entityId || entity.id },
}"
data-cy="goToSummaryBtn"
>
<QIcon name="open_in_new" color="white" size="sm" />
</router-link>

View File

@ -17,7 +17,7 @@ const props = defineProps({
const { t } = useI18n();
const route = useRoute();
const entityId = computed(() => props.id || route.params.id);
const { store } = useArrayData('Parking');
const { store } = useArrayData();
const card = computed(() => store.data);
</script>
<template>

View File

@ -2,11 +2,11 @@
import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import useCardDescription from 'composables/useCardDescription';
import VnLv from 'components/ui/VnLv.vue';
import { dashIfEmpty, toDate } from 'src/filters';
import RouteDescriptorMenu from 'pages/Route/Card/RouteDescriptorMenu.vue';
import filter from './RouteFilter.js';
import useCardDescription from 'src/composables/useCardDescription';
import axios from 'axios';
const $props = defineProps({

View File

@ -332,6 +332,7 @@ const openTicketsDialog = (id) => {
<QBtn
icon="vn:clone"
color="primary"
flat
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="confirmationDialog = true"
@ -341,6 +342,7 @@ const openTicketsDialog = (id) => {
<QBtn
icon="cloud_download"
color="primary"
flat
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="showRouteReport"
@ -352,6 +354,7 @@ const openTicketsDialog = (id) => {
<QBtn
icon="check"
color="primary"
flat
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="markAsServed()"

View File

@ -3,6 +3,7 @@ import { computed, ref, markRaw } from 'vue';
import { useI18n } from 'vue-i18n';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { toHour } from 'src/filters';
import { useRouter } from 'vue-router';
import RouteSummary from 'pages/Route/Card/RouteSummary.vue';
import RouteFilter from 'pages/Route/Card/RouteFilter.vue';
import VnTable from 'components/VnTable/VnTable.vue';
@ -11,9 +12,9 @@ import AgencyDescriptorProxy from 'src/pages/Route/Agency/Card/AgencyDescriptorP
import VehicleDescriptorProxy from 'src/pages/Route/Vehicle/Card/VehicleDescriptorProxy.vue';
import VnSection from 'src/components/common/VnSection.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
import RouteTickets from './RouteTickets.vue';
const { t } = useI18n();
const router = useRouter();
const { viewSummary } = useSummaryDialog();
const tableRef = ref([]);
const dataKey = 'RouteList';
@ -29,8 +30,10 @@ const routeFilter = {
};
function redirectToTickets(id) {
const url = `#/route/${id}/tickets`;
window.open(url, '_blank');
router.push({
name: 'RouteTickets',
params: { id },
});
}
const columns = computed(() => [
@ -46,26 +49,18 @@ const columns = computed(() => [
width: '25px',
},
{
align: 'left',
name: 'workerFk',
label: t('gloabls.worker'),
label: t('globals.worker'),
component: markRaw(VnSelectWorker),
create: true,
format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
columnFilter: false,
cardVisible: true,
width: '100px',
},
{
name: 'workerFk',
label: t('globals.worker'),
visible: false,
cardVisible: true,
},
{
name: 'agencyName',
label: t('globals.agency'),
},
{
label: t('globals.Agency'),
name: 'agencyModeFk',
component: 'select',
attrs: {
@ -77,23 +72,13 @@ const columns = computed(() => [
},
},
create: true,
columnFilter: false,
visible: false,
},
{
name: 'agencyName',
label: t('globals.agency'),
visible: false,
columnFilter: true,
cardVisible: true,
},
{
name: 'vehiclePlateNumber',
label: t('globals.vehicle'),
visible: true,
},
{
name: 'vehicleFk',
label: t('globals.Vehicle'),
cardVisible: true,
label: t('globals.vehicle'),
component: 'select',
attrs: {
url: 'vehicles',
@ -106,8 +91,9 @@ const columns = computed(() => [
},
},
create: true,
columnFilter: false,
visible: false,
columnFilter: true,
cardVisible: true,
visible: true,
},
{
align: 'center',
@ -181,8 +167,8 @@ const columns = computed(() => [
<VnTable
:with-filters="false"
:data-key
:columns="columns"
ref="tableRef"
:columns="columns"
:right-search="false"
redirect="route"
:create="{
@ -199,7 +185,7 @@ const columns = computed(() => [
<WorkerDescriptorProxy :id="row?.workerFk" v-if="row?.workerFk" />
</span>
</template>
<template #column-agencyName="{ row }">
<template #column-agencyModeFk="{ row }">
<span class="link" @click.stop>
{{ row?.agencyName }}
<AgencyDescriptorProxy
@ -208,7 +194,7 @@ const columns = computed(() => [
/>
</span>
</template>
<template #column-vehiclePlateNumber="{ row }">
<template #column-vehicleFk="{ row }">
<span class="link" @click.stop>
{{ row?.vehiclePlateNumber }}
<VehicleDescriptorProxy

View File

@ -1,5 +1,6 @@
<script setup>
import { ref, nextTick } from 'vue';
import { ref, nextTick, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import FetchData from 'components/FetchData.vue';
@ -17,12 +18,12 @@ const maritalStatus = [
{ code: 'M', name: t('Married') },
{ code: 'S', name: t('Single') },
];
async function setAdvancedSummary(data) {
const advanced = (await useAdvancedSummary('Workers', data.id)) ?? {};
onMounted(async () => {
const advanced = await useAdvancedSummary('Workers', useRoute().params.id);
Object.assign(form.value.formData, advanced);
await nextTick();
if (form.value) form.value.hasChanges = false;
}
nextTick(() => (form.value.hasChanges = false));
});
</script>
<template>
<FetchData
@ -42,7 +43,6 @@ async function setAdvancedSummary(data) {
:url-update="`Workers/${$route.params.id}`"
auto-load
model="Worker"
@on-fetch="setAdvancedSummary"
>
<template #form="{ data }">
<VnRow>

View File

@ -39,6 +39,7 @@ onBeforeMount(async () => {
url="Workers/summary"
:user-filter="{ where: { id: entityId } }"
data-key="Worker"
module-name="Worker"
>
<template #header="{ entity }">
<div>{{ entity.id }} - {{ entity.firstName }} {{ entity.lastName }}</div>

View File

@ -1,7 +1,15 @@
<script setup>
import VnCard from 'src/components/common/VnCard.vue';
import ZoneDescriptor from './ZoneDescriptor.vue';
import filter from 'src/pages/Zone/Card/ZoneFilter.js';
import { useRoute } from 'vue-router';
const route = useRoute();
</script>
<template>
<VnCard data-key="Zone" url="Zones" :descriptor="ZoneDescriptor" />
<VnCard
data-key="Zone"
:url="`Zones/${route.params.id}`"
:descriptor="ZoneDescriptor"
:filter="filter"
/>
</template>

View File

@ -8,13 +8,10 @@ export default {
icon: 'grid_view',
moduleName: 'Monitor',
keyBinding: 'm',
menu: ['MonitorTickets', 'MonitorClientsActions'],
},
component: RouterView,
redirect: { name: 'MonitorMain' },
menus: {
main: ['MonitorTickets', 'MonitorClientsActions'],
card: [],
},
children: [
{
path: '',

View File

@ -220,6 +220,7 @@ export default {
path: '',
name: 'RouteIndexMain',
redirect: { name: 'RouteList' },
component: () => import('src/pages/Route/RouteList.vue'),
children: [
{
name: 'RouteList',
@ -228,7 +229,6 @@ export default {
title: 'list',
icon: 'view_list',
},
component: () => import('src/pages/Route/RouteList.vue'),
},
routeCard,
],
@ -264,6 +264,7 @@ export default {
path: 'roadmap',
name: 'RouteRoadmap',
redirect: { name: 'RoadmapList' },
component: () => import('src/pages/Route/RouteRoadmap.vue'),
meta: {
title: 'RouteRoadmap',
icon: 'vn:troncales',
@ -276,7 +277,6 @@ export default {
title: 'list',
icon: 'view_list',
},
component: () => import('src/pages/Route/RouteRoadmap.vue'),
},
roadmapCard,
],
@ -294,6 +294,7 @@ export default {
path: 'agency',
name: 'RouteAgency',
redirect: { name: 'AgencyList' },
component: () => import('src/pages/Route/Agency/AgencyList.vue'),
meta: {
title: 'agency',
icon: 'garage_home',
@ -306,8 +307,6 @@ export default {
title: 'list',
icon: 'view_list',
},
component: () =>
import('src/pages/Route/Agency/AgencyList.vue'),
},
agencyCard,
],
@ -316,6 +315,7 @@ export default {
path: 'vehicle',
name: 'RouteVehicle',
redirect: { name: 'VehicleList' },
component: () => import('src/pages/Route/Vehicle/VehicleList.vue'),
meta: {
title: 'vehicle',
icon: 'directions_car',
@ -328,8 +328,6 @@ export default {
title: 'vehicleList',
icon: 'directions_car',
},
component: () =>
import('src/pages/Route/Vehicle/VehicleList.vue'),
},
vehicleCard,
],

View File

@ -1,4 +1,4 @@
describe('EntryDms', () => {
describe.skip('EntryDms', () => {
const entryId = 1;
beforeEach(() => {
@ -30,7 +30,7 @@ describe('EntryDms', () => {
const textAreaSelector =
'.q-textarea > .q-field__inner > .q-field__control > .q-field__control-container';
cy.get(
`tbody :nth-child(${newFileTd}) > .text-right > .no-wrap > :nth-child(2) > .q-btn > .q-btn__content > .q-icon`
`tbody :nth-child(${newFileTd}) > .text-right > .no-wrap > :nth-child(2) > .q-btn > .q-btn__content > .q-icon`,
).click();
cy.get(textAreaSelector).clear();

View File

@ -1,4 +1,4 @@
describe('Entry', () => {
describe.skip('Entry', () => {
beforeEach(() => {
cy.viewport(1920, 1080);
cy.login('buyer');
@ -20,7 +20,7 @@ describe('Entry', () => {
);
});
it.skip('Create entry, modify travel and add buys', () => {
it('Create entry, modify travel and add buys', () => {
createEntryAndBuy();
cy.get('a[data-cy="EntryBasicData-menu-item"]').click();
selectTravel('two');

View File

@ -1,4 +1,4 @@
describe('EntryStockBought', () => {
describe.skip('EntryStockBought', () => {
beforeEach(() => {
cy.viewport(1920, 1080);
cy.login('buyer');

View File

@ -2,7 +2,7 @@
describe('Logout', () => {
beforeEach(() => {
cy.login('developer');
cy.visit(`/#/dashboard`, false);
cy.visit(`/#/dashboard`);
cy.waitForElement('.q-page', 6000);
});
describe('by user', () => {
@ -28,17 +28,10 @@ describe('Logout', () => {
});
it('when token not exists', () => {
const exceptionHandler = (err) => {
if (err.code === 'AUTHORIZATION_REQUIRED') return;
};
Cypress.on('uncaught:exception', exceptionHandler);
cy.get('.q-list').first().should('be.visible').click();
cy.get('.q-list').should('be.visible').first().should('be.visible').click();
cy.wait('@badRequest');
cy.checkNotification('Authorization Required');
Cypress.off('uncaught:exception', exceptionHandler);
});
});
});

View File

@ -1,4 +1,4 @@
describe.skip('AgencyWorkCenter', () => {
describe('AgencyWorkCenter', () => {
const selectors = {
workCenter: 'workCenter_select',
popupSave: 'FormModelPopup_save',
@ -9,7 +9,7 @@ describe.skip('AgencyWorkCenter', () => {
const messages = {
dataCreated: 'Data created',
alreadyAssigned: 'This workCenter is already assigned to this agency',
removed: 'WorkCenter removed successfully',
removed: 'Work center removed successfully',
};
beforeEach(() => {

View File

@ -1,4 +1,4 @@
describe.skip('RouteAutonomous', () => {
describe('RouteAutonomous', () => {
const getLinkSelector = (colField) =>
`tr:first-child > [data-col-field="${colField}"] > .no-padding > .link`;

View File

@ -1,4 +1,4 @@
describe.skip('Route extended list', () => {
describe('Route extended list', () => {
const getSelector = (colField) => `tr:last-child > [data-col-field="${colField}"]`;
const selectors = {
@ -8,6 +8,8 @@ describe.skip('Route extended list', () => {
date: getSelector('dated'),
description: getSelector('description'),
served: getSelector('isOk'),
firstRowSelectCheckBox:
'tbody > tr:first-child > :nth-child(1) .q-checkbox__inner',
lastRowSelectCheckBox: 'tbody > tr:last-child > :nth-child(1) .q-checkbox__inner',
removeBtn: '[title="Remove"]',
resetBtn: '[title="Reset"]',
@ -19,7 +21,7 @@ describe.skip('Route extended list', () => {
markServedBtn: '#st-actions > .q-btn-group > :nth-child(3)',
searchbar: 'searchbar',
firstTicketsRowSelectCheckBox:
'.q-card > :nth-child(2) > .q-table__container > .q-table__middle > .q-table > tbody > :nth-child(1) > .q-table--col-auto-width > .q-checkbox > .q-checkbox__inner > .q-checkbox__bg > .q-checkbox__svg',
'.q-card .q-table > tbody > :nth-child(1) .q-checkbox',
};
const checkboxState = {
@ -117,12 +119,21 @@ describe.skip('Route extended list', () => {
});
});
it('Should clone selected route', () => {
cy.get(selectors.lastRowSelectCheckBox).click();
it('Should clone selected route and add ticket', () => {
cy.get(selectors.firstRowSelectCheckBox).click();
cy.get(selectors.cloneBtn).click();
cy.dataCy('route.Starting date_inputDate').type('10-05-2001').click();
cy.dataCy('Starting date_inputDate').type('01-01-2001');
cy.get('.q-card__actions > .q-btn--standard > .q-btn__content').click();
cy.validateContent(selectors.date, '05/10/2001');
cy.validateContent(selectors.date, '01/01/2001');
cy.dataCy('tableAction-0').last().click();
cy.get(selectors.firstTicketsRowSelectCheckBox).click();
cy.get('.q-card__actions > .q-btn--standard > .q-btn__content').click();
cy.checkNotification(dataSaved);
cy.get(selectors.lastRowSelectCheckBox).click();
cy.get(selectors.removeBtn).click();
cy.dataCy(selectors.confirmBtn).click();
});
it('Should download selected route', () => {
@ -143,22 +154,15 @@ describe.skip('Route extended list', () => {
cy.validateContent(selectors.served, checkboxState.check);
});
it('Should delete the selected route', () => {
it('Should delete the selected routes', () => {
cy.get(selectors.lastRowSelectCheckBox).click();
cy.get(selectors.removeBtn).click();
cy.dataCy(selectors.confirmBtn).click();
cy.checkNotification(dataSaved);
});
it('Should add ticket to route', () => {
cy.dataCy('tableAction-0').last().click();
cy.get(selectors.firstTicketsRowSelectCheckBox).click();
cy.get('.q-card__actions > .q-btn--standard > .q-btn__content').click();
cy.checkNotification(dataSaved);
});
it('Should save changes in route', () => {
updateFields.forEach(({ selector, type, value }) => {
fillField(selector, type, value);

View File

@ -1,37 +1,205 @@
describe('Route', () => {
const getSelector = (colField) =>
`tr:last-child > [data-col-field="${colField}"] > .no-padding > .link`;
const selectors = {
lastRow: 'tr:last-child > [data-col-field="workerFk"]',
workerLink: getSelector('workerFk'),
agencyLink: getSelector('agencyModeFk'),
vehicleLink: getSelector('vehicleFk'),
assignedTicketsBtn: 'tableAction-0',
rowSummaryBtn: 'tableAction-1',
summaryTitle: '.summaryHeader',
descriptorTitle: '.descriptor .title',
descriptorOpenSummaryBtn: '.descriptor [data-cy="openSummaryBtn"]',
descriptorGoToSummaryBtn: '.descriptor [data-cy="goToSummaryBtn"]',
SummaryGoToSummaryBtn: '.summaryHeader [data-cy="goToSummaryBtn"]',
};
const data = {
Worker: { val: 'logistic', type: 'select' },
Agency: { val: 'Walking', type: 'select' },
Vehicle: { val: '3333-BAT', type: 'select' },
Description: { val: 'routeTest' },
};
const summaryUrl = '/summary';
beforeEach(() => {
cy.viewport(1920, 1080);
cy.login('developer');
cy.visit(`/#/route/extended-list`);
cy.visit(`/#/route/list`);
cy.typeSearchbar('{enter}');
});
it('Route list create route', () => {
it('Should list routes', () => {
cy.get('.q-table')
.children()
.should('be.visible')
.should('have.length.greaterThan', 0);
});
it('Should create new route', () => {
cy.addBtnClick();
cy.get('.q-card input[name="description"]').type('routeTestOne{enter}');
cy.get('.q-notification__message').should('have.text', 'Data created');
cy.url().should('include', '/summary');
cy.fillInForm(data);
cy.dataCy('FormModelPopup_save').should('be.visible').click();
cy.checkNotification('Data created');
cy.url().should('include', summaryUrl);
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Description.val);
});
});
it('Route list search and edit', () => {
cy.get('#searchbar input').type('{enter}');
cy.get('[data-col-field="description"][data-row-index="0"]')
.click()
.type('routeTestOne{enter}');
cy.get('.q-table tr')
.its('length')
.then((rowCount) => {
expect(rowCount).to.be.greaterThan(0);
it('Should open route summary by clicking a route', () => {
cy.get(selectors.lastRow).should('be.visible').click();
cy.url().should('include', summaryUrl);
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Description.val);
});
cy.get('[data-col-field="workerFk"][data-row-index="0"]')
.click()
.type('{downArrow}{enter}');
cy.get('[data-col-field="agencyModeFk"][data-row-index="0"]')
.click()
.type('{downArrow}{enter}');
cy.get('[data-col-field="vehicleFk"][data-row-index="0"]')
.click()
.type('{downArrow}{enter}');
cy.get('button[title="Save"]').click();
cy.get('.q-notification__message').should('have.text', 'Data saved');
});
it('Should redirect to the summary from the route pop-up summary', () => {
cy.dataCy(selectors.rowSummaryBtn).last().should('be.visible').click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Description.val);
});
cy.get(selectors.SummaryGoToSummaryBtn).click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Description.val);
});
});
it('Should redirect to the route assigned tickets from the row assignedTicketsBtn', () => {
cy.dataCy(selectors.assignedTicketsBtn).first().should('be.visible').click();
cy.url().should('include', '1/tickets');
cy.get('.q-table')
.children()
.should('be.visible')
.should('have.length.greaterThan', 0);
});
describe('Worker pop-ups', () => {
it('Should redirect to summary from the worker pop-up descriptor', () => {
cy.get(selectors.workerLink).click();
cy.get(selectors.descriptorTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Worker.val);
});
cy.get(selectors.descriptorGoToSummaryBtn).click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Worker.val);
});
});
it('Should redirect to the summary from the worker pop-up summary', () => {
cy.get(selectors.workerLink).click();
cy.get(selectors.descriptorTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Worker.val);
});
cy.get(selectors.descriptorOpenSummaryBtn).click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Worker.val);
});
cy.get(selectors.SummaryGoToSummaryBtn).click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Worker.val);
});
});
});
describe('Agency pop-ups', () => {
it('Should redirect to summary from the agency pop-up descriptor', () => {
cy.get(selectors.agencyLink).click();
cy.get(selectors.descriptorTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Agency.val);
});
cy.get(selectors.descriptorGoToSummaryBtn).click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Agency.val);
});
});
it('Should redirect to the summary from the agency pop-up summary', () => {
cy.get(selectors.agencyLink).click();
cy.get(selectors.descriptorTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Agency.val);
});
cy.get(selectors.descriptorOpenSummaryBtn).click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Agency.val);
});
cy.get(selectors.SummaryGoToSummaryBtn).click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Agency.val);
});
});
});
describe('Vehicle pop-ups', () => {
it('Should redirect to summary from the vehicle pop-up descriptor', () => {
cy.get(selectors.vehicleLink).click();
cy.get(selectors.descriptorTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Vehicle.val);
});
cy.get(selectors.descriptorGoToSummaryBtn).click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Vehicle.val);
});
});
it('Should redirect to the summary from the vehicle pop-up summary', () => {
cy.get(selectors.vehicleLink).click();
cy.get(selectors.descriptorTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Vehicle.val);
});
cy.get(selectors.descriptorOpenSummaryBtn).click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Vehicle.val);
});
cy.get(selectors.SummaryGoToSummaryBtn).click();
cy.get(selectors.summaryTitle)
.invoke('text')
.then((text) => {
expect(text).to.include(data.Vehicle.val);
});
});
});
});

View File

@ -2,11 +2,11 @@ describe('Vehicle', () => {
beforeEach(() => {
cy.viewport(1920, 1080);
cy.login('deliveryAssistant');
cy.visit(`/#/route/vehicle/7`);
cy.visit(`/#/route/vehicle/7/summary`);
});
it('should delete a vehicle', () => {
cy.openActionsDescriptor();
cy.dataCy('descriptor-more-opts').click();
cy.get('[data-cy="delete"]').click();
cy.checkNotification('Vehicle removed');
});

View File

@ -184,7 +184,7 @@ Cypress.Commands.add('fillInForm', (obj, form = '.q-form > .q-card') => {
cy.get('.q-time .q-time__link').contains(val.x).click();
break;
default:
cy.wrap(el).type(val);
cy.wrap(el).type(`{selectall}${val}`, { delay: 0 });
break;
}
});