#7134 SupplierBalance #905
|
@ -0,0 +1,12 @@
|
||||||
|
export default function (initialFooter, data) {
|
||||||
|
const footer = data.reduce(
|
||||||
|
(acc, row) => {
|
||||||
|
Object.entries(initialFooter).forEach(([key, initialValue]) => {
|
||||||
|
acc[key] += row?.[key] !== undefined ? row[key] : initialValue;
|
||||||
|
});
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{ ...initialFooter }
|
||||||
|
);
|
||||||
|
return footer;
|
||||||
|
}
|
|
@ -10,4 +10,4 @@ import DepartmentDescriptor from 'pages/Department/Card/DepartmentDescriptor.vue
|
||||||
base-url="Departments"
|
base-url="Departments"
|
||||||
:descriptor="DepartmentDescriptor"
|
:descriptor="DepartmentDescriptor"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
<script setup>
|
||||||
|
import { computed, onBeforeMount, ref } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import tableFooter from 'src/components/VnTable/filters/tableFooter';
|
||||||
|
import { dashIfEmpty, toCurrency, toDateHourMin } from 'src/filters';
|
||||||
|
import { useState } from 'src/composables/useState';
|
||||||
|
import { useStateStore } from 'src/stores/useStateStore';
|
||||||
|
|
||||||
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
|
|
||||||
|
import InvoiceInDescriptorProxy from 'src/pages/InvoiceIn/Card/InvoiceInDescriptorProxy.vue';
|
||||||
|
import SupplierBalanceFilter from './SupplierBalanceFilter.vue';
|
||||||
|
import { onMounted } from 'vue';
|
||||||
|
import FetchData from 'src/components/FetchData.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const state = useState();
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const user = state.getUser();
|
||||||
|
|
||||||
|
const tableRef = ref();
|
||||||
|
const companyId = ref();
|
||||||
|
const companyUser = ref(user.value.companyFk);
|
||||||
|
const balances = ref([]);
|
||||||
|
const userParams = ref({
|
||||||
|
supplierId: route.params.id,
|
||||||
|
companyId: companyId.value ?? companyUser.value,
|
||||||
|
isBooked: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'dated',
|
||||||
|
label: t('Creation date'),
|
||||||
|
format: ({ dated }) => toDateHourMin(dated),
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'sref',
|
||||||
|
label: t('Reference'),
|
||||||
|
isTitle: true,
|
||||||
|
class: 'extend',
|
||||||
|
format: ({ sref }) => dashIfEmpty(sref),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'bank',
|
||||||
|
label: t('Bank'),
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'invoiceEuros',
|
||||||
|
label: t('Debit'),
|
||||||
|
format: ({ invoiceEuros }) => toCurrency(invoiceEuros),
|
||||||
|
isId: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'paymentEuros',
|
||||||
|
label: t('Havings'),
|
||||||
|
format: ({ paymentEuros }) => toCurrency(paymentEuros),
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'euroBalance',
|
||||||
|
label: t('Balance'),
|
||||||
|
format: ({ euroBalance }) => toCurrency(euroBalance),
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'isBooked',
|
||||||
|
label: t('Conciliated'),
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
stateStore.rightDrawer = true;
|
||||||
|
companyId.value = companyUser.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
Object.assign(userParams, {
|
||||||
|
supplierId: route.params.id,
|
||||||
|
companyId: companyId.value ?? companyUser.value,
|
||||||
|
isConciliated: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function setFooter(data) {
|
||||||
|
const initialFooter = {
|
||||||
|
invoiceEuros: 0,
|
||||||
|
paymentEuros: 0,
|
||||||
|
euroBalance: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
tableRef.value.footer = tableFooter(initialFooter, data);
|
||||||
|
}
|
||||||
|
async function onFetch(data) {
|
||||||
|
setFooter(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function round(value) {
|
||||||
|
return Math.round(value * 100) / 100;
|
||||||
|
}
|
||||||
|
const onFetchCurrencies = ([currency]) => {
|
||||||
|
userParams.value.currencyFk = currency?.id;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QDrawer side="right" :width="265" v-model="stateStore.rightDrawer">
|
||||||
|
|||||||
|
<SupplierBalanceFilter data-key="SupplierBalance" />
|
||||||
|
</QDrawer>
|
||||||
|
<FetchData
|
||||||
|
url="Currencies"
|
||||||
|
:filter="{ fields: ['id', 'code'], where: { code: 'EUR' } }"
|
||||||
|
sort-by="code"
|
||||||
|
@on-fetch="onFetchCurrencies"
|
||||||
|
auto-load
|
||||||
|
/>
|
||||||
|
<VnTable
|
||||||
|
v-if="userParams.currencyFk"
|
||||||
|
ref="tableRef"
|
||||||
|
data-key="SupplierBalance"
|
||||||
|
url="Suppliers/receipts"
|
||||||
|
search-url="balance"
|
||||||
|
:user-params="userParams"
|
||||||
|
:columns="columns"
|
||||||
|
:right-search="false"
|
||||||
|
:is-editable="false"
|
||||||
|
:column-search="false"
|
||||||
|
@on-fetch="onFetch"
|
||||||
|
:disable-option="{ card: true }"
|
||||||
|
:footer="true"
|
||||||
|
:order="['dated ASC']"
|
||||||
|
data-cy="supplierBalanceTable"
|
||||||
|
auto-load
|
||||||
|
:map-key="false"
|
||||||
|
>
|
||||||
|
<template #column-balance="{ rowIndex }">
|
||||||
|
{{ toCurrency(balances[rowIndex]?.balance) }}
|
||||||
|
</template>
|
||||||
|
<template #column-sref="{ row }">
|
||||||
jsegarra marked this conversation as resolved
jgallego
commented
el redondeo lo hace el toCurrency creo que tiene un parametro para los decimales el redondeo lo hace el toCurrency creo que tiene un parametro para los decimales
jsegarra
commented
Pero por defecto es 2 Pero por defecto es 2
toCurrency =>(value, symbol = 'EUR', fractionSize = 2)
|
|||||||
|
<span class="link" v-if="row.statementType === 'invoiceIn'">
|
||||||
|
{{ dashIfEmpty(row.sref) }}
|
||||||
|
<InvoiceInDescriptorProxy :id="row.id" />
|
||||||
|
</span>
|
||||||
|
<span v-else> {{ dashIfEmpty(row.sref) }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #column-footer-invoiceEuros>
|
||||||
|
<span>
|
||||||
|
{{ toCurrency(round(tableRef.footer.invoiceEuros)) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #column-footer-paymentEuros>
|
||||||
|
<span>
|
||||||
|
{{ toCurrency(round(tableRef.footer.paymentEuros)) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #column-footer-euroBalance>
|
||||||
|
<span>
|
||||||
|
{{ toCurrency(round(tableRef.footer.euroBalance)) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Company: Empresa
|
||||||
|
Total by company: Total por empresa
|
||||||
|
Date: Fecha
|
||||||
|
Creation date: Fecha de creación
|
||||||
|
Reference: Referencia
|
||||||
|
Bank: Caja
|
||||||
|
Debit: Debe
|
||||||
|
Havings: Haber
|
||||||
|
Balance: Balance
|
||||||
|
Conciliated: Conciliado
|
||||||
|
</i18n>
|
|
@ -0,0 +1,121 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
defineProps({
|
||||||
|
dataKey: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<VnFilterPanel
|
||||||
|
:data-key="dataKey"
|
||||||
|
:search-button="true"
|
||||||
|
:redirect="false"
|
||||||
|
:unremovable-params="['supplierId', 'companyId']"
|
||||||
|
>
|
||||||
|
<template #tags="{ tag, formatFn }">
|
||||||
|
<div class="q-gutter-x-xs">
|
||||||
|
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
||||||
|
<span>{{ formatFn(tag.value) }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #body="{ params, searchFn }">
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnInputDate
|
||||||
|
:label="t('params.from')"
|
||||||
|
v-model="params.from"
|
||||||
|
@update:model-value="searchFn()"
|
||||||
|
is-outlined
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('params.bankFk')"
|
||||||
|
v-model="params.bankFk"
|
||||||
|
url="Accountings"
|
||||||
|
option-label="bank"
|
||||||
|
:include="{ relation: 'accountingType' }"
|
||||||
|
sort-by="id"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
>
|
||||||
|
<template #option="scope">
|
||||||
|
<QItem v-bind="scope.itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel>
|
||||||
|
{{ scope.opt.id }} {{ scope.opt.bank }}
|
||||||
|
</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
jsegarra marked this conversation as resolved
jgallego
commented
porque no pones directamente el espacio? porque no pones directamente el espacio?
|
|||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnSelect>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('params.currencyFk')"
|
||||||
|
url="Currencies"
|
||||||
|
:filter="{ fields: ['id', 'name'] }"
|
||||||
|
order="code"
|
||||||
|
v-model="params.currencyFk"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
hide-selected
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<QCheckbox
|
||||||
|
v-model="params.isConciliated"
|
||||||
|
:label="t('params.isConciliated')"
|
||||||
|
/></QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnFilterPanel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
en:
|
||||||
|
params:
|
||||||
|
search: General search
|
||||||
|
supplierId: Supplier
|
||||||
|
categoryId: Category
|
||||||
|
from: From
|
||||||
|
to: To
|
||||||
|
isConciliated: Is conciliated
|
||||||
|
currencyFk: Currency
|
||||||
|
bankFk: Bank
|
||||||
|
companyId: Comapany
|
||||||
|
isBooked: Is booked
|
||||||
|
es:
|
||||||
|
params:
|
||||||
|
supplierId: Proveedor
|
||||||
|
isConciliated: Conciliado
|
||||||
|
currencyFk: Moneda
|
||||||
|
New payment: Añadir pago
|
||||||
|
Date: Fecha
|
||||||
|
from: Desde
|
||||||
|
to: Hasta
|
||||||
|
companyId: Empresa
|
||||||
|
isBooked: Contabilizado
|
||||||
|
bankFk: Caja
|
||||||
|
Amount: Importe
|
||||||
|
Reference: Referencia
|
||||||
|
Cash: Efectivo
|
||||||
|
</i18n>
|
|
@ -21,6 +21,7 @@ export default {
|
||||||
'SupplierAccounts',
|
'SupplierAccounts',
|
||||||
'SupplierContacts',
|
'SupplierContacts',
|
||||||
'SupplierAddresses',
|
'SupplierAddresses',
|
||||||
|
'SupplierBalance',
|
||||||
'SupplierConsumption',
|
'SupplierConsumption',
|
||||||
'SupplierAgencyTerm',
|
'SupplierAgencyTerm',
|
||||||
'SupplierDms',
|
'SupplierDms',
|
||||||
|
@ -144,6 +145,16 @@ export default {
|
||||||
component: () =>
|
component: () =>
|
||||||
import('src/pages/Supplier/Card/SupplierAddressesCreate.vue'),
|
import('src/pages/Supplier/Card/SupplierAddressesCreate.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'balance',
|
||||||
|
name: 'SupplierBalance',
|
||||||
|
meta: {
|
||||||
|
title: 'balance',
|
||||||
|
icon: 'balance',
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import('src/pages/Supplier/Card/SupplierBalance.vue'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'consumption',
|
path: 'consumption',
|
||||||
name: 'SupplierConsumption',
|
name: 'SupplierConsumption',
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
describe('Supplier Balance', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport(1920, 1080);
|
||||||
|
cy.login('developer');
|
||||||
|
cy.visit(`/#/supplier/1/balance`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should load layout', () => {
|
||||||
|
cy.get('.q-page').should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,9 +3,7 @@ describe('Client balance', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.viewport(1280, 720);
|
cy.viewport(1280, 720);
|
||||||
cy.login('developer');
|
cy.login('developer');
|
||||||
cy.visit('#/customer/1101/balance', {
|
cy.visit('#/customer/1101/balance');
|
||||||
timeout: 5000,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
it('Should load layout', () => {
|
it('Should load layout', () => {
|
||||||
cy.get('.q-page').should('be.visible');
|
cy.get('.q-page').should('be.visible');
|
||||||
|
|
Loading…
Reference in New Issue
de momento seguimos con el 265 pero ticketBasicData ya tiene witdth 265, hay que ir mirando de hacerlo en una clase css a nivel aplicacion o un como los iconos md, xs, como creas mas conveniente.