Merge branch 'dev' into 7405-vueDocs
gitea/salix-front/pipeline/pr-dev This commit looks good Details

This commit is contained in:
Javier Segarra 2025-01-29 15:18:40 +00:00
commit ebf2345fea
7 changed files with 348 additions and 4 deletions

View File

@ -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;
}

View File

@ -10,4 +10,4 @@ import DepartmentDescriptor from 'pages/Department/Card/DepartmentDescriptor.vue
base-url="Departments"
:descriptor="DepartmentDescriptor"
/>
</template>
</template>

View File

@ -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 }">
<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>

View File

@ -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>
</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>

View File

@ -21,6 +21,7 @@ export default {
'SupplierAccounts',
'SupplierContacts',
'SupplierAddresses',
'SupplierBalance',
'SupplierConsumption',
'SupplierAgencyTerm',
'SupplierDms',
@ -144,6 +145,16 @@ export default {
component: () =>
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',
name: 'SupplierConsumption',

View File

@ -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');
});
});

View File

@ -3,9 +3,7 @@ describe('Client balance', () => {
beforeEach(() => {
cy.viewport(1280, 720);
cy.login('developer');
cy.visit('#/customer/1101/balance', {
timeout: 5000,
});
cy.visit('#/customer/1101/balance');
});
it('Should load layout', () => {
cy.get('.q-page').should('be.visible');