feat: refs #8441 add VehicleInvoiceIn component with invoice management functionality #1567
|
@ -0,0 +1,140 @@
|
|||
<script setup>
|
||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||
import InvoiceInDescriptorProxy from 'pages/InvoiceIn/Card/InvoiceInDescriptorProxy.vue';
|
||||
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||
import { toDate, toCurrency } from 'src/filters/index';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { ref, computed } from 'vue';
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import axios from 'axios';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||
|
||||
const tableRef = ref();
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const { notify } = useNotify();
|
||||
const dataKey = 'VehicleInvoiceIn';
|
||||
const { openConfirmationModal } = useVnConfirm();
|
||||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
align: 'left',
|
||||
name: 'issued',
|
||||
label: t('invoiceIn.list.issued'),
|
||||
columnFilter: {
|
||||
component: 'date',
|
||||
},
|
||||
format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.issued)),
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
name: 'supplierFk',
|
||||
label: t('invoiceIn.list.supplier'),
|
||||
columnFilter: {
|
||||
component: 'select',
|
||||
attrs: {
|
||||
url: 'Suppliers',
|
||||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
format: ({ supplierName }) => supplierName,
|
||||
columnClass: 'expand',
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
name: 'supplierRef',
|
||||
label: t('invoiceIn.supplierRef'),
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
name: 'amount',
|
||||
label: t('invoiceIn.list.amount'),
|
||||
format: ({ amount }) => toCurrency(amount),
|
||||
columnFilter: false,
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
name: 'tableActions',
|
||||
actions: [
|
||||
{
|
||||
title: t('vehicle.ticket.unassignInvoice'),
|
||||
icon: 'delete',
|
||||
action: (row) =>
|
||||
openConfirmationModal(
|
||||
t('vehicle.ticket.unassignInvoice'),
|
||||
t('vehicle.ticket.unassignInvoiceConfirmation'),
|
||||
() => unassignInvoice(row.id),
|
||||
),
|
||||
isPrimary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
async function unassignInvoice(id) {
|
||||
try {
|
||||
await axios.delete(`VehicleInvoiceIns/${id}`);
|
||||
jtubau marked this conversation as resolved
Outdated
|
||||
notify(t('vehicle.ticket.unlinkedInvoice'), 'positive');
|
||||
tableRef.value.reload();
|
||||
} catch (e) {
|
||||
throw e;
|
||||
jtubau marked this conversation as resolved
Outdated
jorgep
commented
throw e throw e
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VnTable
|
||||
ref="tableRef"
|
||||
:data-key="dataKey"
|
||||
:url="`vehicles/${route.params.id}/getInvoices`"
|
||||
:columns="columns"
|
||||
search-url="vehicleInvoiceIns"
|
||||
:order="['issued DESC', 'supplierRef ASC']"
|
||||
:create="{
|
||||
urlCreate: 'VehicleInvoiceIns',
|
||||
title: t('vehicle.ticket.assignInvoice'),
|
||||
formInitialData: {
|
||||
vehicleFk: parseInt(route.params.id, 10),
|
||||
},
|
||||
onDataSaved: ({ id }) => tableRef.reload(),
|
||||
}"
|
||||
auto-load
|
||||
>
|
||||
<template #column-supplierFk="{ row }">
|
||||
<span class="link" @click.stop>
|
||||
{{ row.supplierName }}
|
||||
<SupplierDescriptorProxy :id="row.supplierId" />
|
||||
</span>
|
||||
</template>
|
||||
<template #column-supplierRef="{ row }">
|
||||
<span class="link" @click.stop>
|
||||
{{ row.supplierRef }}
|
||||
<InvoiceInDescriptorProxy :id="row.invoiceInFk" />
|
||||
</span>
|
||||
</template>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<VnSelect
|
||||
url="invoiceIns"
|
||||
:label="t('invoiceIn.supplierRef')"
|
||||
:fields="['id', 'supplierRef', 'supplierFk']"
|
||||
:filter-options="['id', 'supplierRef']"
|
||||
v-model="data.invoiceInFk"
|
||||
option-label="supplierRef"
|
||||
:required="true"
|
||||
>
|
||||
</VnSelect>
|
||||
<VnInputNumber
|
||||
:label="t('invoiceIn.list.amount')"
|
||||
v-model="data.amount"
|
||||
required
|
||||
/>
|
||||
</template>
|
||||
</VnTable>
|
||||
</template>
|
|
@ -1,16 +1,20 @@
|
|||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { dashIfEmpty, toCurrency, toDate } from 'src/filters';
|
||||
import { downloadFile } from 'src/composables/downloadFile';
|
||||
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import CardSummary from 'components/ui/CardSummary.vue';
|
||||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||
import InvoiceInDescriptorProxy from 'src/pages/InvoiceIn/Card/InvoiceInDescriptorProxy.vue';
|
||||
import VehicleFilter from '../VehicleFilter.js';
|
||||
import { downloadFile } from 'src/composables/downloadFile';
|
||||
import { dashIfEmpty } from 'src/filters';
|
||||
|
||||
const props = defineProps({ id: { type: [Number, String], default: null } });
|
||||
|
||||
const invoices = ref([]);
|
||||
const route = useRoute();
|
||||
const entityId = computed(() => props.id || +route.params.id);
|
||||
const baseLink = `#/${route.meta.moduleName.toLowerCase()}/vehicle/${entityId.value}`;
|
||||
|
@ -23,6 +27,11 @@ const links = {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
:url="`Vehicles/${entityId}/getInvoices`"
|
||||
auto-load
|
||||
@on-fetch="(data) => (invoices = data)"
|
||||
/>
|
||||
<CardSummary
|
||||
data-key="Vehicle"
|
||||
:url="`Vehicles/${entityId}`"
|
||||
|
@ -132,6 +141,45 @@ const links = {
|
|||
</QList>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
<QCard class="vn-max">
|
||||
<VnTitle
|
||||
:url="links['invoice-in']"
|
||||
:text="$t('vehicle.ticket.assignedInvoices')"
|
||||
/>
|
||||
<QTable :rows="invoices" style="text-align: center">
|
||||
<template #body-cell="{ value }">
|
||||
<QTd>{{ value }}</QTd>
|
||||
</template>
|
||||
<template #header="props">
|
||||
<QTr class="tr-header" :props="props">
|
||||
<QTh auto-width>{{ $t('invoiceIn.list.issued') }}</QTh>
|
||||
<QTh auto-width>{{ $t('invoiceIn.list.supplier') }}</QTh>
|
||||
<QTh auto-width>{{ $t('invoiceIn.supplierRef') }}</QTh>
|
||||
<QTh auto-width>{{ $t('invoiceIn.list.amount') }}</QTh>
|
||||
</QTr>
|
||||
</template>
|
||||
<template #body="props">
|
||||
<QTr :props="props">
|
||||
<QTd>{{ toDate(props.row.issued) }}</QTd>
|
||||
<QTd>
|
||||
<span class="link">
|
||||
{{ props.row.supplierName }}
|
||||
<SupplierDescriptorProxy :id="props.row.supplierId" />
|
||||
</span>
|
||||
</QTd>
|
||||
<QTd>
|
||||
<span class="link">
|
||||
{{ props.row.supplierRef }}
|
||||
<InvoiceInDescriptorProxy
|
||||
:id="props.row.supplierId"
|
||||
/>
|
||||
</span>
|
||||
</QTd>
|
||||
<QTd>{{ toCurrency(props.row.amount) }}</QTd>
|
||||
</QTr>
|
||||
</template>
|
||||
</QTable>
|
||||
</QCard>
|
||||
</template>
|
||||
</CardSummary>
|
||||
</template>
|
||||
|
|
|
@ -18,3 +18,9 @@ vehicle:
|
|||
params:
|
||||
vehicleTypeFk: Type
|
||||
vehicleStateFk: State
|
||||
ticket:
|
||||
assignedInvoices: Assigned Invoices
|
||||
assignInvoice: Assign invoice
|
||||
unlinkedInvoice: Unlinked invoice
|
||||
jtubau marked this conversation as resolved
Outdated
jorgep
commented
el adjetivo va delante en inglés el adjetivo va delante en inglés
jtubau
commented
cambiado cambiado
|
||||
unassignInvoice: Unassign invoice
|
||||
unassignInvoiceConfirmation: This invoice will be unassigned from this vehicle! Continue anyway?
|
||||
|
|
|
@ -18,3 +18,9 @@ vehicle:
|
|||
params:
|
||||
vehicleTypeFk: Tipo
|
||||
vehicleStateFk: Estado
|
||||
ticket:
|
||||
assignedInvoices: Facturas vinculadas
|
||||
assignInvoice: Vincular factura
|
||||
unlinkedInvoice: Factura desvinculada
|
||||
unassignInvoice: Desvincular factura
|
||||
unassignInvoiceConfirmation: Esta factura se desvinculará de este vehículo! ¿Continuar de todas formas?
|
||||
|
|
|
@ -51,6 +51,7 @@ route:
|
|||
agencyModeName: Agency route
|
||||
isOwn: Own
|
||||
isAnyVolumeAllowed: Any volume allowed
|
||||
issued: Issued
|
||||
jtubau marked this conversation as resolved
jorgep
commented
Creo que esta traduccion es global, o por lo menos es exactamente la misma que en invoiceIn, hazla global o mira a ver si ya está. Creo que esta traduccion es global, o por lo menos es exactamente la misma que en invoiceIn, hazla global o mira a ver si ya está.
|
||||
Worker: Worker
|
||||
Agency: Agency
|
||||
Vehicle: Vehicle
|
||||
|
|
|
@ -47,11 +47,12 @@ route:
|
|||
routeFk: Id ruta
|
||||
clientFk: Id cliente
|
||||
countryFk: Pais
|
||||
shipped: Fecha preparación
|
||||
shipped: F. preparación
|
||||
agencyModeName: Agencia Ruta
|
||||
agencyAgreement: Agencia Acuerdo
|
||||
isOwn: Propio
|
||||
isAnyVolumeAllowed: Cualquier volumen
|
||||
issued: F. emisión
|
||||
jtubau marked this conversation as resolved
jorgep
commented
Lo mismo que en inglés Lo mismo que en inglés
jtubau
commented
esta ahí por el filtro automático de vnTable, ya que busca la traducción en moduleName.params y en este caso es route.params esta ahí por el filtro automático de vnTable, ya que busca la traducción en moduleName.params y en este caso es route.params
|
||||
Worker: Trabajador
|
||||
Agency: Agencia
|
||||
Vehicle: Vehículo
|
||||
|
@ -82,6 +83,7 @@ route:
|
|||
routeFk: Id ruta
|
||||
country: País
|
||||
clientFk: Id cliente
|
||||
shipped: Fecha preparación
|
||||
warehouseFk: Almacén
|
||||
shipped: F. preparación
|
||||
viewCmr: Ver CMR
|
||||
downloadCmrs: Descargar CMRs
|
||||
|
|
|
@ -34,7 +34,7 @@ const importDms = async () => {
|
|||
dmsId.value = null;
|
||||
emit('onDataSaved');
|
||||
} catch (e) {
|
||||
throw new Error(e.message);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -79,6 +79,7 @@ const agencyCard = {
|
|||
path: 'workCenter',
|
||||
name: 'AgencyWorkCenterCard',
|
||||
redirect: { name: 'AgencyWorkCenters' },
|
||||
component: () => import('src/pages/Route/Agency/Card/AgencyWorkcenter.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
|
@ -87,8 +88,6 @@ const agencyCard = {
|
|||
icon: 'apartment',
|
||||
title: 'workCenters',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Route/Agency/Card/AgencyWorkcenter.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -96,6 +95,7 @@ const agencyCard = {
|
|||
path: 'modes',
|
||||
name: 'AgencyModesCard',
|
||||
redirect: { name: 'AgencyModes' },
|
||||
component: () => import('src/pages/Route/Agency/Card/AgencyModes.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
|
@ -104,8 +104,6 @@ const agencyCard = {
|
|||
icon: 'format_list_bulleted',
|
||||
title: 'modes',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Route/Agency/Card/AgencyModes.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -166,7 +164,10 @@ const vehicleCard = {
|
|||
component: () => import('src/pages/Route/Vehicle/Card/VehicleCard.vue'),
|
||||
redirect: { name: 'VehicleSummary' },
|
||||
meta: {
|
||||
menu: ['VehicleBasicData', 'VehicleNotes'],
|
||||
menu: [
|
||||
'VehicleBasicData',
|
||||
'VehicleNotes',
|
||||
'VehicleInvoiceIn'],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
@ -195,7 +196,16 @@ const vehicleCard = {
|
|||
icon: 'vn:notes',
|
||||
},
|
||||
component: () => import('src/pages/Route/Vehicle/Card/VehicleNotes.vue'),
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'VehicleInvoiceIn',
|
||||
path: 'invoice-in',
|
||||
meta: {
|
||||
title: 'invoiceIns',
|
||||
icon: 'vn:ticket',
|
||||
},
|
||||
component: () => import('src/pages/Route/Vehicle/Card/VehicleInvoiceIn.vue'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -279,6 +289,7 @@ export default {
|
|||
title: 'RouteRoadmap',
|
||||
icon: 'vn:troncales',
|
||||
},
|
||||
component: () => import('src/pages/Route/RouteRoadmap.vue'),
|
||||
children: [
|
||||
{
|
||||
name: 'RoadmapList',
|
||||
|
@ -310,6 +321,7 @@ export default {
|
|||
title: 'agency',
|
||||
icon: 'garage_home',
|
||||
},
|
||||
component: () => import('src/pages/Route/Agency/AgencyList.vue'),
|
||||
children: [
|
||||
{
|
||||
name: 'AgencyList',
|
||||
|
@ -333,6 +345,7 @@ export default {
|
|||
title: 'vehicle',
|
||||
icon: 'directions_car',
|
||||
},
|
||||
component: () => import('src/pages/Route/Vehicle/VehicleList.vue'),
|
||||
children: [
|
||||
{
|
||||
path: 'list',
|
||||
|
|
|
@ -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,7 @@ describe.skip('Route extended list', () => {
|
|||
date: getSelector('dated'),
|
||||
description: getSelector('description'),
|
||||
served: getSelector('isOk'),
|
||||
id: getSelector('id'),
|
||||
firstRowSelectCheckBox:
|
||||
'tbody > tr:first-child > :nth-child(1) .q-checkbox__inner',
|
||||
lastRowSelectCheckBox: 'tbody > tr:last-child > :nth-child(1) .q-checkbox__inner',
|
||||
|
@ -22,13 +23,18 @@ describe.skip('Route extended list', () => {
|
|||
searchbar: 'searchbar',
|
||||
firstTicketsRowSelectCheckBox:
|
||||
'.q-card .q-table > tbody > :nth-child(1) .q-checkbox',
|
||||
openSummaryBtn: 'tableAction-1',
|
||||
goToSummaryBtn: 'tableAction-2',
|
||||
summaryGoToSummaryBtn: '[data-cy="goToSummaryBtn"]',
|
||||
descriptorSubtitle: '[data-cy="vnDescriptor_subtitle"]',
|
||||
hideRightMenu: 'toggle-right-drawer',
|
||||
};
|
||||
|
||||
const checkboxState = {
|
||||
check: 'check',
|
||||
uncheck: 'close',
|
||||
};
|
||||
const url = '/#/route/extended-list';
|
||||
const summaryUrlRegex = /route\/\d+\/summary/;
|
||||
const dataCreated = 'Data created';
|
||||
const dataSaved = 'Data saved';
|
||||
|
||||
|
@ -45,7 +51,7 @@ describe.skip('Route extended list', () => {
|
|||
{ selector: selectors.worker, type: 'select', value: 'salesperson' },
|
||||
{ selector: selectors.agency, type: 'select', value: 'Super-Man delivery' },
|
||||
{ selector: selectors.vehicle, type: 'select', value: '1111-IMK' },
|
||||
{ selector: selectors.date, type: 'date', value: '11/01/2001' },
|
||||
{ selector: selectors.date, type: 'date', value: '02/02/2001' },
|
||||
{ selector: selectors.description, type: 'input', value: 'Description updated' },
|
||||
{ selector: selectors.served, type: 'checkbox', value: checkboxState.check },
|
||||
];
|
||||
|
@ -76,8 +82,9 @@ describe.skip('Route extended list', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
cy.login('developer');
|
||||
cy.visit(url);
|
||||
cy.visit('/#/route/extended-list');
|
||||
cy.typeSearchbar('{enter}');
|
||||
cy.dataCy(selectors.hideRightMenu).click();
|
||||
});
|
||||
|
||||
it('Should list routes', () => {
|
||||
|
@ -105,7 +112,7 @@ describe.skip('Route extended list', () => {
|
|||
cy.fillInForm(data);
|
||||
|
||||
cy.dataCy(selectors.saveFormBtn).click();
|
||||
cy.url().should('include', '/summary');
|
||||
cy.location().should('match', summaryUrlRegex);
|
||||
cy.checkNotification(dataCreated);
|
||||
});
|
||||
|
||||
|
@ -121,7 +128,7 @@ describe.skip('Route extended list', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('Should clone selected route and add ticket', () => {
|
||||
it('Should clone selected route, add ticket and mark as served', () => {
|
||||
cy.get(selectors.firstRowSelectCheckBox).click();
|
||||
cy.get(selectors.cloneBtn).click();
|
||||
cy.dataCy('Starting date_inputDate').type('01-01-2001');
|
||||
|
@ -133,6 +140,11 @@ describe.skip('Route extended list', () => {
|
|||
cy.get('.q-card__actions > .q-btn--standard > .q-btn__content').click();
|
||||
cy.checkNotification(dataSaved);
|
||||
|
||||
cy.get(selectors.lastRowSelectCheckBox).click();
|
||||
cy.get(selectors.markServedBtn).click();
|
||||
cy.typeSearchbar('{enter}');
|
||||
cy.validateContent(selectors.served, checkboxState.check);
|
||||
|
||||
cy.get(selectors.lastRowSelectCheckBox).click();
|
||||
cy.get(selectors.removeBtn).click();
|
||||
cy.dataCy(selectors.confirmBtn).click();
|
||||
|
@ -148,22 +160,6 @@ describe.skip('Route extended list', () => {
|
|||
cy.readFile(`${downloadsFolder}/${fileName}`).should('exist');
|
||||
});
|
||||
|
||||
it('Should mark as served the selected route', () => {
|
||||
cy.get(selectors.lastRowSelectCheckBox).click();
|
||||
cy.get(selectors.markServedBtn).click();
|
||||
|
||||
cy.typeSearchbar('{enter}');
|
||||
cy.validateContent(selectors.served, checkboxState.check);
|
||||
});
|
||||
|
||||
it('Should delete the selected route', () => {
|
||||
cy.get(selectors.lastRowSelectCheckBox).click();
|
||||
cy.get(selectors.removeBtn).click();
|
||||
cy.dataCy(selectors.confirmBtn).click();
|
||||
|
||||
cy.checkNotification(dataSaved);
|
||||
});
|
||||
|
||||
it('Should save changes in route', () => {
|
||||
updateFields.forEach(({ selector, type, value }) => {
|
||||
fillField(selector, type, value);
|
||||
|
@ -174,28 +170,41 @@ describe.skip('Route extended list', () => {
|
|||
|
||||
cy.typeSearchbar('{enter}');
|
||||
|
||||
updateFields.forEach(({ selector, value, type }) => {
|
||||
if (type === 'date') {
|
||||
const [month, day, year] = value.split('/');
|
||||
value = `${day}/${month}/${year}`;
|
||||
}
|
||||
cy.get(selector).should('contain', value);
|
||||
updateFields.forEach(({ selector, value }) => {
|
||||
cy.validateContent(selector, value);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should open summary pop-up when click summuary icon', () => {
|
||||
cy.dataCy('tableAction-1').last().click();
|
||||
cy.get('.summaryHeader > :nth-child(2').should('contain', updateFields[4].value);
|
||||
it('Should delete the selected route', () => {
|
||||
cy.get(selectors.lastRowSelectCheckBox).click();
|
||||
cy.get(selectors.removeBtn).click();
|
||||
cy.dataCy(selectors.confirmBtn).click();
|
||||
|
||||
cy.checkNotification(dataSaved);
|
||||
});
|
||||
|
||||
it('Should redirect to the summary from the route summary pop-up', () => {
|
||||
cy.dataCy('tableAction-1').last().click();
|
||||
cy.get('.header > .q-icon').should('be.visible').click();
|
||||
cy.url().should('include', '/summary');
|
||||
cy.get(selectors.id)
|
||||
jorgep
commented
Este test y el siguiente son práctimente iguales, crea una fn con el parametro del selector openSummaryBtn y goToSummaryBtn Este test y el siguiente son práctimente iguales, crea una fn con el parametro del selector openSummaryBtn y goToSummaryBtn
jtubau
commented
En cuanto fusione la tarea del vehicleDms (#8442) sustituyo esos test por el comando nuevo que lleva la otra PR En cuanto fusione la tarea del vehicleDms (#8442) sustituyo esos test por el comando nuevo que lleva la otra PR
|
||||
.last()
|
||||
.invoke('text')
|
||||
.then((routeId) => {
|
||||
routeId = routeId.trim();
|
||||
cy.dataCy(selectors.openSummaryBtn).last().click();
|
||||
cy.get(selectors.summaryGoToSummaryBtn).should('be.visible').click();
|
||||
cy.location().should('match', summaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorSubtitle, routeId);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should redirect to the summary when click go to summary icon', () => {
|
||||
cy.dataCy('tableAction-2').last().click();
|
||||
cy.url().should('include', '/summary');
|
||||
cy.get(selectors.id)
|
||||
.last()
|
||||
.invoke('text')
|
||||
.then((routeId) => {
|
||||
routeId = routeId.trim();
|
||||
cy.dataCy(selectors.goToSummaryBtn).last().click();
|
||||
cy.location().should('match', summaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorSubtitle, routeId);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
describe('Vehicle Invoice In', () => {
|
||||
const getLinkSelector = (colField) =>
|
||||
jtubau marked this conversation as resolved
Outdated
jorgep
commented
getLinkSelector getLinkSelector
|
||||
`tr:first-child > [data-col-field="${colField}"] > .no-padding > .link`;
|
||||
const selectors = {
|
||||
firstRowSupplier: getLinkSelector('supplierFk'),
|
||||
firstRowInvoice: getLinkSelector('supplierRef'),
|
||||
descriptorSupplierTitle: '[data-cy="vnDescriptor_description"]',
|
||||
descriptorInvoiceInTitle: '[data-cy="vnDescriptor_title"]',
|
||||
descriptorOpenSummaryBtn: '.q-menu > .descriptor [data-cy="openSummaryBtn"]',
|
||||
descriptorGoToSummaryBtn: '.q-menu > .descriptor [data-cy="goToSummaryBtn"]',
|
||||
summaryGoToSummaryBtn: '.summaryHeader [data-cy="goToSummaryBtn"]',
|
||||
unassignBtn: 'tableAction-0',
|
||||
};
|
||||
|
||||
const supplierSummaryUrlRegex = /supplier\/\d+\/summary/;
|
||||
const invoiceInSummaryUrlRegex = /invoice-in\/\d+\/summary/;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('deliveryAssistant');
|
||||
cy.visit(`/#/route/vehicle/1/invoice-in`);
|
||||
});
|
||||
|
||||
it('Should show assigned tickets', () => {
|
||||
cy.get('.q-table')
|
||||
.children()
|
||||
.should('be.visible')
|
||||
.should('have.length.greaterThan', 0);
|
||||
});
|
||||
|
||||
it('Should assign a new invoice', () => {
|
||||
const data = {
|
||||
'Invoice nº': { val: '1243', type: 'select' },
|
||||
Amount: { val: '1000' },
|
||||
};
|
||||
cy.addBtnClick();
|
||||
cy.fillInForm(data);
|
||||
cy.dataCy('FormModelPopup_save').click();
|
||||
cy.checkNotification('Data created');
|
||||
});
|
||||
|
||||
it('Should unassign an invoice', () => {
|
||||
cy.dataCy(selectors.unassignBtn).last().click();
|
||||
cy.clickConfirm();
|
||||
cy.checkNotification('Unlinked invoice');
|
||||
});
|
||||
|
||||
describe('Supplier pop-ups', () => {
|
||||
jtubau marked this conversation as resolved
Outdated
jorgep
commented
Creo que con validar que se abra el popup es suficiente. Creo que con validar que se abra el popup es suficiente.
|
||||
it('Should redirect to the supplier summary from the supplier descriptor pop-up', () => {
|
||||
cy.get(selectors.firstRowSupplier)
|
||||
.click()
|
||||
.invoke('text')
|
||||
.then((supplierName) => {
|
||||
supplierName = supplierName.trim();
|
||||
cy.get(selectors.descriptorGoToSummaryBtn)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.location().should('match', supplierSummaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorSupplierTitle, supplierName);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should redirect to the supplier summary from summary pop-up from the supplier descriptor pop-up', () => {
|
||||
cy.get(selectors.firstRowSupplier)
|
||||
.click()
|
||||
.invoke('text')
|
||||
.then((supplierName) => {
|
||||
supplierName = supplierName.trim();
|
||||
jtubau marked this conversation as resolved
Outdated
jorgep
commented
Creo que con validar que se abra el popup es suficiente. Creo que con validar que se abra el popup es suficiente.
|
||||
cy.get(selectors.descriptorOpenSummaryBtn)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.get(selectors.summaryGoToSummaryBtn).should('be.visible').click();
|
||||
jtubau marked this conversation as resolved
Outdated
jorgep
commented
guardar en variable con nombre descriptivo o usasr data-cy guardar en variable con nombre descriptivo o usasr data-cy
|
||||
cy.location().should('match', supplierSummaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorSupplierTitle, supplierName);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Invoice pop-ups', () => {
|
||||
it('Should redirect to the invoiceIn summary from the invoice descriptor pop-up', () => {
|
||||
cy.get(selectors.firstRowInvoice)
|
||||
.click()
|
||||
.invoke('text')
|
||||
.then((invoice) => {
|
||||
invoice = invoice.trim();
|
||||
cy.get(selectors.descriptorGoToSummaryBtn)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.location().should('match', invoiceInSummaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorInvoiceInTitle, invoice);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should redirect to the invoiceIn summary from summary pop-up from the invoice descriptor pop-up', () => {
|
||||
cy.get(selectors.firstRowInvoice)
|
||||
.click()
|
||||
.invoke('text')
|
||||
.then((invoice) => {
|
||||
invoice = invoice.trim();
|
||||
cy.get(selectors.descriptorOpenSummaryBtn)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.get(selectors.summaryGoToSummaryBtn).should('be.visible').click();
|
||||
cy.location().should('match', invoiceInSummaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorInvoiceInTitle, invoice);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,16 +1,16 @@
|
|||
describe('Vehicle list', () => {
|
||||
const selectors = {
|
||||
saveFormBtn: 'FormModelPopup_save',
|
||||
descriptorTitle: '[data-cy="vnDescriptor_title"]',
|
||||
summaryPopupBtn: 'tr:last-child > .q-table--col-auto-width > .q-btn',
|
||||
summaryGoToSummaryBtn: '.header > .q-icon',
|
||||
summaryHeader: '.summaryHeader > div',
|
||||
summaryGoToSummaryBtn: '[data-cy="goToSummaryBtn"]',
|
||||
numberPlate: 'tr:last-child > [data-col-field="numberPlate"] > .no-padding',
|
||||
};
|
||||
|
||||
const data = {
|
||||
'Nº Plate': { val: '9465-LPA' },
|
||||
'Trade Mark': { val: 'WAYNE INDUSTRIES' },
|
||||
Model: { val: 'BATREMOLQUE' },
|
||||
Model: { val: 'BATHAUL' },
|
||||
Type: { val: 'remolque', type: 'select' },
|
||||
Warehouse: { val: 'Warehouse One', type: 'select' },
|
||||
Country: { val: 'Portugal', type: 'select' },
|
||||
|
@ -18,7 +18,7 @@ describe('Vehicle list', () => {
|
|||
};
|
||||
|
||||
const expected = data['Nº Plate'].val;
|
||||
const summaryUrl = '/summary';
|
||||
const summaryUrlRegex = /vehicle\/\d+\/summary/;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login('developer');
|
||||
|
@ -34,25 +34,42 @@ describe('Vehicle list', () => {
|
|||
});
|
||||
|
||||
it('Should add new vehicle', () => {
|
||||
cy.intercept('POST', '/api/Vehicles').as('postRequest');
|
||||
cy.addBtnClick();
|
||||
cy.fillInForm(data);
|
||||
cy.dataCy(selectors.saveFormBtn).should('be.visible').click();
|
||||
|
||||
cy.checkNotification('Data created');
|
||||
cy.get(selectors.summaryHeader).should('contain', expected);
|
||||
cy.url().should('include', summaryUrl);
|
||||
cy.wait('@postRequest').then((interception) => {
|
||||
expect(interception.response.statusCode).to.eq(200);
|
||||
cy.url().should(
|
||||
'include',
|
||||
`vehicle/${interception.response.body.id}/summary`,
|
||||
);
|
||||
});
|
||||
|
||||
cy.containContent(selectors.descriptorTitle, expected);
|
||||
});
|
||||
|
||||
it('should open summary by clicking a vehicle', () => {
|
||||
jorgep
commented
Este test y el siguiente son práctimente iguales, crea una fn con el parametro del selector openSummaryBtn y goToSummaryBtn. Este test y el siguiente son práctimente iguales, crea una fn con el parametro del selector openSummaryBtn y goToSummaryBtn.
|
||||
cy.get(selectors.numberPlate).click();
|
||||
cy.get(selectors.summaryHeader).should('contain', expected);
|
||||
cy.url().should('include', summaryUrl);
|
||||
cy.get(selectors.numberPlate)
|
||||
.click()
|
||||
.invoke('text')
|
||||
.then((numberPlate) => {
|
||||
numberPlate = numberPlate.trim();
|
||||
cy.location().should('match', summaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorTitle, numberPlate);
|
||||
});
|
||||
});
|
||||
|
||||
it('should redirect to vehicle summary when click summary icon on summary pop-up', () => {
|
||||
cy.get(selectors.summaryPopupBtn).click();
|
||||
cy.get(selectors.summaryHeader).should('contain', expected);
|
||||
cy.get(selectors.summaryGoToSummaryBtn).click();
|
||||
cy.url().should('include', summaryUrl);
|
||||
cy.get(selectors.numberPlate)
|
||||
.invoke('text')
|
||||
.then((numberPlate) => {
|
||||
numberPlate = numberPlate.trim();
|
||||
cy.get(selectors.summaryPopupBtn).click();
|
||||
cy.get(selectors.summaryGoToSummaryBtn).click();
|
||||
cy.location().should('match', summaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorTitle, numberPlate);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
describe('Vehicle summary', () => {
|
||||
jtubau marked this conversation as resolved
jorgep
commented
Pasar a data-cy. Pasar a data-cy.
|
||||
const selectors = {
|
||||
summaryTitle: '.summaryHeader',
|
||||
descriptorTitle: '.q-item__label--header > .title > span',
|
||||
summaryAssignedInvoicesLink: '.vn-max > .q-pb-lg > .header-link > .link',
|
||||
summaryBasicDataLink: '[dense=""] > .q-pb-lg > .header-link > .link',
|
||||
basicDataSupplierLink: ':nth-child(4) > .value > .link',
|
||||
assignedInvoicesSupplierLink: 'tbody > :nth-child(1) > :nth-child(2) > .link',
|
||||
assignedInvoicesInvoiceLink: 'tbody > :nth-child(1) > :nth-child(3) > .link',
|
||||
descriptorOpenSummaryBtn: '.q-menu > .descriptor [data-cy="openSummaryBtn"]',
|
||||
descriptorGoToSummaryBtn: '.q-menu > .descriptor [data-cy="goToSummaryBtn"]',
|
||||
summaryGoToSummaryBtn: '.summaryHeader [data-cy="goToSummaryBtn"]',
|
||||
};
|
||||
|
||||
const vehiclePlate = '3333-BAT';
|
||||
const supplierSummaryUrlRegex = /supplier\/\d+\/summary/;
|
||||
const invoiceInSummaryUrlRegex = /invoice-in\/\d+\/summary/;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('deliveryAssistant');
|
||||
cy.visit(`/#/route/vehicle/1/summary`);
|
||||
});
|
||||
it('Should load summary', () => {
|
||||
cy.containContent(selectors.summaryTitle, vehiclePlate);
|
||||
cy.containContent(selectors.descriptorTitle, vehiclePlate);
|
||||
});
|
||||
|
||||
it('Should redirect to vehicle basic-data', () => {
|
||||
cy.get(selectors.summaryBasicDataLink).click();
|
||||
cy.url().should('include', '/vehicle/1/basic-data');
|
||||
});
|
||||
|
||||
it('Should redirect to vehicle invoice-ins', () => {
|
||||
cy.get(selectors.summaryAssignedInvoicesLink).click();
|
||||
cy.url().should('include', '/vehicle/1/invoice-in');
|
||||
});
|
||||
|
||||
describe('Supplier basic data pop-ups', () => {
|
||||
it('Should redirect to the supplier summary from the supplier descriptor pop-up', () => {
|
||||
cy.get(selectors.basicDataSupplierLink)
|
||||
.click()
|
||||
.invoke('text')
|
||||
.then((supplierName) => {
|
||||
supplierName = supplierName.trim();
|
||||
cy.get(selectors.descriptorGoToSummaryBtn)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.url().should('match', supplierSummaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorTitle, supplierName);
|
||||
});
|
||||
});
|
||||
|
||||
jtubau marked this conversation as resolved
Outdated
jorgep
commented
Con que lo abra es suficiente. Con que lo abra es suficiente.
|
||||
it('Should redirect to the supplier summary from summary pop-up from the supplier descriptor pop-up', () => {
|
||||
cy.get(selectors.basicDataSupplierLink)
|
||||
.click()
|
||||
.invoke('text')
|
||||
.then((supplierName) => {
|
||||
supplierName = supplierName.trim();
|
||||
cy.get(selectors.descriptorOpenSummaryBtn)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.get(selectors.summaryGoToSummaryBtn).should('be.visible').click();
|
||||
cy.url().should('match', supplierSummaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorTitle, supplierName);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Supplier assigned invoices pop-ups', () => {
|
||||
it('Should redirect to the supplier summary from the invoice descriptor pop-up', () => {
|
||||
cy.get(selectors.assignedInvoicesSupplierLink)
|
||||
.click()
|
||||
jtubau marked this conversation as resolved
Outdated
jorgep
commented
Con que lo abra es suficiente Con que lo abra es suficiente
|
||||
.invoke('text')
|
||||
.then((supplierName) => {
|
||||
supplierName = supplierName.trim();
|
||||
cy.get(selectors.descriptorGoToSummaryBtn)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.url().should('match', supplierSummaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorTitle, supplierName);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should redirect to the supplier summary from summary pop-up from the supplier descriptor pop-up', () => {
|
||||
cy.get(selectors.assignedInvoicesSupplierLink)
|
||||
.click()
|
||||
.invoke('text')
|
||||
.then((supplierName) => {
|
||||
supplierName = supplierName.trim();
|
||||
cy.get(selectors.descriptorOpenSummaryBtn)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.get(selectors.summaryGoToSummaryBtn).should('be.visible').click();
|
||||
cy.url().should('match', supplierSummaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorTitle, supplierName);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// redmine: #8872
|
||||
describe.skip('Invoice assigned invoices pop-ups', () => {
|
||||
it('Should redirect to the invoiceIn summary from the invoice descriptor pop-up', () => {
|
||||
cy.get(selectors.assignedInvoicesInvoiceLink)
|
||||
.should('be.visible')
|
||||
.click()
|
||||
.invoke('text')
|
||||
.then((invoice) => {
|
||||
invoice = invoice.trim();
|
||||
cy.get(selectors.descriptorGoToSummaryBtn)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.url().should('match', invoiceInSummaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorTitle, invoice);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should redirect to the invoiceIn summary from summary pop-up from the invoice descriptor pop-up', () => {
|
||||
cy.get(selectors.assignedInvoicesInvoiceLink)
|
||||
.should('be.visible')
|
||||
.click()
|
||||
.invoke('text')
|
||||
.then((invoice) => {
|
||||
invoice = invoice.trim();
|
||||
cy.get(selectors.descriptorOpenSummaryBtn)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.get(selectors.summaryGoToSummaryBtn).should('be.visible').click();
|
||||
cy.url().should('match', invoiceInSummaryUrlRegex);
|
||||
cy.containContent(selectors.descriptorTitle, invoice);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Si falla el delete mostrará la notificación de dataSaved Haz algo así:
async () => { try { await axios.delete(
Vehicles/${entity.id}); notify('vehicle.remove', 'positive'); $router.push({ name: 'VehicleList' }); } catch (e) { throw e; } }