#6899 end invoiceOut migration with VnTable #513
|
@ -46,22 +46,6 @@ const onDataSaved = async (formData, requestResponse) => {
|
||||||
@on-fetch="(data) => (taxAreasOptions = data)"
|
@on-fetch="(data) => (taxAreasOptions = data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<FetchData
|
|
||||||
url="Tickets"
|
|
||||||
:filter="{
|
|
||||||
fields: ['id', 'nickname'],
|
|
||||||
where: { refFk: null },
|
|
||||||
order: 'shipped DESC',
|
|
||||||
}"
|
|
||||||
@on-fetch="(data) => (ticketsOptions = data)"
|
|
||||||
auto-load
|
|
||||||
/>
|
|
||||||
<FetchData
|
|
||||||
url="Clients"
|
|
||||||
:filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }"
|
|
||||||
@on-fetch="(data) => (clientsOptions = data)"
|
|
||||||
auto-load
|
|
||||||
/>
|
|
||||||
<FormModelPopup
|
<FormModelPopup
|
||||||
ref="formModelPopupRef"
|
ref="formModelPopupRef"
|
||||||
:title="t('Create manual invoice')"
|
:title="t('Create manual invoice')"
|
||||||
|
@ -84,6 +68,10 @@ const onDataSaved = async (formData, requestResponse) => {
|
||||||
option-value="id"
|
option-value="id"
|
||||||
v-model="data.ticketFk"
|
v-model="data.ticketFk"
|
||||||
@update:model-value="data.clientFk = null"
|
@update:model-value="data.clientFk = null"
|
||||||
|
url="Tickets"
|
||||||
|
:where="{ refFk: null }"
|
||||||
|
:fields="['id', 'nickname']"
|
||||||
|
:filter-options="{ order: 'shipped DESC' }"
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
|
@ -105,6 +93,9 @@ const onDataSaved = async (formData, requestResponse) => {
|
||||||
option-value="id"
|
option-value="id"
|
||||||
v-model="data.clientFk"
|
v-model="data.clientFk"
|
||||||
@update:model-value="data.ticketFk = null"
|
@update:model-value="data.ticketFk = null"
|
||||||
|
url="Clients"
|
||||||
|
:fields="['id', 'name']"
|
||||||
|
:filter-options="{ order: 'name ASC' }"
|
||||||
/>
|
/>
|
||||||
<VnInputDate :label="t('Max date')" v-model="data.maxShipped" />
|
<VnInputDate :label="t('Max date')" v-model="data.maxShipped" />
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
@ -116,7 +107,6 @@ const onDataSaved = async (formData, requestResponse) => {
|
||||||
option-label="description"
|
option-label="description"
|
||||||
option-value="code"
|
option-value="code"
|
||||||
v-model="data.serial"
|
v-model="data.serial"
|
||||||
:required="true"
|
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('Area')"
|
:label="t('Area')"
|
||||||
|
@ -125,7 +115,6 @@ const onDataSaved = async (formData, requestResponse) => {
|
||||||
option-label="code"
|
option-label="code"
|
||||||
option-value="code"
|
option-value="code"
|
||||||
v-model="data.taxArea"
|
v-model="data.taxArea"
|
||||||
:required="true"
|
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow class="row q-gutter-md q-mb-md">
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
|
|
@ -8,7 +8,7 @@ import VnRow from 'components/ui/VnRow.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import VnSelect from 'components/common/VnSelect.vue';
|
import VnSelect from 'components/common/VnSelect.vue';
|
||||||
import FormPopup from './FormPopup.vue';
|
import FormPopup from './FormPopup.vue';
|
||||||
|
import { useDialogPluginComponent } from 'quasar';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ const $props = defineProps({
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const { dialogRef } = useDialogPluginComponent();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -116,90 +116,92 @@ const makeInvoice = async () => {
|
||||||
@on-fetch="(data) => (invoiceCorrectionTypesOptions = data)"
|
@on-fetch="(data) => (invoiceCorrectionTypesOptions = data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<FormPopup
|
<QDialog ref="dialogRef">
|
||||||
|
<FormPopup
|
||||||
jsegarra marked this conversation as resolved
|
|||||||
@on-submit="makeInvoice()"
|
@on-submit="makeInvoice()"
|
||||||
:title="t('Transfer invoice')"
|
:title="t('Transfer invoice')"
|
||||||
:custom-submit-button-label="t('Transfer client')"
|
:custom-submit-button-label="t('Transfer client')"
|
||||||
:default-cancel-button="false"
|
:default-cancel-button="false"
|
||||||
>
|
>
|
||||||
<template #form-inputs>
|
<template #form-inputs>
|
||||||
<VnRow class="row q-gutter-md q-mb-md">
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('Client')"
|
:label="t('Client')"
|
||||||
:options="clientsOptions"
|
:options="clientsOptions"
|
||||||
hide-selected
|
hide-selected
|
||||||
option-label="name"
|
option-label="name"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
v-model="transferInvoiceParams.newClientFk"
|
v-model="transferInvoiceParams.newClientFk"
|
||||||
:required="true"
|
:required="true"
|
||||||
url="Clients"
|
url="Clients"
|
||||||
:fields="['id', 'name', 'hasToInvoiceByAddress']"
|
:fields="['id', 'name', 'hasToInvoiceByAddress']"
|
||||||
auto-load
|
auto-load
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem
|
<QItem
|
||||||
v-bind="scope.itemProps"
|
v-bind="scope.itemProps"
|
||||||
@click="selectedClient(scope.opt)"
|
@click="selectedClient(scope.opt)"
|
||||||
>
|
>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QItemLabel>
|
<QItemLabel>
|
||||||
#{{ scope.opt?.id }} - {{ scope.opt?.name }}
|
#{{ scope.opt?.id }} - {{ scope.opt?.name }}
|
||||||
</QItemLabel>
|
</QItemLabel>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
</template>
|
</template>
|
||||||
</VnSelect>
|
</VnSelect>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('Rectificative type')"
|
:label="t('Rectificative type')"
|
||||||
:options="rectificativeTypeOptions"
|
:options="rectificativeTypeOptions"
|
||||||
hide-selected
|
hide-selected
|
||||||
option-label="description"
|
option-label="description"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
v-model="transferInvoiceParams.cplusRectificationTypeFk"
|
v-model="transferInvoiceParams.cplusRectificationTypeFk"
|
||||||
:required="true"
|
:required="true"
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow class="row q-gutter-md q-mb-md">
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('Class')"
|
:label="t('Class')"
|
||||||
:options="siiTypeInvoiceOutsOptions"
|
:options="siiTypeInvoiceOutsOptions"
|
||||||
hide-selected
|
hide-selected
|
||||||
option-label="description"
|
option-label="description"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
v-model="transferInvoiceParams.siiTypeInvoiceOutFk"
|
v-model="transferInvoiceParams.siiTypeInvoiceOutFk"
|
||||||
:required="true"
|
:required="true"
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #option="scope">
|
||||||
<QItem v-bind="scope.itemProps">
|
<QItem v-bind="scope.itemProps">
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QItemLabel>
|
<QItemLabel>
|
||||||
{{ scope.opt?.code }} -
|
{{ scope.opt?.code }} -
|
||||||
{{ scope.opt?.description }}
|
{{ scope.opt?.description }}
|
||||||
</QItemLabel>
|
</QItemLabel>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
</template>
|
</template>
|
||||||
</VnSelect>
|
</VnSelect>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('Type')"
|
:label="t('Type')"
|
||||||
:options="invoiceCorrectionTypesOptions"
|
:options="invoiceCorrectionTypesOptions"
|
||||||
hide-selected
|
hide-selected
|
||||||
option-label="description"
|
option-label="description"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
v-model="transferInvoiceParams.invoiceCorrectionTypeFk"
|
v-model="transferInvoiceParams.invoiceCorrectionTypeFk"
|
||||||
:required="true"
|
:required="true"
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow class="row q-gutter-md q-mb-md">
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
<div>
|
<div>
|
||||||
<QCheckbox :label="t('Bill destination client')" v-model="checked" />
|
<QCheckbox :label="t('Bill destination client')" v-model="checked" />
|
||||||
<QIcon name="info" class="cursor-info q-ml-sm" size="sm">
|
<QIcon name="info" class="cursor-info q-ml-sm" size="sm">
|
||||||
<QTooltip>{{ t('transferInvoiceInfo') }}</QTooltip>
|
<QTooltip>{{ t('transferInvoiceInfo') }}</QTooltip>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
</div>
|
</div>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
</template>
|
</template>
|
||||||
</FormPopup>
|
</FormPopup>
|
||||||
|
</QDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -67,6 +67,10 @@ const $props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({ card: false, table: false }),
|
default: () => ({ card: false, table: false }),
|
||||||
},
|
},
|
||||||
|
table: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
|
@ -249,7 +253,7 @@ defineExpose({
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ rows }">
|
<template #body="{ rows }">
|
||||||
<QTable
|
<QTable
|
||||||
v-bind="$attrs['q-table']"
|
v-bind="table"
|
||||||
class="vnTable"
|
class="vnTable"
|
||||||
:columns="splittedColumns.columns"
|
:columns="splittedColumns.columns"
|
||||||
:rows="rows"
|
:rows="rows"
|
||||||
|
|
|
@ -165,9 +165,9 @@ const toModule = computed(() =>
|
||||||
<QTooltip>
|
<QTooltip>
|
||||||
{{ t('components.cardDescriptor.moreOptions') }}
|
{{ t('components.cardDescriptor.moreOptions') }}
|
||||||
</QTooltip>
|
</QTooltip>
|
||||||
<QMenu>
|
<QMenu ref="menuRef">
|
||||||
<QList>
|
<QList>
|
||||||
<slot name="menu" :entity="entity" />
|
<slot name="menu" :entity="entity" :menu-ref="menuRef" />
|
||||||
</QList>
|
</QList>
|
||||||
</QMenu>
|
</QMenu>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
|
|
|
@ -63,8 +63,8 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
|
||||||
@on-fetch="setData"
|
@on-fetch="setData"
|
||||||
data-key="invoiceOutData"
|
data-key="invoiceOutData"
|
||||||
>
|
>
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity, menuRef }">
|
||||||
<InvoiceOutDescriptorMenu :invoice-out-data="entity" />
|
<InvoiceOutDescriptorMenu :invoice-out-data="entity" :menu-ref="menuRef" />
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="t('invoiceOut.card.issued')" :value="toDate(entity.issued)" />
|
<VnLv :label="t('invoiceOut.card.issued')" :value="toDate(entity.issued)" />
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, onBeforeMount } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
|
@ -11,13 +11,20 @@ import useNotify from 'src/composables/useNotify';
|
||||||
import { useSession } from 'src/composables/useSession';
|
import { useSession } from 'src/composables/useSession';
|
||||||
import { usePrintService } from 'composables/usePrintService';
|
import { usePrintService } from 'composables/usePrintService';
|
||||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
|
import { getUrl } from 'src/composables/getUrl';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
|
onBeforeMount(async () => (salixUrl.value = await getUrl('')));
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
invoiceOutData: {
|
invoiceOutData: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
menuRef: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
|
@ -28,8 +35,7 @@ const { t } = useI18n();
|
||||||
const { openReport, sendEmail } = usePrintService();
|
const { openReport, sendEmail } = usePrintService();
|
||||||
const { openConfirmationModal } = useVnConfirm();
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
const salixUrl = ref();
|
||||||
const transferInvoiceDialogRef = ref();
|
|
||||||
const invoiceFormType = ref('pdf');
|
const invoiceFormType = ref('pdf');
|
||||||
const defaultEmailAddress = ref($props.invoiceOutData.client?.email);
|
const defaultEmailAddress = ref($props.invoiceOutData.client?.email);
|
||||||
|
|
||||||
|
@ -115,6 +121,7 @@ const refundInvoice = async (withWarehouse) => {
|
||||||
try {
|
try {
|
||||||
const params = { ref: $props.invoiceOutData.ref, withWarehouse: withWarehouse };
|
const params = { ref: $props.invoiceOutData.ref, withWarehouse: withWarehouse };
|
||||||
const { data } = await axios.post('InvoiceOuts/refund', params);
|
const { data } = await axios.post('InvoiceOuts/refund', params);
|
||||||
|
location.href = window.origin + `/#/ticket/${data[0].id}/sale`;
|
||||||
jon marked this conversation as resolved
Outdated
jsegarra
commented
podemos probar a usar window.origin en vez de salixURL? podemos probar a usar window.origin en vez de salixURL?
|
|||||||
notify(
|
notify(
|
||||||
t('refundInvoiceSuccessMessage', {
|
t('refundInvoiceSuccessMessage', {
|
||||||
refundTicket: data[0].id,
|
refundTicket: data[0].id,
|
||||||
|
@ -125,11 +132,22 @@ const refundInvoice = async (withWarehouse) => {
|
||||||
console.error('Error generating invoice out pdf', err);
|
console.error('Error generating invoice out pdf', err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showTransferInvoiceForm = async () => {
|
||||||
|
quasar.dialog({
|
||||||
jsegarra marked this conversation as resolved
jsegarra
commented
Ufff... me suena que esto ya pasó una vez y lo corregimos Ufff... me suena que esto ya pasó una vez y lo corregimos
|
|||||||
|
component: TransferInvoiceForm,
|
||||||
|
componentProps: {
|
||||||
|
invoiceOutData: $props.invoiceOutData,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QItem v-ripple clickable @click="transferInvoiceDialogRef.show()">
|
<QItem v-ripple clickable>
|
||||||
<QItemSection>{{ t('Transfer invoice to...') }}</QItemSection>
|
<QItemSection @click="showTransferInvoiceForm()">{{
|
||||||
|
t('Transfer invoice to...')
|
||||||
|
}}</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem v-ripple clickable>
|
<QItem v-ripple clickable>
|
||||||
<QItemSection>{{ t('Show invoice...') }}</QItemSection>
|
<QItemSection>{{ t('Show invoice...') }}</QItemSection>
|
||||||
|
@ -222,10 +240,6 @@ const refundInvoice = async (withWarehouse) => {
|
||||||
{{ t('Create a single ticket with all the content of the current invoice') }}
|
{{ t('Create a single ticket with all the content of the current invoice') }}
|
||||||
</QTooltip>
|
</QTooltip>
|
||||||
</QItem>
|
</QItem>
|
||||||
|
|
||||||
<QDialog ref="transferInvoiceDialogRef">
|
|
||||||
<TransferInvoiceForm :invoice-out-data="invoiceOutData" />
|
|
||||||
</QDialog>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { onMounted, ref, computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { toCurrency, toDate } from 'src/filters';
|
import { toCurrency, toDate, toPercentage } from 'src/filters';
|
||||||
jon marked this conversation as resolved
jsegarra
commented
Hay una traducción que no va bien Hay una traducción que no va bien
|
|||||||
import CardSummary from 'components/ui/CardSummary.vue';
|
import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import { getUrl } from 'src/composables/getUrl';
|
import { getUrl } from 'src/composables/getUrl';
|
||||||
|
@ -57,12 +57,14 @@ const taxColumns = ref([
|
||||||
name: 'quantity',
|
name: 'quantity',
|
||||||
label: 'invoiceOut.summary.rate',
|
label: 'invoiceOut.summary.rate',
|
||||||
field: (row) => row.rate,
|
field: (row) => row.rate,
|
||||||
|
format: (value) => toPercentage(value / 100),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'invoiceOuted',
|
name: 'invoiceOuted',
|
||||||
label: 'invoiceOut.summary.fee',
|
label: 'invoiceOut.summary.fee',
|
||||||
field: (row) => row.vat,
|
field: (row) => row.vat,
|
||||||
|
format: (value) => toCurrency(value),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -113,7 +115,7 @@ const ticketsColumns = ref([
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ entity: { invoiceOut } }">
|
<template #body="{ entity: { invoiceOut } }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle :text="t('invoiceOut.pageTitles.basicData')" />
|
<VnTitle :text="t('globals.pageTitles.basicData')" />
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('invoiceOut.summary.issued')"
|
:label="t('invoiceOut.summary.issued')"
|
||||||
:value="toDate(invoiceOut.issued)"
|
:value="toDate(invoiceOut.issued)"
|
||||||
|
@ -164,7 +166,7 @@ const ticketsColumns = ref([
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-item="{ value }">
|
<template #body-cell-item="{ value }">
|
||||||
<QTd>
|
<QTd>
|
||||||
<QBtn flat color="primary">
|
<QBtn flat class="link">
|
||||||
{{ value }}
|
{{ value }}
|
||||||
<TicketDescriptorProxy :id="value" />
|
<TicketDescriptorProxy :id="value" />
|
||||||
</QBtn>
|
</QBtn>
|
||||||
|
@ -172,7 +174,7 @@ const ticketsColumns = ref([
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-quantity="{ value, row }">
|
<template #body-cell-quantity="{ value, row }">
|
||||||
<QTd>
|
<QTd>
|
||||||
<QBtn class="no-uppercase" flat color="primary" dense>
|
<QBtn class="no-uppercase link" flat dense>
|
||||||
{{ value }}
|
{{ value }}
|
||||||
<CustomerDescriptorProxy :id="row.id" />
|
<CustomerDescriptorProxy :id="row.id" />
|
||||||
</QBtn>
|
</QBtn>
|
||||||
|
|
|
@ -41,7 +41,7 @@ function setWorkers(data) {
|
||||||
<span>{{ formatFn(tag.value) }}</span>
|
<span>{{ formatFn(tag.value) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ params, searchFn }">
|
<template #body="{ params }">
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<VnInput
|
||||||
|
@ -93,7 +93,6 @@ function setWorkers(data) {
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
:label="t('Has PDF')"
|
:label="t('Has PDF')"
|
||||||
@update:model-value="searchFn()"
|
|
||||||
toggle-indeterminate
|
toggle-indeterminate
|
||||||
v-model="params.hasPdf"
|
v-model="params.hasPdf"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -30,7 +30,7 @@ const selectedCustomerId = ref(null);
|
||||||
const tableColumnComponents = {
|
const tableColumnComponents = {
|
||||||
clientId: {
|
clientId: {
|
||||||
component: QBtn,
|
component: QBtn,
|
||||||
props: { flat: true, color: 'blue' },
|
props: { flat: true, class: 'link' },
|
||||||
event: (prop) => selectCustomerId(prop.value),
|
event: (prop) => selectCustomerId(prop.value),
|
||||||
},
|
},
|
||||||
clientName: {
|
clientName: {
|
||||||
|
@ -52,7 +52,12 @@ const tableColumnComponents = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{ label: 'Id', field: 'clientId', name: 'clientId', align: 'left' },
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'clientId',
|
||||||
|
label: 'Id',
|
||||||
|
field: 'clientId',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.globalInvoices.table.client'),
|
label: t('invoiceOut.globalInvoices.table.client'),
|
||||||
field: 'clientName',
|
field: 'clientName',
|
||||||
|
|
|
@ -48,7 +48,7 @@ const getStatus = computed({
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await invoiceOutGlobalStore.init();
|
await invoiceOutGlobalStore.init();
|
||||||
formData.value = { ...formInitialData.value };
|
formData.value = formInitialData.value.invoiceDate;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,96 +1,177 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { onMounted, onUnmounted, ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
|
||||||
import InvoiceOutSummary from './Card/InvoiceOutSummary.vue';
|
|
||||||
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
|
||||||
import CardList from 'src/components/ui/CardList.vue';
|
|
||||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||||
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
|
|
||||||
import CreateManualInvoiceForm from 'src/components/CreateManualInvoiceForm.vue';
|
|
||||||
|
|
||||||
import InvoiceOutFilter from './InvoiceOutFilter.vue';
|
|
||||||
import { toDate, toCurrency } from 'src/filters/index';
|
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
|
||||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
import { useSession } from 'src/composables/useSession';
|
import { usePrintService } from 'composables/usePrintService';
|
||||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
import VnTable from 'components/VnTable/VnTable.vue';
|
||||||
|
import InvoiceOutSummary from './Card/InvoiceOutSummary.vue';
|
||||||
|
import { toCurrency, toDate } from 'src/filters/index';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import { QBtn } from 'quasar';
|
||||||
|
import { watchEffect } from 'vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const session = useSession();
|
|
||||||
const tokenMultimedia = session.getTokenMultimedia();
|
|
||||||
const { viewSummary } = useSummaryDialog();
|
const { viewSummary } = useSummaryDialog();
|
||||||
|
const tableRef = ref();
|
||||||
|
const invoiceOutSerialsOptions = ref([]);
|
||||||
|
const ticketsOptions = ref([]);
|
||||||
|
const customerOptions = ref([]);
|
||||||
|
const selectedRows = ref([]);
|
||||||
|
const hasSelectedCards = computed(() => selectedRows.value.length > 0);
|
||||||
|
const MODEL = 'InvoiceOuts';
|
||||||
|
const { openReport } = usePrintService();
|
||||||
|
|
||||||
const manualInvoiceDialogRef = ref(null);
|
const columns = computed(() => [
|
||||||
const selectedCards = ref(new Map());
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'id',
|
||||||
|
label: t('invoiceOutList.tableVisibleColumns.id'),
|
||||||
|
chip: {
|
||||||
|
condition: () => true,
|
||||||
|
},
|
||||||
|
isId: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'ref',
|
||||||
|
label: t('invoiceOutList.tableVisibleColumns.ref'),
|
||||||
|
isTitle: true,
|
||||||
|
component: 'select',
|
||||||
|
attrs: {
|
||||||
|
url: MODEL,
|
||||||
jon marked this conversation as resolved
Outdated
jsegarra
commented
5 veces aparece la misma url. Propuesta, crear una constante que sea MODEL = 'InvoiceOuts' 5 veces aparece la misma url.
Propuesta, crear una constante que sea MODEL = 'InvoiceOuts'
|
|||||||
|
optionLabel: 'ref',
|
||||||
|
optionValue: 'id',
|
||||||
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'Issued',
|
||||||
|
label: t('invoiceOutList.tableVisibleColumns.issued'),
|
||||||
|
component: 'date',
|
||||||
|
format: (row) => toDate(row.issued),
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'clientSocialName',
|
||||||
|
label: t('invoiceOutModule.customer'),
|
||||||
|
cardVisible: true,
|
||||||
|
component: 'select',
|
||||||
|
attrs: {
|
||||||
|
url: 'Clients',
|
||||||
|
fields: ['id', 'name'],
|
||||||
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'companyCode',
|
||||||
|
label: t('invoiceOutModule.company'),
|
||||||
|
cardVisible: true,
|
||||||
|
component: 'select',
|
||||||
|
attrs: {
|
||||||
|
url: 'Companies',
|
||||||
|
optionLabel: 'code',
|
||||||
|
optionValue: 'id',
|
||||||
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'amount',
|
||||||
|
label: t('invoiceOutModule.amount'),
|
||||||
|
cardVisible: true,
|
||||||
|
format: (row) => toCurrency(row.amount),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'created',
|
||||||
|
label: t('invoiceOutList.tableVisibleColumns.created'),
|
||||||
|
component: 'date',
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
format: (row) => toDate(row.created),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'dued',
|
||||||
|
label: t('invoiceOutList.tableVisibleColumns.dueDate'),
|
||||||
|
component: 'date',
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
format: (row) => toDate(row.dued),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'right',
|
||||||
|
name: 'tableActions',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
title: t('InvoiceOutSummary'),
|
||||||
jsegarra marked this conversation as resolved
jsegarra
commented
Si no pones label, no se rompe nada. Si no pones label, no se rompe nada.
Yo también he pecado de lo mismo
|
|||||||
|
icon: 'preview',
|
||||||
|
action: (row) => viewSummary(row.id, InvoiceOutSummary),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('DownloadPdf'),
|
||||||
|
icon: 'vn:ticket',
|
||||||
|
isPrimary: true,
|
||||||
|
action: (row) => openPdf(row.id),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
onMounted(() => (stateStore.rightDrawer = true));
|
onMounted(() => (stateStore.rightDrawer = true));
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
|
|
||||||
function navigate(id) {
|
function openPdf(id) {
|
||||||
router.push({ path: `/invoice-out/${id}` });
|
try {
|
||||||
|
openReport(`${MODEL}/${id}/download`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error opening PDF', err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleIndividualCard = (cardData) => {
|
function downloadPdf() {
|
||||||
if (selectedCards.value.has(cardData.id)) {
|
|
||||||
selectedCards.value.delete(cardData.id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
selectedCards.value.set(cardData.id, cardData);
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleAllCards = (cardsData) => {
|
|
||||||
const allSelected = selectedCards.value.size === cardsData.length;
|
|
||||||
|
|
||||||
if (!allSelected) {
|
|
||||||
// Si no todas las tarjetas están seleccionadas, selecciónalas todas
|
|
||||||
cardsData.forEach((data) => {
|
|
||||||
if (!selectedCards.value.has(data.id)) {
|
|
||||||
selectedCards.value.set(data.id, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Si todas las tarjetas están seleccionadas, deselecciónalas todas
|
|
||||||
selectedCards.value.clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const openPdf = () => {
|
|
||||||
try {
|
try {
|
||||||
if (selectedCards.value.size === 0) return;
|
if (selectedRows.value.size === 0) return;
|
||||||
jon marked this conversation as resolved
Outdated
jsegarra
commented
hay un composable que hace justo esto. En la línea 170 también hay un composable que hace justo esto.
Se llama usePrintservice
Pruébalo y sino cumple las necesidades, vemos si aplicarlo o no
En la línea 170 también
|
|||||||
const selectedCardsArray = Array.from(selectedCards.value.values());
|
const selectedCardsArray = Array.from(selectedRows.value.values());
|
||||||
|
|
||||||
if (selectedCards.value.size === 1) {
|
if (selectedRows.value.size === 1) {
|
||||||
const [invoiceOut] = selectedCardsArray;
|
const [invoiceOut] = selectedCardsArray;
|
||||||
const url = `api/InvoiceOuts/${invoiceOut.id}/download?access_token=${tokenMultimedia}`;
|
openPdf(invoiceOut.id);
|
||||||
window.open(url, '_blank');
|
|
||||||
} else {
|
} else {
|
||||||
const invoiceOutIdsArray = selectedCardsArray.map(
|
const invoiceOutIdsArray = selectedCardsArray.map(
|
||||||
(invoiceOut) => invoiceOut.id
|
(invoiceOut) => invoiceOut.id
|
||||||
);
|
);
|
||||||
const invoiceOutIds = invoiceOutIdsArray.join(',');
|
const invoiceOutIds = invoiceOutIdsArray.join(',');
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
const params = {
|
||||||
access_token: tokenMultimedia,
|
|
||||||
ids: invoiceOutIds,
|
ids: invoiceOutIds,
|
||||||
});
|
};
|
||||||
|
|
||||||
const url = `api/InvoiceOuts/downloadZip?${params}`;
|
openReport(`${MODEL}/downloadZip`, params);
|
||||||
window.open(url, '_blank');
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error opening PDF');
|
console.error('Error opening PDF');
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
Eliminar comentarios Eliminar comentarios
|
|||||||
const openCreateInvoiceModal = () => {
|
watchEffect(selectedRows);
|
||||||
manualInvoiceDialogRef.value.show();
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -99,115 +180,84 @@ const openCreateInvoiceModal = () => {
|
||||||
:label="t('searchInvoice')"
|
:label="t('searchInvoice')"
|
||||||
data-key="InvoiceOutList"
|
data-key="InvoiceOutList"
|
||||||
/>
|
/>
|
||||||
<RightMenu>
|
<VnSubToolbar>
|
||||||
<template #right-panel>
|
<template #st-actions>
|
||||||
<InvoiceOutFilter data-key="InvoiceOutList" />
|
<QBtn
|
||||||
|
color="primary"
|
||||||
|
icon-right="cloud_download"
|
||||||
|
@click="downloadPdf()"
|
||||||
|
:disable="!hasSelectedCards"
|
||||||
|
>
|
||||||
|
<QTooltip>{{ t('globals.downloadPdf') }}</QTooltip>
|
||||||
|
</QBtn>
|
||||||
</template>
|
</template>
|
||||||
</RightMenu>
|
</VnSubToolbar>
|
||||||
<QPage>
|
<VnTable
|
||||||
<VnPaginate
|
ref="tableRef"
|
||||||
auto-load
|
data-key="invoiceOut"
|
||||||
data-key="InvoiceOutList"
|
:url="`${MODEL}/filter`"
|
||||||
:order="['issued DESC', 'id DESC']"
|
:create="{
|
||||||
url="InvoiceOuts/filter"
|
urlCreate: 'InvoiceOuts/createManualInvoice',
|
||||||
>
|
title: t('Create Manual Invoice'),
|
||||||
<template #body="{ rows }">
|
onDataSaved: ({ id }) => tableRef.redirect(id),
|
||||||
<VnSubToolbar class="justify-end">
|
formInitialData: {
|
||||||
<template #st-actions>
|
active: true,
|
||||||
<QBtn
|
},
|
||||||
@click="openPdf()"
|
}"
|
||||||
class="q-mr-md"
|
v-model:selected="selectedRows"
|
||||||
color="primary"
|
order="id DESC"
|
||||||
icon="cloud_download"
|
:columns="columns"
|
||||||
:disable="selectedCards.size === 0"
|
default-mode="table"
|
||||||
>
|
redirect="invoice-out"
|
||||||
<QTooltip>{{ t('globals.downloadPdf') }}</QTooltip>
|
auto-load
|
||||||
</QBtn>
|
:table="{
|
||||||
<QCheckbox
|
'row-key': 'id',
|
||||||
left-label
|
selection: 'multiple',
|
||||||
:label="t('globals.markAll')"
|
}"
|
||||||
@click="toggleAllCards(rows)"
|
>
|
||||||
:model-value="selectedCards.size === rows.length"
|
<template #more-create-dialog="{ data }">
|
||||||
class="q-mr-md"
|
<VnSelect
|
||||||
/>
|
url="Tickets"
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
Duda: era q-table o table? Duda: era q-table o table?
|
|||||||
</template>
|
v-model="data.ticketFk"
|
||||||
</VnSubToolbar>
|
:label="t('invoiceOutList.tableVisibleColumns.ticket')"
|
||||||
<div class="flex flex-center q-pa-md">
|
:options="ticketsOptions"
|
||||||
<div class="vn-card-list">
|
option-label="nickname"
|
||||||
<CardList
|
option-value="id"
|
||||||
:element="row"
|
/>
|
||||||
:id="row.id"
|
<VnSelect
|
||||||
:show-checkbox="true"
|
url="Clients"
|
||||||
:is-selected="selectedCards.has(row.id)"
|
v-model="data.clientFk"
|
||||||
:key="row.id"
|
:label="t('invoiceOutModule.customer')"
|
||||||
:title="row.ref"
|
:options="customerOptions"
|
||||||
@click="navigate(row.id)"
|
option-label="name"
|
||||||
@toggle-card-check="toggleIndividualCard(row)"
|
option-value="id"
|
||||||
v-for="row of rows"
|
/>
|
||||||
>
|
<VnInputDate
|
||||||
<template #list-items>
|
:label="t('invoiceOutList.tableVisibleColumns.dueDate')"
|
||||||
<VnLv
|
v-model="data.maxShipped"
|
||||||
:label="t('invoiceOut.list.issued')"
|
/>
|
||||||
:value="toDate(row.issued)"
|
<VnSelect
|
||||||
/>
|
url="InvoiceOutSerials"
|
||||||
<VnLv
|
v-model="data.invoiceOutSerial"
|
||||||
:label="t('invoiceOut.list.amount')"
|
:label="t('invoiceOutList.tableVisibleColumns.invoiceOutSerial')"
|
||||||
:value="toCurrency(row.amount)"
|
:options="invoiceOutSerialsOptions"
|
||||||
/>
|
option-label="description"
|
||||||
<VnLv :label="t('invoiceOut.list.client')">
|
option-value="code"
|
||||||
<template #value>
|
/>
|
||||||
<span class="link" @click.stop>
|
<VnSelect
|
||||||
{{ row?.clientSocialName }}
|
url="TaxAreas"
|
||||||
<CustomerDescriptorProxy
|
v-model="data.area"
|
||||||
:id="row?.clientFk"
|
:label="t('invoiceOutList.tableVisibleColumns.taxArea')"
|
||||||
/>
|
:options="taxAreasOptions"
|
||||||
</span>
|
option-label="code"
|
||||||
</template>
|
option-value="code"
|
||||||
</VnLv>
|
/>
|
||||||
<VnLv
|
<QInput
|
||||||
:label="t('invoiceOut.list.shortCreated')"
|
v-model="data.reference"
|
||||||
:title-label="t('invoiceOut.list.created')"
|
:label="t('invoiceOutList.tableVisibleColumns.ref')"
|
||||||
:value="toDate(row.created)"
|
/>
|
||||||
/>
|
</template>
|
||||||
<VnLv
|
</VnTable>
|
||||||
:label="t('invoiceOut.list.company')"
|
|
||||||
:value="row.companyCode"
|
|
||||||
/>
|
|
||||||
<VnLv
|
|
||||||
:label="t('invoiceOut.list.shortDued')"
|
|
||||||
:title-label="t('invoiceOut.list.dued')"
|
|
||||||
:value="toDate(row.dued)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #actions>
|
|
||||||
<QBtn
|
|
||||||
:label="t('components.smartCard.openSummary')"
|
|
||||||
@click.stop="viewSummary(row.id, InvoiceOutSummary)"
|
|
||||||
color="primary"
|
|
||||||
style="margin-top: 15px"
|
|
||||||
type="submit"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</CardList>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</VnPaginate>
|
|
||||||
<QPageSticky :offset="[20, 20]">
|
|
||||||
<QBtn fab icon="add" color="primary" @click="openCreateInvoiceModal()" />
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('createInvoice') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QPageSticky>
|
|
||||||
|
|
||||||
<QDialog
|
|
||||||
ref="manualInvoiceDialogRef"
|
|
||||||
transition-show="scale"
|
|
||||||
transition-hide="scale"
|
|
||||||
>
|
|
||||||
<CreateManualInvoiceForm />
|
|
||||||
</QDialog>
|
|
||||||
</QPage>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -1,200 +1,177 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onBeforeMount } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
|
||||||
import InvoiceOutNegativeFilter from './InvoiceOutNegativeBasesFilter.vue';
|
|
||||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
|
||||||
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
|
|
||||||
import { toCurrency } from 'src/filters';
|
import { toCurrency } from 'src/filters';
|
||||||
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
import { useInvoiceOutGlobalStore } from 'src/stores/invoiceOutGlobal.js';
|
import { useInvoiceOutGlobalStore } from 'src/stores/invoiceOutGlobal.js';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import { useArrayData } from 'composables/useArrayData';
|
|
||||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
|
||||||
|
|
||||||
const invoiceOutGlobalStore = useInvoiceOutGlobalStore();
|
|
||||||
const stateStore = useStateStore();
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const tableRef = ref();
|
||||||
const arrayData = useArrayData('InvoiceOutNegative', {
|
const invoiceOutGlobalStore = useInvoiceOutGlobalStore();
|
||||||
url: 'InvoiceOuts/negativeBases',
|
const userParams = {
|
||||||
limit: 0,
|
from: Date.vnFirstDayOfMonth().toISOString(),
|
||||||
userParams: {
|
to: Date.vnLastDayOfMonth().toISOString(),
|
||||||
from: Date.vnFirstDayOfMonth().toISOString(),
|
};
|
||||||
jsegarra marked this conversation as resolved
jon
commented
Se ha decidido dejar así para no hacer dos llamadas iguales(la del Vntable y la del arrayData) Se ha decidido dejar así para no hacer dos llamadas iguales(la del Vntable y la del arrayData)
|
|||||||
to: Date.vnLastDayOfMonth().toISOString(),
|
useArrayData('InvoiceOutNegative', { userParams });
|
||||||
},
|
|
||||||
exprBuilder: (param, value) => {
|
|
||||||
switch (param) {
|
|
||||||
case 'from':
|
|
||||||
case 'to':
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
return { [param]: value };
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
|
||||||
await arrayData.fetch({ append: false });
|
|
||||||
stateStore.rightDrawer = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.company'),
|
align: 'left',
|
||||||
field: 'company',
|
|
||||||
name: 'company',
|
name: 'company',
|
||||||
align: 'left',
|
label: t('invoiceOutModule.company'),
|
||||||
|
component: 'select',
|
||||||
|
cardVisible: true,
|
||||||
|
attrs: {
|
||||||
|
url: 'Companies',
|
||||||
|
optionLabel: 'code',
|
||||||
|
optionValue: 'id',
|
||||||
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.country'),
|
align: 'left',
|
||||||
field: 'country',
|
|
||||||
name: 'country',
|
name: 'country',
|
||||||
align: 'left',
|
label: t('negativeBases.country'),
|
||||||
|
component: 'select',
|
||||||
|
attrs: {
|
||||||
|
url: 'Countries',
|
||||||
|
optionLabel: 'name',
|
||||||
|
optionValue: 'id',
|
||||||
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.clientId'),
|
align: 'left',
|
||||||
field: 'clientId',
|
|
||||||
name: 'clientId',
|
name: 'clientId',
|
||||||
align: 'left',
|
label: t('negativeBases.clientId'),
|
||||||
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.client'),
|
|
||||||
field: 'clientSocialName',
|
|
||||||
name: 'client',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
name: 'clientSocialName',
|
||||||
|
label: t('invoiceOutModule.customer'),
|
||||||
|
component: 'select',
|
||||||
|
isTitle: true,
|
||||||
|
cardVisible: true,
|
||||||
|
attrs: {
|
||||||
|
url: 'Clients',
|
||||||
|
fields: ['id', 'name'],
|
||||||
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.amount'),
|
align: 'left',
|
||||||
field: 'amount',
|
|
||||||
name: 'amount',
|
name: 'amount',
|
||||||
align: 'left',
|
label: t('invoiceOutModule.amount'),
|
||||||
format: (value) => toCurrency(value),
|
format: (row) => toCurrency(row.amount),
|
||||||
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.base'),
|
|
||||||
field: 'taxableBase',
|
|
||||||
name: 'base',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
name: 'taxableBase',
|
||||||
|
label: t('negativeBases.base'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.ticketId'),
|
|
||||||
field: 'ticketFk',
|
|
||||||
name: 'ticketId',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
name: 'ticketFk',
|
||||||
|
label: t('negativeBases.ticketId'),
|
||||||
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.active'),
|
|
||||||
field: 'isActive',
|
|
||||||
name: 'active',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
name: 'isActive',
|
||||||
|
label: t('negativeBases.active'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.hasToInvoice'),
|
align: 'left',
|
||||||
field: 'hasToInvoice',
|
|
||||||
name: 'hasToInvoice',
|
name: 'hasToInvoice',
|
||||||
align: 'left',
|
label: t('negativeBases.hasToInvoice'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.verifiedData'),
|
|
||||||
field: 'isTaxDataChecked',
|
|
||||||
name: 'verifiedData',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
name: 'hasVerifiedData',
|
||||||
|
label: t('negativeBases.verifiedData'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('invoiceOut.negativeBases.comercial'),
|
|
||||||
field: 'workerName',
|
|
||||||
name: 'worker',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
label: t('customer.extendedList.tableVisibleColumns.salesPersonFk'),
|
||||||
|
name: 'workerName',
|
||||||
|
component: 'select',
|
||||||
|
attrs: {
|
||||||
|
url: 'Workers/activeWithInheritedRole',
|
||||||
|
fields: ['id', 'name'],
|
||||||
|
where: { role: 'salesPerson' },
|
||||||
|
},
|
||||||
|
columnField: {
|
||||||
|
component: null,
|
||||||
|
},
|
||||||
|
format: (row, dashIfEmpty) => dashIfEmpty(row.workerName),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const downloadCSV = async () => {
|
const downloadCSV = async () => {
|
||||||
const params = {}; // filter.value;
|
|
||||||
const filterParams = {
|
const filterParams = {
|
||||||
limit: 20,
|
limit: 20,
|
||||||
where: {
|
where: {
|
||||||
and: [],
|
and: [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
for (const param in params) {
|
|
||||||
if (params[param]) filterParams.where.and.push({ [param]: params[param] });
|
for (const [key, value] of Object.entries(userParams)) {
|
||||||
|
if (value) {
|
||||||
|
filterParams.where.and.push({ [key]: value });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await invoiceOutGlobalStore.getNegativeBasesCsv(
|
await invoiceOutGlobalStore.getNegativeBasesCsv(
|
||||||
arrayData.value.store.userParams.from,
|
userParams.from,
|
||||||
arrayData.value.store.userParams.to,
|
userParams.to,
|
||||||
params
|
filterParams
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnSubToolbar>
|
<VnSubToolbar>
|
||||||
<template #st-actions>
|
<template #st-actions>
|
||||||
<QBtn color="primary" icon-right="download" no-caps @click="downloadCSV()">
|
<QBtn color="primary" icon-right="download" @click="downloadCSV()">
|
||||||
<QTooltip>{{ t('Download as CSV') }}</QTooltip>
|
<QTooltip>{{ t('Download as CSV') }}</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</template>
|
</template>
|
||||||
</VnSubToolbar>
|
</VnSubToolbar>
|
||||||
<RightMenu>
|
<VnTable
|
||||||
<template #right-panel>
|
ref="tableRef"
|
||||||
<InvoiceOutNegativeFilter data-key="InvoiceOutNegative" />
|
data-key="negativeFilter"
|
||||||
</template>
|
url="InvoiceOuts/negativeBases"
|
||||||
</RightMenu>
|
:user-params="userParams"
|
||||||
<QPage class="column items-center q-pa-md">
|
:expr-builder="
|
||||||
<QTable
|
(param, value) => {
|
||||||
:columns="columns"
|
switch (param) {
|
||||||
:rows="arrayData.store.data"
|
case 'from':
|
||||||
row-key="clientId"
|
case 'to':
|
||||||
class="full-width q-mt-md"
|
return;
|
||||||
>
|
default:
|
||||||
<template #body-cell-clientId="{ row }">
|
return { [param]: value };
|
||||||
<QTd>
|
}
|
||||||
<QBtn flat dense class="link"> {{ row.clientId }}</QBtn>
|
}
|
||||||
<CustomerDescriptorProxy :id="row.clientId" />
|
"
|
||||||
</QTd>
|
:limit="0"
|
||||||
</template>
|
:columns="columns"
|
||||||
<template #body-cell-ticketId="{ row }">
|
default-mode="table"
|
||||||
<QTd>
|
auto-load
|
||||||
<QBtn flat dense class="link"> {{ row.ticketFk }}</QBtn>
|
:is-editable="false"
|
||||||
<TicketDescriptorProxy :id="row.ticketFk" />
|
:use-model="true"
|
||||||
</QTd>
|
>
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
👀 👀
|
|||||||
</template>
|
</VnTable>
|
||||||
<template #body-cell-worker="{ row }">
|
|
||||||
<QTd>
|
|
||||||
<QBtn class="no-uppercase link" flat dense>{{ row.workerName }}</QBtn>
|
|
||||||
<WorkerDescriptorProxy :id="row.comercialId" />
|
|
||||||
</QTd>
|
|
||||||
</template>
|
|
||||||
<template #body-cell-active="{ row }">
|
|
||||||
<QTd>
|
|
||||||
<QCheckbox :model-value="!!row.isActive" disable />
|
|
||||||
</QTd>
|
|
||||||
</template>
|
|
||||||
<template #body-cell-hasToInvoice="{ row }">
|
|
||||||
<QTd>
|
|
||||||
<QCheckbox :model-value="!!row.hasToInvoice" disable />
|
|
||||||
</QTd>
|
|
||||||
</template>
|
|
||||||
<template #body-cell-verifiedData="{ row }">
|
|
||||||
<QTd>
|
|
||||||
<QCheckbox :model-value="!!row.isTaxDataChecked" disable />
|
|
||||||
</QTd>
|
|
||||||
</template>
|
|
||||||
</QTable>
|
|
||||||
</QPage>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.col-content {
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 6px;
|
|
||||||
}
|
|
||||||
.no-uppercase {
|
|
||||||
text-transform: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Download as CSV: Descargar como CSV
|
Download as CSV: Descargar como CSV
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
invoiceOutModule:
|
||||||
|
customer: Client
|
||||||
|
amount: Amount
|
||||||
|
company: Company
|
||||||
|
invoiceOutList:
|
||||||
|
tableVisibleColumns:
|
||||||
|
id: ID
|
||||||
|
ref: Reference
|
||||||
|
issued: Issued
|
||||||
|
created: Created
|
||||||
|
dueDate: Max date
|
||||||
|
invoiceOutSerial: Serial
|
||||||
|
ticket: Ticket
|
||||||
|
taxArea: Tax area
|
||||||
|
DownloadPdf: Download PDF
|
||||||
|
InvoiceOutSummary: Summary
|
||||||
|
negativeBases:
|
||||||
|
country: Country
|
||||||
|
clientId: Client ID
|
||||||
|
base: Base
|
||||||
|
ticketId: Ticket
|
||||||
|
active: Active
|
||||||
|
hasToInvoice: Has to invoice
|
||||||
|
verifiedData: Verified data
|
||||||
|
commercial: Commercial
|
|
@ -1,2 +1,31 @@
|
||||||
Search invoice: Buscar factura emitida
|
Search invoice: Buscar factura emitida
|
||||||
You can search by invoice reference: Puedes buscar por referencia de la factura
|
You can search by invoice reference: Puedes buscar por referencia de la factura
|
||||||
|
invoiceOutModule:
|
||||||
|
customer: Cliente
|
||||||
|
amount: Importe
|
||||||
|
company: Empresa
|
||||||
|
invoiceOutList:
|
||||||
|
tableVisibleColumns:
|
||||||
|
id: ID
|
||||||
|
ref: Referencia
|
||||||
|
issued: Fecha emisión
|
||||||
|
customer: Cliente
|
||||||
|
company: Empresa
|
||||||
|
amount: Importe
|
||||||
|
created: F. creación
|
||||||
|
dueDate: F. máxima
|
||||||
|
invoiceOutSerial: Serial
|
||||||
|
ticket: Ticket
|
||||||
|
taxArea: Area
|
||||||
|
DownloadPdf: Descargar PDF
|
||||||
|
InvoiceOutSummary: Resumen
|
||||||
|
negativeBases:
|
||||||
|
country: País
|
||||||
|
clientId: ID del cliente
|
||||||
|
client: Cliente
|
||||||
|
base: Base
|
||||||
|
ticketId: Ticket
|
||||||
|
active: Activo
|
||||||
|
hasToInvoice: Debe facturar
|
||||||
|
verifiedData: Datos verificados
|
||||||
|
commercial: Comercial
|
|
@ -35,7 +35,7 @@ export default {
|
||||||
name: 'InvoiceOutGlobal',
|
name: 'InvoiceOutGlobal',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'globalInvoicing',
|
title: 'globalInvoicing',
|
||||||
icon: 'contact_support',
|
icon: 'Date_Range',
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/InvoiceOut/InvoiceOutGlobal.vue'),
|
component: () => import('src/pages/InvoiceOut/InvoiceOutGlobal.vue'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -237,7 +237,7 @@ export const useInvoiceOutGlobalStore = defineStore({
|
||||||
async getNegativeBasesCsv() {
|
async getNegativeBasesCsv() {
|
||||||
try {
|
try {
|
||||||
const arrayData = useArrayData('InvoiceOutNegative');
|
const arrayData = useArrayData('InvoiceOutNegative');
|
||||||
const params = arrayData.store.currentFilter;
|
const params = arrayData.store.userParams;
|
||||||
jon
commented
Debido al cambio en el uso de arrayData en negativeBases la store deja de tener currentFitler, y le pasa los userParams declarados Debido al cambio en el uso de arrayData en negativeBases la store deja de tener currentFitler, y le pasa los userParams declarados
|
|||||||
|
|
||||||
const { data } = await axios.get('InvoiceOuts/negativeBasesCsv', {
|
const { data } = await axios.get('InvoiceOuts/negativeBasesCsv', {
|
||||||
params,
|
params,
|
||||||
|
|
Loading…
Reference in New Issue
Has probado a usar FormPopupDialog?