Reviewed-on: #1452 Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
commit
25fce95265
src
components
VnTable
common
ui
pages/InvoiceIn
test/cypress
|
@ -140,7 +140,7 @@ const $props = defineProps({
|
|||
},
|
||||
dataCy: {
|
||||
type: String,
|
||||
default: 'vn-table',
|
||||
default: 'vnTable',
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -684,7 +684,7 @@ const rowCtrlClickFunction = computed(() => {
|
|||
@update:selected="emit('update:selected', $event)"
|
||||
@selection="(details) => handleSelection(details, rows)"
|
||||
:hide-selected-banner="true"
|
||||
:data-cy="$props.dataCy ?? 'vnTable'"
|
||||
:data-cy
|
||||
>
|
||||
<template #top-left v-if="!$props.withoutHeader">
|
||||
<slot name="top-left"> </slot>
|
||||
|
@ -781,6 +781,7 @@ const rowCtrlClickFunction = computed(() => {
|
|||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
"
|
||||
:data-cy="`vnTableCell_${col.name}`"
|
||||
>
|
||||
<slot
|
||||
:name="`column-${col.name}`"
|
||||
|
|
|
@ -27,7 +27,11 @@ const checkboxModel = computed({
|
|||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<QCheckbox v-bind="$attrs" v-model="checkboxModel" />
|
||||
<QCheckbox
|
||||
v-bind="$attrs"
|
||||
v-model="checkboxModel"
|
||||
:data-cy="$attrs['data-cy'] ?? `vnCheckbox${$attrs['label'] ?? ''}`"
|
||||
/>
|
||||
<QIcon
|
||||
v-if="info"
|
||||
v-bind="$attrs"
|
||||
|
|
|
@ -107,7 +107,7 @@ const manageDate = (date) => {
|
|||
@click="isPopupOpen = !isPopupOpen"
|
||||
@keydown="isPopupOpen = false"
|
||||
hide-bottom-space
|
||||
:data-cy="$attrs.dataCy ?? $attrs.label + '_inputDate'"
|
||||
:data-cy="($attrs['data-cy'] ?? $attrs.label) + '_inputDate'"
|
||||
>
|
||||
<template #append>
|
||||
<QIcon
|
||||
|
|
|
@ -151,7 +151,7 @@ const toModule = computed(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="descriptor">
|
||||
<div class="descriptor" data-cy="cardDescriptor">
|
||||
<template v-if="entity && !isLoading">
|
||||
<div class="header bg-primary q-pa-sm justify-between">
|
||||
<slot name="header-extra-action">
|
||||
|
@ -213,18 +213,27 @@ const toModule = computed(() => {
|
|||
<QList dense>
|
||||
<QItemLabel header class="ellipsis text-h5" :lines="1">
|
||||
<div class="title">
|
||||
<span v-if="$props.title" :title="getValueFromPath(title)">
|
||||
<span
|
||||
v-if="$props.title"
|
||||
:title="getValueFromPath(title)"
|
||||
:data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_title`"
|
||||
>
|
||||
{{ getValueFromPath(title) ?? $props.title }}
|
||||
</span>
|
||||
<slot v-else name="description" :entity="entity">
|
||||
<span :title="entity.name">
|
||||
{{ entity.name }}
|
||||
</span>
|
||||
<span
|
||||
:title="entity.name"
|
||||
:data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_description`"
|
||||
v-text="entity.name"
|
||||
/>
|
||||
</slot>
|
||||
</div>
|
||||
</QItemLabel>
|
||||
<QItem>
|
||||
<QItemLabel class="subtitle" data-cy="descriptor_id">
|
||||
<QItemLabel
|
||||
class="subtitle"
|
||||
:data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_subtitle`"
|
||||
>
|
||||
#{{ getValueFromPath(subtitle) ?? entity.id }}
|
||||
</QItemLabel>
|
||||
<QBtn
|
||||
|
@ -242,7 +251,10 @@ const toModule = computed(() => {
|
|||
</QBtn>
|
||||
</QItem>
|
||||
</QList>
|
||||
<div class="list-box q-mt-xs">
|
||||
<div
|
||||
class="list-box q-mt-xs"
|
||||
:data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_listbox`"
|
||||
>
|
||||
<slot name="body" :entity="entity" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -249,7 +249,7 @@ const getLocale = (label) => {
|
|||
:key="chip.label"
|
||||
:removable="!unremovableParams?.includes(chip.label)"
|
||||
@remove="remove(chip.label)"
|
||||
data-cy="vnFilterPanelChip"
|
||||
:data-cy="`vnFilterPanelChip_${chip.label}`"
|
||||
>
|
||||
<slot
|
||||
name="tags"
|
||||
|
|
|
@ -28,7 +28,7 @@ function copyValueText() {
|
|||
const val = computed(() => $props.value);
|
||||
</script>
|
||||
<template>
|
||||
<div class="vn-label-value">
|
||||
<div class="vn-label-value" :data-cy="`${$attrs['data-cy'] ?? 'vnLv'}${label ?? ''}`">
|
||||
<QCheckbox
|
||||
v-if="typeof value === 'boolean'"
|
||||
v-model="val"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
{{ $t('components.cardDescriptor.moreOptions') }}
|
||||
</QTooltip>
|
||||
<QMenu ref="menuRef" data-cy="descriptor-more-opts-menu">
|
||||
<QList>
|
||||
<QList data-cy="descriptor-more-opts_list">
|
||||
<slot name="menu" :menu-ref="$refs.menuRef" />
|
||||
</QList>
|
||||
</QMenu>
|
||||
|
|
|
@ -121,25 +121,40 @@ function deleteFile(dmsFk) {
|
|||
hide-selected
|
||||
:is-clearable="false"
|
||||
:required="true"
|
||||
data-cy="invoiceInBasicDataSupplier"
|
||||
/>
|
||||
<VnInput
|
||||
clearable
|
||||
clear-icon="close"
|
||||
:label="t('invoiceIn.supplierRef')"
|
||||
v-model="data.supplierRef"
|
||||
data-cy="invoiceInBasicDataSupplierRef"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInputDate :label="t('Expedition date')" v-model="data.issued" />
|
||||
<VnInputDate
|
||||
:label="t('Expedition date')"
|
||||
v-model="data.issued"
|
||||
data-cy="invoiceInBasicDataIssued"
|
||||
/>
|
||||
<VnInputDate
|
||||
:label="t('Operation date')"
|
||||
v-model="data.operated"
|
||||
autofocus
|
||||
data-cy="invoiceInBasicDataOperated"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInputDate :label="t('Entry date')" v-model="data.bookEntried" />
|
||||
<VnInputDate :label="t('Accounted date')" v-model="data.booked" />
|
||||
<VnInputDate
|
||||
:label="t('Entry date')"
|
||||
v-model="data.bookEntried"
|
||||
data-cy="invoiceInBasicDatabookEntried"
|
||||
/>
|
||||
<VnInputDate
|
||||
:label="t('Accounted date')"
|
||||
v-model="data.booked"
|
||||
data-cy="invoiceInBasicDataBooked"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
|
@ -149,7 +164,7 @@ function deleteFile(dmsFk) {
|
|||
option-value="id"
|
||||
option-label="id"
|
||||
:filter-options="['id', 'name']"
|
||||
data-cy="UnDeductibleVatSelect"
|
||||
data-cy="invoiceInBasicDataDeductibleExpenseFk"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
|
@ -182,6 +197,7 @@ function deleteFile(dmsFk) {
|
|||
padding="xs"
|
||||
round
|
||||
@click="downloadFile(data.dmsFk)"
|
||||
data-cy="invoiceInBasicDataDmsDownload"
|
||||
/>
|
||||
<QBtn
|
||||
:class="{
|
||||
|
@ -197,6 +213,7 @@ function deleteFile(dmsFk) {
|
|||
documentDialogRef.dms = data.dms;
|
||||
}
|
||||
"
|
||||
data-cy="invoiceInBasicDataDmsEdit"
|
||||
>
|
||||
<QTooltip>{{ t('Edit document') }}</QTooltip>
|
||||
</QBtn>
|
||||
|
@ -210,6 +227,7 @@ function deleteFile(dmsFk) {
|
|||
padding="xs"
|
||||
round
|
||||
@click="deleteFile(data.dmsFk)"
|
||||
data-cy="invoiceInBasicDataDmsDelete"
|
||||
/>
|
||||
</div>
|
||||
<QBtn
|
||||
|
@ -224,7 +242,7 @@ function deleteFile(dmsFk) {
|
|||
delete documentDialogRef.dms;
|
||||
}
|
||||
"
|
||||
data-cy="dms-create"
|
||||
data-cy="invoiceInBasicDataDmsAdd"
|
||||
>
|
||||
<QTooltip>{{ t('Create document') }}</QTooltip>
|
||||
</QBtn>
|
||||
|
@ -237,9 +255,9 @@ function deleteFile(dmsFk) {
|
|||
:label="t('Currency')"
|
||||
v-model="data.currencyFk"
|
||||
:options="currencies"
|
||||
option-value="id"
|
||||
option-label="code"
|
||||
sort-by="id"
|
||||
data-cy="invoiceInBasicDataCurrencyFk"
|
||||
/>
|
||||
|
||||
<VnSelect
|
||||
|
@ -249,8 +267,8 @@ function deleteFile(dmsFk) {
|
|||
:label="t('Company')"
|
||||
v-model="data.companyFk"
|
||||
:options="companies"
|
||||
option-value="id"
|
||||
option-label="code"
|
||||
data-cy="invoiceInBasicDataCompanyFk"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
|
@ -260,6 +278,7 @@ function deleteFile(dmsFk) {
|
|||
:options="sageWithholdings"
|
||||
option-value="id"
|
||||
option-label="withholding"
|
||||
data-cy="invoiceInBasicDataWithholdingSageFk"
|
||||
/>
|
||||
</VnRow>
|
||||
</template>
|
||||
|
|
|
@ -1,22 +1,16 @@
|
|||
<script setup>
|
||||
import { ref, computed, capitalize } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import CrudModel from 'src/components/CrudModel.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
||||
const arrayData = useArrayData();
|
||||
const invoiceIn = computed(() => arrayData.store.data);
|
||||
const invoiceInCorrectionRef = ref();
|
||||
const filter = {
|
||||
include: { relation: 'invoiceIn' },
|
||||
where: { correctingFk: route.params.id },
|
||||
};
|
||||
const columns = computed(() => [
|
||||
{
|
||||
name: 'origin',
|
||||
|
@ -92,7 +86,8 @@ const requiredFieldRule = (val) => val || t('globals.requiredField');
|
|||
v-if="invoiceIn"
|
||||
data-key="InvoiceInCorrection"
|
||||
url="InvoiceInCorrections"
|
||||
:filter="filter"
|
||||
:user-filter="{ include: { relation: 'invoiceIn' } }"
|
||||
:filter="{ where: { correctingFk: $route.params.id } }"
|
||||
auto-load
|
||||
primary-key="correctingFk"
|
||||
:default-remove="false"
|
||||
|
@ -115,6 +110,7 @@ const requiredFieldRule = (val) => val || t('globals.requiredField');
|
|||
:option-label="col.optionLabel"
|
||||
:disable="row.invoiceIn.isBooked"
|
||||
:filter-options="['description']"
|
||||
data-cy="invoiceInCorrective_type"
|
||||
>
|
||||
<template #option="{ opt, itemProps }">
|
||||
<QItem v-bind="itemProps">
|
||||
|
@ -137,6 +133,7 @@ const requiredFieldRule = (val) => val || t('globals.requiredField');
|
|||
:rules="[requiredFieldRule]"
|
||||
:filter-options="['code', 'description']"
|
||||
:disable="row.invoiceIn.isBooked"
|
||||
data-cy="invoiceInCorrective_class"
|
||||
>
|
||||
<template #option="{ opt, itemProps }">
|
||||
<QItem v-bind="itemProps">
|
||||
|
@ -161,6 +158,7 @@ const requiredFieldRule = (val) => val || t('globals.requiredField');
|
|||
:option-label="col.optionLabel"
|
||||
:rules="[requiredFieldRule]"
|
||||
:disable="row.invoiceIn.isBooked"
|
||||
data-cy="invoiceInCorrective_reason"
|
||||
/>
|
||||
</QTd>
|
||||
</template>
|
||||
|
|
|
@ -17,10 +17,6 @@ const { t } = useI18n();
|
|||
const cardDescriptorRef = ref();
|
||||
const entityId = computed(() => $props.id || +currentRoute.value.params.id);
|
||||
const totalAmount = ref();
|
||||
const config = ref();
|
||||
const cplusRectificationTypes = ref([]);
|
||||
const siiTypeInvoiceIns = ref([]);
|
||||
const invoiceCorrectionTypes = ref([]);
|
||||
const invoiceInCorrection = reactive({ correcting: [], corrected: null });
|
||||
const routes = reactive({
|
||||
getSupplier: (id) => {
|
||||
|
@ -30,7 +26,7 @@ const routes = reactive({
|
|||
return {
|
||||
name: 'InvoiceInList',
|
||||
query: {
|
||||
params: JSON.stringify({ supplierFk: id }),
|
||||
table: JSON.stringify({ supplierFk: id }),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
@ -39,7 +35,7 @@ const routes = reactive({
|
|||
return {
|
||||
name: 'InvoiceInList',
|
||||
query: {
|
||||
params: JSON.stringify({ correctedFk: entityId.value }),
|
||||
table: JSON.stringify({ correctedFk: entityId.value }),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -108,7 +104,7 @@ async function setInvoiceCorrection(id) {
|
|||
<VnLv :label="t('invoiceIn.list.amount')" :value="toCurrency(totalAmount)" />
|
||||
<VnLv :label="t('invoiceIn.list.supplier')">
|
||||
<template #value>
|
||||
<span class="link">
|
||||
<span class="link" data-cy="invoiceInDescriptor_supplier">
|
||||
{{ entity?.supplier?.nickname }}
|
||||
<SupplierDescriptorProxy :id="entity?.supplierFk" />
|
||||
</span>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { ref, computed, toRefs, reactive } from 'vue';
|
||||
import { ref, computed, toRefs, reactive, onBeforeMount } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
|
@ -111,10 +111,9 @@ async function cloneInvoice() {
|
|||
}
|
||||
|
||||
const isAgricultural = () => {
|
||||
if (!config.value) return false;
|
||||
return (
|
||||
invoiceIn.value?.supplier?.sageFarmerWithholdingFk ===
|
||||
config?.value[0]?.sageWithholdingFk
|
||||
invoiceIn.value?.supplier?.sageWithholdingFk ==
|
||||
config.value?.sageFarmerWithholdingFk
|
||||
);
|
||||
};
|
||||
function showPdfInvoice() {
|
||||
|
@ -153,162 +152,183 @@ const createInvoiceInCorrection = async () => {
|
|||
);
|
||||
push({ path: `/invoice-in/${correctingId}/summary` });
|
||||
};
|
||||
|
||||
onBeforeMount(async () => {
|
||||
config.value = (
|
||||
await axios.get('invoiceinConfigs/findOne', {
|
||||
params: { fields: ['sageFarmerWithholdingFk'] },
|
||||
})
|
||||
).data;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="InvoiceCorrectionTypes"
|
||||
@on-fetch="(data) => (invoiceCorrectionTypes = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="CplusRectificationTypes"
|
||||
@on-fetch="(data) => (cplusRectificationTypes = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="SiiTypeInvoiceIns"
|
||||
:where="{ code: { like: 'R%' } }"
|
||||
@on-fetch="(data) => (siiTypeInvoiceIns = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="InvoiceInConfigs"
|
||||
:where="{ fields: ['sageWithholdingFk'] }"
|
||||
auto-load
|
||||
@on-fetch="(data) => (config = data)"
|
||||
/>
|
||||
<InvoiceInToBook>
|
||||
<template #content="{ book }">
|
||||
<QItem
|
||||
v-if="!invoice?.isBooked && canEditProp('toBook')"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="book(entityId)"
|
||||
<template v-if="config">
|
||||
<FetchData
|
||||
url="InvoiceCorrectionTypes"
|
||||
@on-fetch="(data) => (invoiceCorrectionTypes = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="CplusRectificationTypes"
|
||||
@on-fetch="(data) => (cplusRectificationTypes = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="SiiTypeInvoiceIns"
|
||||
:where="{ code: { like: 'R%' } }"
|
||||
@on-fetch="(data) => (siiTypeInvoiceIns = data)"
|
||||
auto-load
|
||||
/>
|
||||
<InvoiceInToBook>
|
||||
<template #content="{ book }">
|
||||
<QItem
|
||||
v-if="!invoice?.isBooked && canEditProp('toBook')"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="book(entityId)"
|
||||
>
|
||||
<QItemSection>{{ t('invoiceIn.descriptorMenu.book') }}</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</InvoiceInToBook>
|
||||
<QItem
|
||||
v-if="invoice?.isBooked && canEditProp('toUnbook')"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="triggerMenu('unbook')"
|
||||
>
|
||||
<QItemSection>
|
||||
{{ t('invoiceIn.descriptorMenu.unbook') }}
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="canEditProp('deleteById')"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="triggerMenu('delete')"
|
||||
>
|
||||
<QItemSection>{{ t('invoiceIn.descriptorMenu.deleteInvoice') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="canEditProp('clone')"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="triggerMenu('clone')"
|
||||
>
|
||||
<QItemSection>{{ t('invoiceIn.descriptorMenu.cloneInvoice') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('showPdf')">
|
||||
<QItemSection>{{
|
||||
t('invoiceIn.descriptorMenu.showAgriculturalPdf')
|
||||
}}</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('sendPdf')">
|
||||
<QItemSection
|
||||
>{{ t('invoiceIn.descriptorMenu.sendAgriculturalPdf') }}...</QItemSection
|
||||
>
|
||||
<QItemSection>{{ t('invoiceIn.descriptorMenu.book') }}</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</InvoiceInToBook>
|
||||
<QItem
|
||||
v-if="invoice?.isBooked && canEditProp('toUnbook')"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="triggerMenu('unbook')"
|
||||
>
|
||||
<QItemSection>
|
||||
{{ t('invoiceIn.descriptorMenu.unbook') }}
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="canEditProp('deleteById')"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="triggerMenu('delete')"
|
||||
>
|
||||
<QItemSection>{{ t('invoiceIn.descriptorMenu.deleteInvoice') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-if="canEditProp('clone')" v-ripple clickable @click="triggerMenu('clone')">
|
||||
<QItemSection>{{ t('invoiceIn.descriptorMenu.cloneInvoice') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('showPdf')">
|
||||
<QItemSection>{{
|
||||
t('invoiceIn.descriptorMenu.showAgriculturalPdf')
|
||||
}}</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('sendPdf')">
|
||||
<QItemSection
|
||||
>{{ t('invoiceIn.descriptorMenu.sendAgriculturalPdf') }}...</QItemSection
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="!invoiceInCorrection.corrected"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="triggerMenu('correct')"
|
||||
data-cy="createCorrectiveItem"
|
||||
>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="!invoiceInCorrection.corrected"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="triggerMenu('correct')"
|
||||
data-cy="createCorrectiveItem"
|
||||
>
|
||||
<QItemSection
|
||||
>{{ t('invoiceIn.descriptorMenu.createCorrective') }}...</QItemSection
|
||||
<QItemSection
|
||||
>{{ t('invoiceIn.descriptorMenu.createCorrective') }}...</QItemSection
|
||||
>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="invoice.dmsFk"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="downloadFile(invoice.dmsFk)"
|
||||
>
|
||||
</QItem>
|
||||
<QItem v-if="invoice.dmsFk" v-ripple clickable @click="downloadFile(invoice.dmsFk)">
|
||||
<QItemSection>{{ t('components.smartCard.downloadFile') }}</QItemSection>
|
||||
</QItem>
|
||||
<QDialog ref="correctionDialogRef">
|
||||
<QCard>
|
||||
<QCardSection>
|
||||
<QItem class="q-px-none">
|
||||
<span class="text-primary text-h6 full-width">
|
||||
{{ t('Create rectificative invoice') }}
|
||||
</span>
|
||||
<QBtn icon="close" flat round dense v-close-popup />
|
||||
</QItem>
|
||||
</QCardSection>
|
||||
<QCardSection>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<QInput
|
||||
:label="t('Original invoice')"
|
||||
v-model="entityId"
|
||||
readonly
|
||||
/>
|
||||
<VnSelect
|
||||
:label="`${useCapitalize(t('globals.class'))}`"
|
||||
v-model="correctionFormData.invoiceClass"
|
||||
:options="siiTypeInvoiceIns"
|
||||
option-value="id"
|
||||
option-label="code"
|
||||
:required="true"
|
||||
/>
|
||||
</QItemSection>
|
||||
<QItemSection>
|
||||
<VnSelect
|
||||
:label="`${useCapitalize(t('globals.type'))}`"
|
||||
v-model="correctionFormData.invoiceType"
|
||||
:options="cplusRectificationTypes"
|
||||
option-value="id"
|
||||
option-label="description"
|
||||
:required="true"
|
||||
>
|
||||
<template #option="{ itemProps, opt }">
|
||||
<QItem v-bind="itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel
|
||||
>{{ opt.id }} -
|
||||
{{ opt.description }}</QItemLabel
|
||||
>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<div></div>
|
||||
</template>
|
||||
</VnSelect>
|
||||
<QItemSection>{{ t('components.smartCard.downloadFile') }}</QItemSection>
|
||||
</QItem>
|
||||
<QDialog ref="correctionDialogRef">
|
||||
<QCard data-cy="correctiveInvoiceDialog">
|
||||
<QCardSection>
|
||||
<QItem class="q-px-none">
|
||||
<span class="text-primary text-h6 full-width">
|
||||
{{ t('Create rectificative invoice') }}
|
||||
</span>
|
||||
<QBtn icon="close" flat round dense v-close-popup />
|
||||
</QItem>
|
||||
</QCardSection>
|
||||
<QCardSection>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<QInput
|
||||
:label="t('Original invoice')"
|
||||
v-model="entityId"
|
||||
readonly
|
||||
/>
|
||||
<VnSelect
|
||||
:label="`${useCapitalize(t('globals.class'))}`"
|
||||
v-model="correctionFormData.invoiceClass"
|
||||
:options="siiTypeInvoiceIns"
|
||||
option-value="id"
|
||||
option-label="code"
|
||||
:required="true"
|
||||
data-cy="invoiceInDescriptorMenu_class"
|
||||
/>
|
||||
</QItemSection>
|
||||
<QItemSection>
|
||||
<VnSelect
|
||||
:label="`${useCapitalize(t('globals.type'))}`"
|
||||
v-model="correctionFormData.invoiceType"
|
||||
:options="cplusRectificationTypes"
|
||||
option-value="id"
|
||||
option-label="description"
|
||||
:required="true"
|
||||
data-cy="invoiceInDescriptorMenu_type"
|
||||
>
|
||||
<template #option="{ itemProps, opt }">
|
||||
<QItem v-bind="itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel
|
||||
>{{ opt.id }} -
|
||||
{{ opt.description }}</QItemLabel
|
||||
>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<div></div>
|
||||
</template>
|
||||
</VnSelect>
|
||||
|
||||
<VnSelect
|
||||
:label="`${useCapitalize(t('globals.reason'))}`"
|
||||
v-model="correctionFormData.invoiceReason"
|
||||
:options="invoiceCorrectionTypes"
|
||||
option-value="id"
|
||||
option-label="description"
|
||||
:required="true"
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</QCardSection>
|
||||
<QCardActions class="justify-end q-mr-sm">
|
||||
<QBtn flat :label="t('globals.close')" color="primary" v-close-popup />
|
||||
<QBtn
|
||||
:label="t('globals.save')"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="createInvoiceInCorrection"
|
||||
:disable="isNotFilled"
|
||||
/>
|
||||
</QCardActions>
|
||||
</QCard>
|
||||
</QDialog>
|
||||
<VnSelect
|
||||
:label="`${useCapitalize(t('globals.reason'))}`"
|
||||
v-model="correctionFormData.invoiceReason"
|
||||
:options="invoiceCorrectionTypes"
|
||||
option-value="id"
|
||||
option-label="description"
|
||||
:required="true"
|
||||
data-cy="invoiceInDescriptorMenu_reason"
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</QCardSection>
|
||||
<QCardActions class="justify-end q-mr-sm">
|
||||
<QBtn
|
||||
flat
|
||||
:label="t('globals.close')"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
/>
|
||||
<QBtn
|
||||
:label="t('globals.save')"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="createInvoiceInCorrection"
|
||||
:disable="isNotFilled"
|
||||
data-cy="saveCorrectiveInvoice"
|
||||
/>
|
||||
</QCardActions>
|
||||
</QCard>
|
||||
</QDialog>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
en:
|
||||
isNotLinked: The entry {bookEntry} has been deleted with {accountingEntries} entries
|
||||
|
|
|
@ -198,6 +198,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
|||
color="orange-11"
|
||||
text-color="black"
|
||||
@click="book(entityId)"
|
||||
data-cy="invoiceInSummary_book"
|
||||
/>
|
||||
</template>
|
||||
</InvoiceIntoBook>
|
||||
|
@ -219,7 +220,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
|||
:value="entity.supplier?.name"
|
||||
>
|
||||
<template #value>
|
||||
<span class="link">
|
||||
<span class="link" data-cy="invoiceInSummary_supplier">
|
||||
{{ entity.supplier?.name }}
|
||||
<SupplierDescriptorProxy :id="entity.supplierFk" />
|
||||
</span>
|
||||
|
|
|
@ -202,6 +202,9 @@ function setCursor(ref) {
|
|||
:option-label="col.optionLabel"
|
||||
:filter-options="['id', 'name']"
|
||||
:tooltip="t('Create a new expense')"
|
||||
:acls="[
|
||||
{ model: 'Expense', props: '*', accessType: 'WRITE' },
|
||||
]"
|
||||
@keydown.tab.prevent="
|
||||
autocompleteExpense(
|
||||
$event,
|
||||
|
|
|
@ -7,6 +7,7 @@ import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
|||
import { dateRange } from 'src/filters';
|
||||
import { date } from 'quasar';
|
||||
import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
|
||||
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
|
||||
|
||||
defineProps({ dataKey: { type: String, required: true } });
|
||||
const dateFormat = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
|
||||
|
@ -147,13 +148,13 @@ function handleDaysAgo(params, daysAgo) {
|
|||
</QItem>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<QCheckbox
|
||||
<VnCheckbox
|
||||
:label="$t('invoiceIn.isBooked')"
|
||||
v-model="params.isBooked"
|
||||
@update:model-value="searchFn()"
|
||||
toggle-indeterminate
|
||||
/>
|
||||
<QCheckbox
|
||||
<VnCheckbox
|
||||
:label="getLocale('params.correctingFk')"
|
||||
v-model="params.correctingFk"
|
||||
@update:model-value="searchFn()"
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useQuasar } from 'quasar';
|
|||
import { useI18n } from 'vue-i18n';
|
||||
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import qs from 'qs';
|
||||
|
||||
const { notify, dialog } = useQuasar();
|
||||
const { t } = useI18n();
|
||||
|
||||
|
@ -61,17 +61,15 @@ async function checkToBook(id) {
|
|||
}
|
||||
|
||||
async function toBook(id) {
|
||||
let type = 'positive';
|
||||
let message = t('globals.dataSaved');
|
||||
|
||||
let err = false;
|
||||
try {
|
||||
await axios.post(`InvoiceIns/${id}/toBook`);
|
||||
store.data.isBooked = true;
|
||||
} catch (e) {
|
||||
type = 'negative';
|
||||
message = t('It was not able to book the invoice');
|
||||
err = true;
|
||||
throw e;
|
||||
} finally {
|
||||
notify({ type, message });
|
||||
if (!err) notify({ type: 'positive', message: t('globals.dataSaved') });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -55,9 +55,9 @@ describe('OrderCatalog', () => {
|
|||
it('removes a secondary tag', () => {
|
||||
cy.get(':nth-child(1) > [data-cy="catalogFilterCategory"]').click();
|
||||
cy.selectOption('[data-cy="catalogFilterType"]', 'Anthurium');
|
||||
cy.dataCy('vnFilterPanelChip').should('exist');
|
||||
cy.dataCy('vnFilterPanelChip_typeFk').should('exist');
|
||||
cy.get('[data-cy="catalogFilterCustomTag"] > .q-chip__icon--remove').click();
|
||||
cy.dataCy('vnFilterPanelChip').should('not.exist');
|
||||
cy.dataCy('vnFilterPanelChip_typeFk').should('not.exist');
|
||||
});
|
||||
|
||||
it('Removes category tag', () => {
|
||||
|
|
|
@ -53,7 +53,7 @@ describe.skip('Client list', () => {
|
|||
it('Client founded create ticket', () => {
|
||||
const search = 'Jessica Jones';
|
||||
cy.searchByLabel('Name', search);
|
||||
cy.openActionDescriptor('Create ticket');
|
||||
cy.selectDescriptorOption();
|
||||
cy.waitForElement('#formModel');
|
||||
cy.waitForElement('.q-form');
|
||||
cy.checkValueForm(1, search);
|
||||
|
|
|
@ -1,26 +1,40 @@
|
|||
/// <reference types="cypress" />
|
||||
import moment from 'moment';
|
||||
describe('InvoiceInBasicData', () => {
|
||||
const firstFormSelect = '.q-card > .vn-row:nth-child(1) > .q-select';
|
||||
const dialogInputs = '.q-dialog input';
|
||||
const resetBtn = '.q-btn-group--push > .q-btn--flat';
|
||||
const getDocumentBtns = (opt) => `[data-cy="dms-buttons"] > :nth-child(${opt})`;
|
||||
const futureDate = moment().add(1, 'days').format('DD-MM-YYYY');
|
||||
const mock = {
|
||||
invoiceInBasicDataSupplier: { val: 'Bros nick', type: 'select' },
|
||||
invoiceInBasicDataSupplierRef_input: 'mockInvoice41',
|
||||
invoiceInBasicDataIssued: { val: futureDate, type: 'date' },
|
||||
invoiceInBasicDataOperated: { val: futureDate, type: 'date' },
|
||||
invoiceInBasicDatabookEntried: { val: futureDate, type: 'date' },
|
||||
invoiceInBasicDataBooked: {
|
||||
val: moment().add(5, 'days').format('DD-MM-YYYY'),
|
||||
type: 'date',
|
||||
},
|
||||
invoiceInBasicDataDeductibleExpenseFk: {
|
||||
val: '4751000000',
|
||||
type: 'select',
|
||||
},
|
||||
invoiceInBasicDataCurrencyFk: { val: 'USD', type: 'select' },
|
||||
invoiceInBasicDataCompanyFk: { val: 'CCs', type: 'select' },
|
||||
invoiceInBasicDataWithholdingSageFk: {
|
||||
val: 'Arrendamiento y subarrendamiento',
|
||||
type: 'select',
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login('developer');
|
||||
cy.login('administrative');
|
||||
cy.visit(`/#/invoice-in/1/basic-data`);
|
||||
});
|
||||
|
||||
it('should edit the provideer and supplier ref', () => {
|
||||
cy.dataCy('UnDeductibleVatSelect').type('4751000000');
|
||||
cy.get('.q-menu .q-item').contains('4751000000').click();
|
||||
cy.get(resetBtn).click();
|
||||
|
||||
cy.waitForElement('#formModel').within(() => {
|
||||
cy.dataCy('vnSupplierSelect').type('Bros nick');
|
||||
})
|
||||
cy.get('.q-menu .q-item').contains('Bros nick').click();
|
||||
it('should edit every field', () => {
|
||||
cy.fillInForm(mock, { attr: 'data-cy' });
|
||||
cy.saveCard();
|
||||
cy.get(`${firstFormSelect} input`).invoke('val').should('eq', 'Bros nick');
|
||||
cy.validateForm(mock, { attr: 'data-cy' });
|
||||
});
|
||||
|
||||
it('should edit, remove and create the dms data', () => {
|
||||
|
@ -44,7 +58,7 @@ describe('InvoiceInBasicData', () => {
|
|||
cy.checkNotification('Data saved');
|
||||
|
||||
//create
|
||||
cy.get('[data-cy="dms-create"]').eq(0).click();
|
||||
cy.get('[data-cy="invoiceInBasicDataDmsAdd"]').eq(0).click();
|
||||
cy.get('[data-cy="VnDms_inputFile"').selectFile(
|
||||
'test/cypress/fixtures/image.jpg',
|
||||
{
|
||||
|
|
|
@ -1,22 +1,59 @@
|
|||
/// <reference types="cypress" />
|
||||
describe('InvoiceInCorrective', () => {
|
||||
const saveDialog = '.q-card > .q-card__actions > .q-btn--standard ';
|
||||
describe('invoiceInCorrective', () => {
|
||||
beforeEach(() => cy.login('administrative'));
|
||||
|
||||
it('should create a correcting invoice', () => {
|
||||
cy.viewport(1280, 720);
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/invoice-in/1/summary`);
|
||||
it('should modify the invoice', () => {
|
||||
cy.visit('/#/invoice-in/1/summary');
|
||||
cy.intercept('POST', '/api/InvoiceIns/corrective').as('corrective');
|
||||
cy.intercept('POST', '/api/InvoiceInCorrections/crud').as('crud');
|
||||
cy.intercept('GET', /InvoiceInCorrections\?filter=.+/).as('getCorrective');
|
||||
|
||||
cy.openActionsDescriptor();
|
||||
cy.selectDescriptorOption(4);
|
||||
cy.dataCy('saveCorrectiveInvoice').click();
|
||||
|
||||
cy.dataCy('createCorrectiveItem').click();
|
||||
cy.get(saveDialog).click();
|
||||
cy.wait('@corrective').then((interception) => {
|
||||
const correctingId = interception.response.body;
|
||||
cy.url().should('include', `/invoice-in/${correctingId}/summary`);
|
||||
cy.visit(`/#/invoice-in/${correctingId}/corrective`);
|
||||
cy.wait('@corrective').then(({ response }) => {
|
||||
const correctingFk = response.body;
|
||||
cy.url().should('include', `/invoice-in/${correctingFk}/summary`);
|
||||
cy.visit(`/#/invoice-in/${correctingFk}/corrective`);
|
||||
cy.selectOption('[data-cy="invoiceInCorrective_class"]', 'r4');
|
||||
cy.selectOption('[data-cy="invoiceInCorrective_type"]', 'sustitución');
|
||||
cy.selectOption('[data-cy="invoiceInCorrective_reason"]', 'vat');
|
||||
cy.dataCy('crudModelDefaultSaveBtn').click();
|
||||
|
||||
cy.wait('@crud');
|
||||
cy.reload();
|
||||
cy.wait('@getCorrective');
|
||||
cy.validateRow('tbody > :nth-of-type(1)', [
|
||||
,
|
||||
'S – Por sustitución',
|
||||
'R4',
|
||||
'Error in VAT calculation',
|
||||
]);
|
||||
});
|
||||
cy.get('tbody > tr:visible').should('have.length', 1);
|
||||
});
|
||||
|
||||
it('should not be able to modify the invoice if the original invoice is booked', () => {
|
||||
cy.intercept('POST', '/api/InvoiceIns/corrective').as('corrective');
|
||||
cy.visit('/#/invoice-in/4/summary');
|
||||
cy.selectDescriptorOption();
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.selectDescriptorOption(4);
|
||||
cy.dataCy('saveCorrectiveInvoice').click();
|
||||
|
||||
cy.wait('@corrective').then(({ response }) => {
|
||||
const correctingFk = response.body;
|
||||
cy.url().should('include', `/invoice-in/${correctingFk}/summary`);
|
||||
cy.visit(`/#/invoice-in/${correctingFk}/corrective`);
|
||||
|
||||
cy.dataCy('invoiceInCorrective_class').should('be.disabled');
|
||||
cy.dataCy('invoiceInCorrective_type').should('be.disabled');
|
||||
cy.dataCy('invoiceInCorrective_reason').should('be.disabled');
|
||||
});
|
||||
});
|
||||
|
||||
it('should show/hide the section if it is a corrective invoice', () => {
|
||||
cy.visit('/#/invoice-in/1/summary');
|
||||
cy.get('[data-cy="InvoiceInCorrective-menu-item"]').should('not.exist');
|
||||
cy.clicDescriptorAction(4);
|
||||
cy.get('[data-cy="InvoiceInCorrective-menu-item"]').should('exist');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,21 +1,147 @@
|
|||
describe('InvoiceInDescriptor', () => {
|
||||
const book = '.summaryHeader > .no-wrap > .q-btn';
|
||||
const firstDescritorOpt = '.q-menu > .q-list > :nth-child(5) > .q-item__section';
|
||||
const checkbox = ':nth-child(5) > .q-checkbox';
|
||||
beforeEach(() => cy.login('administrative'));
|
||||
|
||||
it('should booking and unbooking the invoice properly', () => {
|
||||
cy.viewport(1280, 720);
|
||||
cy.login('developer');
|
||||
cy.visit('/#/invoice-in/1/summary');
|
||||
cy.waitForElement('.q-page');
|
||||
describe('more options', () => {
|
||||
it('should booking and unbooking the invoice properly', () => {
|
||||
const checkbox = '[data-cy="vnLvIs booked"] > .q-checkbox';
|
||||
cy.visit('/#/invoice-in/2/summary');
|
||||
cy.selectDescriptorOption();
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.validateCheckbox(checkbox);
|
||||
cy.selectDescriptorOption();
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.validateCheckbox(checkbox, false);
|
||||
});
|
||||
|
||||
cy.get(book).click();
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.get(checkbox).invoke('attr', 'aria-checked').should('eq', 'true');
|
||||
it('should delete the invoice properly', () => {
|
||||
cy.visit('/#/invoice-in/2/summary');
|
||||
cy.selectDescriptorOption(2);
|
||||
cy.clickConfirm();
|
||||
cy.checkNotification('invoice deleted');
|
||||
});
|
||||
|
||||
cy.dataCy('descriptor-more-opts').first().click();
|
||||
cy.get(firstDescritorOpt).click();
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.get(checkbox).invoke('attr', 'aria-checked').should('eq', 'false');
|
||||
it('should clone the invoice properly', () => {
|
||||
cy.visit('/#/invoice-in/3/summary');
|
||||
cy.selectDescriptorOption(3);
|
||||
cy.clickConfirm();
|
||||
cy.checkNotification('Invoice cloned');
|
||||
});
|
||||
|
||||
it('should show the agricultural PDF properly', () => {
|
||||
cy.visit('/#/invoice-in/6/summary');
|
||||
cy.validatePdfDownload(
|
||||
/api\/InvoiceIns\/6\/invoice-in-pdf\?access_token=.*/,
|
||||
() => cy.selectDescriptorOption(4),
|
||||
);
|
||||
});
|
||||
|
||||
it('should send the agricultural PDF properly', () => {
|
||||
cy.intercept('POST', 'api/InvoiceIns/6/invoice-in-email').as('sendEmail');
|
||||
cy.visit('/#/invoice-in/6/summary');
|
||||
cy.selectDescriptorOption(5);
|
||||
|
||||
cy.dataCy('SendEmailNotifiactionDialogInput_input').type(
|
||||
'{selectall}jorgito@gmail.mx',
|
||||
);
|
||||
cy.clickConfirm();
|
||||
cy.checkNotification('Notification sent');
|
||||
cy.wait('@sendEmail').then(({ request, response }) => {
|
||||
expect(request.body).to.deep.equal({
|
||||
recipientId: 2,
|
||||
recipient: 'jorgito@gmail.mx',
|
||||
});
|
||||
expect(response.statusCode).to.equal(200);
|
||||
});
|
||||
});
|
||||
// https://redmine.verdnatura.es/issues/8767
|
||||
it.skip('should download the file properly', () => {
|
||||
cy.visit('/#/invoice-in/1/summary');
|
||||
cy.validateDownload(() => cy.selectDescriptorOption(5));
|
||||
});
|
||||
});
|
||||
|
||||
describe('buttons', () => {
|
||||
beforeEach(() => cy.visit('/#/invoice-in/1/summary'));
|
||||
|
||||
it('should navigate to the supplier summary', () => {
|
||||
cy.clicDescriptorAction(1);
|
||||
cy.url().should('to.match', /supplier\/\d+\/summary/);
|
||||
});
|
||||
|
||||
it('should navigate to the entry summary', () => {
|
||||
cy.clicDescriptorAction(2);
|
||||
cy.url().should('to.match', /entry\/\d+\/summary/);
|
||||
});
|
||||
|
||||
it('should navigate to the invoiceIn list', () => {
|
||||
cy.clicDescriptorAction(3);
|
||||
cy.url().should('to.match', /invoice-in\/list\?table=\{.*supplierFk.+\}/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('corrective', () => {
|
||||
const originalId = 4;
|
||||
|
||||
beforeEach(() => cy.visit(`/#/invoice-in/${originalId}/summary`));
|
||||
|
||||
it('should create a correcting invoice and redirect to original invoice', () => {
|
||||
createCorrective();
|
||||
redirect(originalId);
|
||||
});
|
||||
|
||||
it('should create a correcting invoice and navigate to list filtered by corrective', () => {
|
||||
createCorrective();
|
||||
redirect(originalId);
|
||||
|
||||
cy.clicDescriptorAction(4);
|
||||
cy.validateVnTableRows({
|
||||
cols: [
|
||||
{
|
||||
name: 'supplierRef',
|
||||
val: '1237',
|
||||
operation: 'include',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('link', () => {
|
||||
it('should open the supplier descriptor popup', () => {
|
||||
cy.visit('/#/invoice-in/1/summary');
|
||||
cy.intercept('GET', /Suppliers\/\d+/).as('getSupplier');
|
||||
|
||||
cy.dataCy('invoiceInDescriptor_supplier').then(($el) => {
|
||||
const alias = $el.text().trim();
|
||||
$el.click();
|
||||
cy.wait('@getSupplier').then(() =>
|
||||
cy.validateDescriptor({ listbox: { 1: alias }, popup: true }),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createCorrective() {
|
||||
cy.intercept('POST', '/api/InvoiceIns/corrective').as('corrective');
|
||||
|
||||
cy.selectDescriptorOption(4);
|
||||
cy.dataCy('saveCorrectiveInvoice').click();
|
||||
|
||||
cy.wait('@corrective').then(({ response }) => {
|
||||
const correctingId = response.body;
|
||||
cy.url().should('include', `/invoice-in/${correctingId}/summary`);
|
||||
cy.visit(`/#/invoice-in/${correctingId}/corrective`);
|
||||
cy.dataCy('invoiceInCorrective_class').should('contain.value', 'R2');
|
||||
cy.dataCy('invoiceInCorrective_type').should('contain.value', 'diferencias');
|
||||
cy.dataCy('invoiceInCorrective_reason').should('contain.value', 'sales details');
|
||||
});
|
||||
}
|
||||
|
||||
function redirect(subtitle) {
|
||||
const regex = new RegExp(`InvoiceIns/${subtitle}\\?filter=.*`);
|
||||
cy.intercept('GET', regex).as('getOriginal');
|
||||
cy.clicDescriptorAction(4);
|
||||
cy.wait('@getOriginal');
|
||||
cy.validateDescriptor({ subtitle });
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ describe('InvoiceInDueDay', () => {
|
|||
const addBtn = '.q-page-sticky > div > .q-btn > .q-btn__content';
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login('developer');
|
||||
cy.login('administrative');
|
||||
cy.visit(`/#/invoice-in/6/due-day`);
|
||||
});
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ describe('InvoiceInIntrastat', () => {
|
|||
const firstRowAmount = `${firstRow} > :nth-child(3)`;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login('developer');
|
||||
cy.login('administrative');
|
||||
cy.visit(`/#/invoice-in/1/intrastat`);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
/// <reference types="cypress" />
|
||||
|
||||
describe('InvoiceInList', () => {
|
||||
const firstRow = 'tbody.q-virtual-scroll__content tr:nth-child(1)';
|
||||
const firstId = `${firstRow} > td:nth-child(2) span`;
|
||||
const firstDetailBtn = `${firstRow} .q-btn:nth-child(1)`;
|
||||
const summaryHeaders = '.summaryBody .header-link';
|
||||
const mockInvoiceRef = `createMockInvoice${Math.floor(Math.random() * 100)}`;
|
||||
const mock = {
|
||||
vnSupplierSelect: { val: 'farmer king', type: 'select' },
|
||||
'Invoice nº_input': mockInvoiceRef,
|
||||
Company_select: { val: 'orn', type: 'select' },
|
||||
'Expedition date_inputDate': '16-11-2001',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
cy.viewport(1920, 1080);
|
||||
cy.login('developer');
|
||||
cy.login('administrative');
|
||||
cy.visit(`/#/invoice-in/list`);
|
||||
cy.get('#searchbar input').type('{enter}');
|
||||
});
|
||||
|
@ -27,4 +35,18 @@ describe('InvoiceInList', () => {
|
|||
cy.get(summaryHeaders).eq(1).contains('Basic data');
|
||||
cy.get(summaryHeaders).eq(4).contains('Vat');
|
||||
});
|
||||
|
||||
it('should create a new Invoice', () => {
|
||||
cy.dataCy('vnTableCreateBtn').click();
|
||||
cy.fillInForm({ ...mock }, { attr: 'data-cy' });
|
||||
cy.dataCy('FormModelPopup_save').click();
|
||||
cy.intercept('GET', /\/api\/InvoiceIns\/\d+\/getTotals$/).as('invoice');
|
||||
cy.wait('@invoice').then(() =>
|
||||
cy.validateDescriptor({
|
||||
title: mockInvoiceRef,
|
||||
listBox: { 0: '11/16/2001', 3: 'The farmer' },
|
||||
}),
|
||||
);
|
||||
cy.get('[data-cy="vnLvCompany"]').should('contain.text', 'ORN');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
describe('InvoiceInSerial', () => {
|
||||
beforeEach(() => {
|
||||
cy.login('administrative');
|
||||
cy.visit('#/invoice-in/serial');
|
||||
});
|
||||
|
||||
it('should filter by serial number', () => {
|
||||
cy.dataCy('serial_input').type('R{enter}');
|
||||
cy.validateVnTableRows({ cols: [{ name: 'serial', val: 'r' }] });
|
||||
});
|
||||
|
||||
it('should filter by last days ', () => {
|
||||
let before;
|
||||
cy.dataCy('vnTableCell_total')
|
||||
.invoke('text')
|
||||
.then((total) => (before = +total));
|
||||
|
||||
cy.dataCy('Last days_input').type('{selectall}1{enter}');
|
||||
cy.dataCy('vnTableCell_total')
|
||||
.invoke('text')
|
||||
.then((total) => expect(+total).to.be.lessThan(before));
|
||||
});
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
describe('InvoiceInSummary', () => {
|
||||
beforeEach(() => {
|
||||
cy.login('administrative');
|
||||
cy.visit('/#/invoice-in/3/summary');
|
||||
});
|
||||
|
||||
it('should booking and unbooking the invoice properly', () => {
|
||||
const checkbox = '[data-cy="vnLvIs booked"] > .q-checkbox';
|
||||
cy.dataCy('invoiceInSummary_book').click();
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.validateCheckbox(checkbox);
|
||||
});
|
||||
|
||||
it('should open the supplier descriptor popup', () => {
|
||||
cy.intercept('GET', /Suppliers\/\d+/).as('getSupplier');
|
||||
cy.dataCy('invoiceInSummary_supplier').then(($el) => {
|
||||
const description = $el.text().trim();
|
||||
$el.click();
|
||||
cy.wait('@getSupplier').then(() =>
|
||||
cy.validateDescriptor({ description, popup: true }),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -8,7 +8,7 @@ describe('InvoiceInVat', () => {
|
|||
const randomInt = Math.floor(Math.random() * 100);
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login('developer');
|
||||
cy.login('administrative');
|
||||
cy.visit(`/#/invoice-in/1/vat`);
|
||||
});
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ describe('VnLog', () => {
|
|||
|
||||
it('should show claimDescriptor', () => {
|
||||
cy.dataCy('iconLaunch-claimFk').first().click();
|
||||
cy.dataCy('descriptor_id').contains('1');
|
||||
cy.dataCy('cardDescriptor_subtitle').contains('1');
|
||||
cy.dataCy('iconLaunch-claimFk').first().click();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -27,8 +27,9 @@
|
|||
// DO NOT REMOVE
|
||||
// Imports Quasar Cypress AE predefined commands
|
||||
// import { registerCommands } from '@quasar/quasar-app-extension-testing-e2e-cypress';
|
||||
|
||||
import moment from 'moment';
|
||||
import waitUntil from './waitUntil';
|
||||
|
||||
Cypress.Commands.add('waitUntil', { prevSubject: 'optional' }, waitUntil);
|
||||
|
||||
Cypress.Commands.add('resetDB', () => {
|
||||
|
@ -122,9 +123,10 @@ function selectItem(selector, option, ariaControl, hasWrite = true) {
|
|||
cy.waitSpinner();
|
||||
|
||||
getItems(ariaControl).then((items) => {
|
||||
const matchingItem = items
|
||||
.toArray()
|
||||
.find((item) => item.innerText.includes(option));
|
||||
const matchingItem = items.toArray().find((item) => {
|
||||
const val = typeof option == 'string' ? option.toLowerCase() : option;
|
||||
return item.innerText.toLowerCase().includes(val);
|
||||
});
|
||||
if (matchingItem) return cy.wrap(matchingItem).click();
|
||||
|
||||
if (hasWrite) cy.get(selector).clear().type(option);
|
||||
|
@ -160,14 +162,20 @@ Cypress.Commands.add('countSelectOptions', (selector, option) => {
|
|||
cy.get('.q-menu .q-item').should('have.length', option);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('fillInForm', (obj, form = '.q-form > .q-card') => {
|
||||
Cypress.Commands.add('fillInForm', (obj, opts = {}) => {
|
||||
cy.waitSpinner();
|
||||
const { form = '.q-form > .q-card', attr = 'aria-label' } = opts;
|
||||
cy.waitForElement(form);
|
||||
cy.get(`${form} input`).each(([el]) => {
|
||||
cy.wrap(el)
|
||||
.invoke('attr', 'aria-label')
|
||||
.then((ariaLabel) => {
|
||||
const field = obj[ariaLabel];
|
||||
.invoke('attr', attr)
|
||||
.then((key) => {
|
||||
const field = obj[key];
|
||||
if (!field) return;
|
||||
if (typeof field == 'string')
|
||||
return cy
|
||||
.wrap(el)
|
||||
.type(`{selectall}{backspace}${field}`, { delay: 0 });
|
||||
|
||||
const { type, val } = field;
|
||||
switch (type) {
|
||||
|
@ -175,7 +183,9 @@ Cypress.Commands.add('fillInForm', (obj, form = '.q-form > .q-card') => {
|
|||
cy.selectOption(el, val);
|
||||
break;
|
||||
case 'date':
|
||||
cy.get(el).type(val.split('-').join(''));
|
||||
cy.get(el).type(
|
||||
`{selectall}{backspace}${val.split('-').join('')}`,
|
||||
);
|
||||
break;
|
||||
case 'time':
|
||||
cy.get(el).click();
|
||||
|
@ -191,6 +201,40 @@ Cypress.Commands.add('fillInForm', (obj, form = '.q-form > .q-card') => {
|
|||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('validateForm', (obj, opts = {}) => {
|
||||
const { form = '.q-form > .q-card', attr = 'data-cy' } = opts;
|
||||
cy.waitForElement(form);
|
||||
cy.get(`${form} input`).each(([el]) => {
|
||||
cy.wrap(el)
|
||||
.invoke('attr', attr)
|
||||
.then((key) => {
|
||||
const field = obj[key];
|
||||
if (!field) return;
|
||||
|
||||
const { type, val } = field;
|
||||
cy.get(el)
|
||||
.invoke('val')
|
||||
.then((elVal) => {
|
||||
if (typeof field == 'string')
|
||||
expect(elVal.toLowerCase()).to.equal(field.toLowerCase());
|
||||
else
|
||||
switch (type) {
|
||||
case 'date':
|
||||
const elDate = moment(elVal, 'DD-MM-YYYY');
|
||||
const mockDate = moment(val, 'DD-MM-YYYY');
|
||||
expect(elDate.isSame(mockDate, 'day')).to.be.true;
|
||||
break;
|
||||
default:
|
||||
expect(elVal.toLowerCase()).to.equal(
|
||||
val.toLowerCase(),
|
||||
);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('checkOption', (selector) => {
|
||||
cy.get(selector).find('.q-checkbox__inner').click();
|
||||
});
|
||||
|
@ -207,14 +251,17 @@ Cypress.Commands.add('saveCard', () => {
|
|||
Cypress.Commands.add('resetCard', () => {
|
||||
cy.get('[title="Reset"]').click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('removeCard', () => {
|
||||
cy.get('[title="Remove"]').click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('addCard', () => {
|
||||
cy.waitForElement('tbody');
|
||||
cy.waitForElement('.q-page-sticky > div > .q-btn');
|
||||
cy.get('.q-page-sticky > div > .q-btn').click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('clickConfirm', () => {
|
||||
cy.waitForElement('.q-dialog__inner > .q-card');
|
||||
cy.get('.q-card__actions > .q-btn--unelevated > .q-btn__content > .block').click();
|
||||
|
@ -295,6 +342,7 @@ Cypress.Commands.add('removeRow', (rowIndex) => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('openListSummary', (row) => {
|
||||
cy.get('.card-list-body .actions .q-btn:nth-child(2)').eq(row).click();
|
||||
});
|
||||
|
@ -322,20 +370,8 @@ Cypress.Commands.add('validateContent', (selector, expectedValue) => {
|
|||
cy.get(selector).should('have.text', expectedValue);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('openActionDescriptor', (opt) => {
|
||||
cy.openActionsDescriptor();
|
||||
const listItem = '[role="menu"] .q-list .q-item';
|
||||
cy.contains(listItem, opt).click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('openActionsDescriptor', () => {
|
||||
cy.get('[data-cy="descriptor-more-opts"]').click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('clickButtonDescriptor', (id) => {
|
||||
cy.get(`.actions > .q-card__actions> .q-btn:nth-child(${id})`)
|
||||
.invoke('removeAttr', 'target')
|
||||
.click();
|
||||
cy.get('[data-cy="cardDescriptor"] [data-cy="descriptor-more-opts"]').click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('openUserPanel', () => {
|
||||
|
@ -424,3 +460,137 @@ Cypress.Commands.add('searchBtnFilterPanel', () => {
|
|||
Cypress.Commands.add('waitRequest', (alias, cb) => {
|
||||
cy.wait(alias).then(cb);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('validateDescriptor', (toCheck = {}) => {
|
||||
const { title, description, subtitle, listbox = {}, popup = false } = toCheck;
|
||||
|
||||
const popupSelector = popup ? '[role="menu"] ' : '';
|
||||
|
||||
if (title) cy.get(`${popupSelector}[data-cy="cardDescriptor_title"]`).contains(title);
|
||||
if (description)
|
||||
cy.get(`${popupSelector}[data-cy="cardDescriptor_description"]`).contains(
|
||||
description,
|
||||
);
|
||||
if (subtitle)
|
||||
cy.get(`${popupSelector}[data-cy="cardDescriptor_subtitle"]`).contains(subtitle);
|
||||
|
||||
for (const index in listbox)
|
||||
cy.get(`${popupSelector}[data-cy="cardDescriptor_listbox"] > *`)
|
||||
.eq(index)
|
||||
.should('contain.text', listbox[index]);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('validateVnTableRows', (opts = {}) => {
|
||||
let { cols = [], rows = [] } = opts;
|
||||
if (!Array.isArray(cols)) cols = [cols];
|
||||
const rowSelector = rows.length
|
||||
? rows.map((row) => `> :nth-child(${row})`).join(', ')
|
||||
: '> *';
|
||||
cy.get(`[data-cy="vnTable"] .q-virtual-scroll__content`).within(() => {
|
||||
cy.get(`${rowSelector}`).each(($el) => {
|
||||
for (const { name, type = 'string', val, operation = 'equal' } of cols) {
|
||||
cy.wrap($el)
|
||||
.find(`[data-cy="vnTableCell_${name}"]`)
|
||||
.invoke('text')
|
||||
.then((text) => {
|
||||
if (type === 'string')
|
||||
expect(text.trim().toLowerCase()).to[operation](
|
||||
val.toLowerCase(),
|
||||
);
|
||||
if (type === 'number') cy.checkNumber(text, val, operation);
|
||||
if (type === 'date') cy.checkDate(text, val, operation);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('checkDate', (rawDate, expectedVal, operation) => {
|
||||
const date = moment(rawDate.trim(), 'MM/DD/YYYY');
|
||||
const compareDate = moment(expectedVal, 'DD/MM/YYYY');
|
||||
|
||||
switch (operation) {
|
||||
case 'equal':
|
||||
expect(text.trim()).to.equal(compareDate);
|
||||
break;
|
||||
case 'before':
|
||||
expect(date.isBefore(compareDate)).to.be.true;
|
||||
break;
|
||||
case 'after':
|
||||
expect(date.isAfter(compareDate)).to.be.true;
|
||||
}
|
||||
});
|
||||
|
||||
Cypress.Commands.add('selectDescriptorOption', (opt = 1) => {
|
||||
const listItem = '[data-cy="descriptor-more-opts_list"]';
|
||||
cy.get('body').then(($body) => {
|
||||
if (!$body.find(listItem).length) cy.openActionsDescriptor();
|
||||
});
|
||||
|
||||
cy.waitForElement(listItem);
|
||||
cy.get(`${listItem} > :not(template):nth-of-type(${opt})`).click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('validateCheckbox', (selector, expectedVal = 'true') => {
|
||||
cy.get(selector).should('have.attr', 'aria-checked', expectedVal.toString());
|
||||
});
|
||||
|
||||
Cypress.Commands.add('validateDownload', (trigger, opts = {}) => {
|
||||
const {
|
||||
url = /api\/dms\/\d+\/downloadFile\?access_token=.+/,
|
||||
types = ['text/plain', 'image/jpeg'],
|
||||
alias = 'download',
|
||||
} = opts;
|
||||
cy.intercept('GET', url).as(alias);
|
||||
trigger().then(() => {
|
||||
cy.wait(`@${alias}`).then(({ response }) => {
|
||||
expect(response.statusCode).to.equal(200);
|
||||
const isValidType = types.some((type) =>
|
||||
response.headers['content-type'].includes(type),
|
||||
);
|
||||
expect(isValidType).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('validatePdfDownload', (match, trigger) => {
|
||||
cy.window().then((win) => {
|
||||
cy.stub(win, 'open')
|
||||
.callsFake(() => null)
|
||||
.as('pdf');
|
||||
});
|
||||
trigger();
|
||||
cy.get('@pdf')
|
||||
.should('be.calledOnce')
|
||||
.then((stub) => {
|
||||
const [url] = stub.getCall(0).args;
|
||||
expect(url).to.match(match);
|
||||
cy.request(url).then((response) =>
|
||||
expect(response.headers['content-type']).to.include('application/pdf'),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('clicDescriptorAction', (index = 1) => {
|
||||
cy.get(`[data-cy="descriptor_actions"] .q-btn:nth-of-type(${index})`).click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('checkQueryParams', (expectedParams = {}) => {
|
||||
cy.url().then((url) => {
|
||||
const urlParams = new URLSearchParams(url.split('?')[1]);
|
||||
|
||||
for (const key in expectedParams) {
|
||||
const expected = expectedParams[key];
|
||||
const param = JSON.parse(decodeURIComponent(urlParams.get(key)));
|
||||
|
||||
if (typeof expected === 'object') {
|
||||
const { subkey, val } = expected;
|
||||
expect(param[subkey]).to.equal(val);
|
||||
} else expect(param).to.equal(expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('waitTableScrollLoad', () =>
|
||||
cy.waitForElement('[data-q-vs-anchor]'),
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue