423 lines
14 KiB
Vue
423 lines
14 KiB
Vue
<script setup>
|
|
import { onMounted, ref, computed } from 'vue';
|
|
import { useRoute } from 'vue-router';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { toCurrency, toDate } from 'src/filters';
|
|
import { getUrl } from 'src/composables/getUrl';
|
|
import CardSummary from 'components/ui/CardSummary.vue';
|
|
import VnLv from 'src/components/ui/VnLv.vue';
|
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
|
|
|
onMounted(async () => {
|
|
salixUrl.value = await getUrl('');
|
|
invoiceInUrl.value = salixUrl.value + `invoiceIn/${entityId.value}/`;
|
|
});
|
|
|
|
const route = useRoute();
|
|
const { t } = useI18n();
|
|
|
|
const $props = defineProps({
|
|
id: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
});
|
|
|
|
const entityId = computed(() => $props.id || route.params.id);
|
|
|
|
const salixUrl = ref();
|
|
const invoiceInUrl = ref();
|
|
const amountsNotMatch = ref(null);
|
|
const intrastatTotals = ref({});
|
|
|
|
const vatColumns = ref([
|
|
{
|
|
name: 'expense',
|
|
label: 'invoiceIn.summary.expense',
|
|
field: (row) => row.expenseFk,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'landed',
|
|
label: 'invoiceIn.summary.taxableBase',
|
|
field: (row) => row.taxableBase,
|
|
format: (value) => toCurrency(value),
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'vat',
|
|
label: 'invoiceIn.summary.sageVat',
|
|
field: (row) => row.taxTypeSage?.vat,
|
|
format: (value) => value,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'transaction',
|
|
label: 'invoiceIn.summary.sageTransaction',
|
|
field: (row) => row.transactionTypeSage?.transaction,
|
|
format: (value) => value,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'rate',
|
|
label: 'invoiceIn.summary.rate',
|
|
field: (row) => taxRate(row.taxableBase, row.taxTypeSage?.rate),
|
|
format: (value) => toCurrency(value),
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'currency',
|
|
label: 'invoiceIn.summary.currency',
|
|
field: (row) => row.foreignValue,
|
|
format: (value) => value,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
]);
|
|
|
|
const dueDayColumns = ref([
|
|
{
|
|
name: 'date',
|
|
label: 'invoiceIn.summary.dueDay',
|
|
field: (row) => toDate(row.dueDated),
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'bank',
|
|
label: 'invoiceIn.summary.bank',
|
|
field: (row) => row.bank.bank,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'amount',
|
|
label: 'invoiceIn.summary.amount',
|
|
field: (row) => row.amount,
|
|
format: (value) => toCurrency(value),
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'landed',
|
|
label: 'invoiceIn.summary.foreignValue',
|
|
field: (row) => row.foreignValue,
|
|
format: (value) => value,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
]);
|
|
|
|
const intrastatColumns = ref([
|
|
{
|
|
name: 'code',
|
|
label: 'invoiceIn.summary.code',
|
|
field: (row) => {
|
|
return `${row.intrastat.id}: ${row.intrastat?.description}`;
|
|
},
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'amount',
|
|
label: 'invoiceIn.summary.amount',
|
|
field: (row) => toCurrency(row.amount),
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'net',
|
|
label: 'invoiceIn.summary.net',
|
|
field: (row) => row.net,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'stems',
|
|
label: 'invoiceIn.summary.stems',
|
|
field: (row) => row.stems,
|
|
format: (value) => value,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'landed',
|
|
label: 'invoiceIn.summary.country',
|
|
field: (row) => row.country?.code,
|
|
format: (value) => value,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
]);
|
|
|
|
function getAmountNotMatch(totals) {
|
|
return (
|
|
totals.totalDueDay != totals.totalTaxableBase &&
|
|
totals.totalDueDay != totals.totalVat
|
|
);
|
|
}
|
|
|
|
function getIntrastatTotals(intrastat) {
|
|
const totals = {
|
|
amount: intrastat.reduce((acc, cur) => acc + cur.amount, 0),
|
|
net: intrastat.reduce((acc, cur) => acc + cur.net, 0),
|
|
stems: intrastat.reduce((acc, cur) => acc + cur.stems, 0),
|
|
};
|
|
|
|
return totals;
|
|
}
|
|
|
|
function getTaxTotal(tax) {
|
|
return tax.reduce(
|
|
(acc, cur) => acc + taxRate(cur.taxableBase, cur.taxTypeSage?.rate),
|
|
0
|
|
);
|
|
}
|
|
|
|
function setData(entity) {
|
|
if (!entity) return false;
|
|
|
|
amountsNotMatch.value = getAmountNotMatch(entity.totals);
|
|
|
|
if (entity.invoiceInIntrastat.length)
|
|
intrastatTotals.value = { ...getIntrastatTotals(entity.invoiceInIntrastat) };
|
|
}
|
|
|
|
function taxRate(taxableBase = 0, rate = 0) {
|
|
return (rate / 100) * taxableBase;
|
|
}
|
|
|
|
function getLink(param) {
|
|
return `#/invoice-in/${entityId.value}/${param}`;
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<CardSummary
|
|
data-key="InvoiceInSummary"
|
|
:url="`InvoiceIns/${entityId}/summary`"
|
|
@on-fetch="(data) => setData(data)"
|
|
>
|
|
<template #header="{ entity: invoiceIn }">
|
|
<div>{{ invoiceIn.id }} - {{ invoiceIn.supplier?.name }}</div>
|
|
</template>
|
|
<template #body="{ entity: invoiceIn }">
|
|
<!--Basic Data-->
|
|
<QCard class="vn-one">
|
|
<QCardSection class="q-pa-none">
|
|
<VnTitle
|
|
:url="getLink('basic-data')"
|
|
:text="t('invoiceIn.pageTitles.basicData')"
|
|
/>
|
|
</QCardSection>
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.supplier')"
|
|
:value="invoiceIn.supplier?.name"
|
|
/>
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.supplierRef')"
|
|
:value="invoiceIn.supplierRef"
|
|
/>
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.currency')"
|
|
:value="invoiceIn.currency?.code"
|
|
/>
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.docNumber')"
|
|
:value="`${invoiceIn.serial}/${invoiceIn.serialNumber}`"
|
|
/>
|
|
</QCard>
|
|
<QCard class="vn-one">
|
|
<QCardSection class="q-pa-none">
|
|
<VnTitle
|
|
:url="getLink('basic-data')"
|
|
:text="t('invoiceIn.pageTitles.basicData')"
|
|
/>
|
|
</QCardSection>
|
|
<VnLv
|
|
:ellipsis-value="false"
|
|
:label="t('invoiceIn.summary.issued')"
|
|
:value="toDate(invoiceIn.issued)"
|
|
/>
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.operated')"
|
|
:value="toDate(invoiceIn.operated)"
|
|
/>
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.bookEntried')"
|
|
:value="toDate(invoiceIn.bookEntried)"
|
|
/>
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.bookedDate')"
|
|
:value="toDate(invoiceIn.booked)"
|
|
/>
|
|
</QCard>
|
|
<QCard class="vn-one">
|
|
<QCardSection class="q-pa-none">
|
|
<VnTitle
|
|
:url="getLink('basic-data')"
|
|
:text="t('invoiceIn.pageTitles.basicData')"
|
|
/>
|
|
</QCardSection>
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.sage')"
|
|
:value="invoiceIn.sageWithholding?.withholding"
|
|
/>
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.vat')"
|
|
:value="invoiceIn.expenseDeductible?.name"
|
|
/>
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.company')"
|
|
:value="invoiceIn.company?.code"
|
|
/>
|
|
<QCheckbox
|
|
:label="t('invoiceIn.summary.booked')"
|
|
v-model="invoiceIn.isBooked"
|
|
:disable="true"
|
|
/>
|
|
</QCard>
|
|
<QCard class="vn-one">
|
|
<QCardSection class="q-pa-none">
|
|
<VnTitle
|
|
:url="getLink('basic-data')"
|
|
:text="t('invoiceIn.pageTitles.basicData')"
|
|
/>
|
|
</QCardSection>
|
|
<QCardSection class="q-pa-none">
|
|
<div class="bordered q-px-sm q-mx-auto">
|
|
<VnLv
|
|
:label="t('invoiceIn.summary.taxableBase')"
|
|
:value="toCurrency(invoiceIn.totals.totalTaxableBase)"
|
|
/>
|
|
<VnLv
|
|
label="Total"
|
|
:value="toCurrency(invoiceIn.totals.totalVat)"
|
|
/>
|
|
<VnLv :label="t('invoiceIn.summary.dueTotal')">
|
|
<template #value>
|
|
<QChip
|
|
dense
|
|
class="q-pa-xs"
|
|
:color="amountsNotMatch ? 'negative' : 'transparent'"
|
|
:title="
|
|
amountsNotMatch
|
|
? t('invoiceIn.summary.noMatch')
|
|
: t('invoiceIn.summary.dueTotal')
|
|
"
|
|
>
|
|
{{ toCurrency(invoiceIn.totals.totalDueDay) }}
|
|
</QChip>
|
|
</template>
|
|
</VnLv>
|
|
</div>
|
|
</QCardSection>
|
|
</QCard>
|
|
<!--Vat-->
|
|
<QCard v-if="invoiceIn.invoiceInTax.length">
|
|
<VnTitle :url="getLink('vat')" :text="t('invoiceIn.card.vat')" />
|
|
<QTable
|
|
:columns="vatColumns"
|
|
:rows="invoiceIn.invoiceInTax"
|
|
flat
|
|
hide-pagination
|
|
>
|
|
<template #header="props">
|
|
<QTr :props="props" class="bg">
|
|
<QTh v-for="col in props.cols" :key="col.name" :props="props">
|
|
{{ t(col.label) }}
|
|
</QTh>
|
|
</QTr>
|
|
</template>
|
|
<template #bottom-row>
|
|
<QTr class="bg">
|
|
<QTd></QTd>
|
|
<QTd>{{ toCurrency(invoiceIn.totals.totalTaxableBase) }}</QTd>
|
|
<QTd></QTd>
|
|
<QTd></QTd>
|
|
<QTd>{{
|
|
toCurrency(getTaxTotal(invoiceIn.invoiceInTax))
|
|
}}</QTd>
|
|
<QTd></QTd>
|
|
</QTr>
|
|
</template>
|
|
</QTable>
|
|
</QCard>
|
|
<!--Due Day-->
|
|
<QCard v-if="invoiceIn.invoiceInDueDay.length">
|
|
<VnTitle :url="getLink('due-day')" :text="t('invoiceIn.card.dueDay')" />
|
|
<QTable
|
|
class="full-width"
|
|
:columns="dueDayColumns"
|
|
:rows="invoiceIn.invoiceInDueDay"
|
|
flat
|
|
>
|
|
<template #header="props">
|
|
<QTr :props="props" class="bg">
|
|
<QTh v-for="col in props.cols" :key="col.name" :props="props">
|
|
{{ t(col.label) }}
|
|
</QTh>
|
|
</QTr>
|
|
</template>
|
|
<template #bottom-row>
|
|
<QTr class="bg">
|
|
<QTd></QTd>
|
|
<QTd></QTd>
|
|
<QTd>{{ toCurrency(invoiceIn.totals.totalDueDay) }}</QTd>
|
|
<QTd></QTd>
|
|
</QTr>
|
|
</template>
|
|
</QTable>
|
|
</QCard>
|
|
<!--Intrastat-->
|
|
<QCard v-if="invoiceIn.invoiceInIntrastat.length">
|
|
<VnTitle
|
|
:url="getLink('intrastat')"
|
|
:text="t('invoiceIn.card.intrastat')"
|
|
/>
|
|
<QTable
|
|
:columns="intrastatColumns"
|
|
:rows="invoiceIn.invoiceInIntrastat"
|
|
flat
|
|
>
|
|
<template #header="props">
|
|
<QTr :props="props" class="bg">
|
|
<QTh v-for="col in props.cols" :key="col.name" :props="props">
|
|
{{ t(col.label) }}
|
|
</QTh>
|
|
</QTr>
|
|
</template>
|
|
<template #bottom-row>
|
|
<QTr class="bg">
|
|
<QTd></QTd>
|
|
<QTd>{{ toCurrency(intrastatTotals.amount) }}</QTd>
|
|
<QTd>{{ intrastatTotals.net }}</QTd>
|
|
<QTd>{{ intrastatTotals.stems }}</QTd>
|
|
<QTd></QTd>
|
|
</QTr>
|
|
</template>
|
|
</QTable>
|
|
</QCard>
|
|
</template>
|
|
</CardSummary>
|
|
</template>
|
|
<style lang="scss" scoped>
|
|
.bg {
|
|
background-color: var(--vn-accent-color);
|
|
}
|
|
.bordered {
|
|
border: 1px solid var(--vn-text-color);
|
|
max-width: 18em;
|
|
}
|
|
</style>
|
|
<i18n>
|
|
es:
|
|
Search invoice: Buscar factura recibida
|
|
You can search by invoice reference: Puedes buscar por referencia de la factura
|
|
</i18n>
|