0
0
Fork 0

Merge pull request 'Se termina desarrollo de las tarjetas gestion documental e impagado' (#88) from features/ms_164_file_management_card into dev

Reviewed-on: hyervoni/salix-front-mindshore#88
This commit is contained in:
Carlos Fonseca 2024-02-06 16:09:27 +00:00
commit 5127369e5c
23 changed files with 1084 additions and 170 deletions

View File

@ -112,14 +112,18 @@ function tMobile(...args) {
}
async function fetch() {
try {
const { data } = await axios.get($props.url, {
params: { filter: JSON.stringify($props.filter) },
});
state.set($props.model, data);
originalData.value = data && JSON.parse(JSON.stringify(data));
emit('onFetch', state.get($props.model));
} catch (error) {
state.set($props.model, {});
originalData.value = {};
}
}
async function save() {

View File

@ -48,6 +48,10 @@ body.body--dark {
background-color: var(--vn-dark);
}
.color-vn-label {
color: var(--vn-label);
}
.color-vn-text {
color: var(--vn-text);
}

View File

@ -27,7 +27,6 @@ const companiesOptions = ref([]);
const companyId = ref(null);
const receiptsRef = ref(null);
const rows = ref([]);
const workerId = ref(null);
const filterCompanies = { order: ['code'] };
const params = {
@ -37,49 +36,49 @@ const params = {
};
const filter = {
include: { relation: 'company', scope: { fields: ['code'] } },
where: { clientFk: `${route.params.id}`, companyFk: user.value.companyFk },
where: { clientFk: route.params.id, companyFk: user.value.companyFk },
};
const tableColumnComponents = {
payed: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
created: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
userName: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: ({ row }) => (workerId.value = row.clientFk),
event: () => {},
},
description: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
bankFk: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
debit: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
credit: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
balance: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
isConciliate: {
component: QCheckbox,
@ -87,7 +86,7 @@ const tableColumnComponents = {
disable: true,
'model-value': Boolean(prop.value),
}),
event: () => (workerId.value = null),
event: () => {},
},
};
@ -207,11 +206,11 @@ const updateCompanyId = (id) => {
<QTable
:columns="columns"
:no-data-label="t('globals.noResults')"
:pagination="{ rowsPerPage: 12 }"
:rows="rows"
class="full-width q-mt-md"
row-key="id"
v-if="rows?.length"
>
<template #body-cell="props">
<QTd :props="props">
@ -225,17 +224,16 @@ const updateCompanyId = (id) => {
<template v-if="props.col.name !== 'isConciliate'">
{{ props.value }}
</template>
<WorkerDescriptorProxy :id="workerId" />
<WorkerDescriptorProxy
:id="props.row.clientFk"
v-if="props.col.name === 'userName'"
/>
</component>
</QTr>
</QTd>
</template>
</QTable>
<h5 class="flex justify-center label-color" v-else>
{{ t('globals.noResults') }}
</h5>
<QDrawer :width="256" show-if-above side="right" v-model="stateStore.rightDrawer">
<div class="q-mt-xl q-px-md">
<VnSelectFilter

View File

@ -5,17 +5,11 @@ const { t } = useI18n();
</script>
<template>
<h5 class="flex justify-center label-color">
<h5 class="flex justify-center color-vn-label">
{{ t('Enter a new search') }}
</h5>
</template>
<style lang="scss">
.label-color {
color: var(--vn-label);
}
</style>
<i18n>
es:
Enter a new search: Introduce una nueva búsqueda

View File

@ -108,7 +108,7 @@ const updateData = () => {
<div class="q-ml-lg">
<div class="flex q-mb-xs">
<div class="q-mr-sm label-color">
<div class="q-mr-sm color-vn-label">
{{ t('Since') }}:
</div>
<div class="text-weight-bold">
@ -116,7 +116,9 @@ const updateData = () => {
</div>
</div>
<div class="flex">
<div class="q-mr-sm label-color">{{ t('To') }}:</div>
<div class="q-mr-sm color-vn-label">
{{ t('To') }}:
</div>
<div class="text-weight-bold">
{{ toDate(item.finished) }}
</div>
@ -129,7 +131,7 @@ const updateData = () => {
<div class="flex">
<div class="flex items-center">
<div class="flex q-mr-xl">
<div class="q-mr-sm label-color">
<div class="q-mr-sm color-vn-label">
{{ t('Credit') }}:
</div>
<div class="text-weight-bold">
@ -137,7 +139,7 @@ const updateData = () => {
</div>
</div>
<div class="flex q-mr-xl">
<div class="q-mr-sm label-color">
<div class="q-mr-sm color-vn-label">
{{ t('Grade') }}:
</div>
<div class="text-weight-bold">
@ -145,7 +147,7 @@ const updateData = () => {
</div>
</div>
<div class="flex">
<div class="q-mr-sm label-color">
<div class="q-mr-sm color-vn-label">
{{ t('Date') }}:
</div>
<div class="text-weight-bold">
@ -167,7 +169,7 @@ const updateData = () => {
</div>
</QCard>
</div>
<h5 class="flex justify-center label-color" v-else>
<h5 class="flex justify-center color-vn-label" v-else>
{{ t('globals.noResults') }}
</h5>
</template>
@ -188,9 +190,6 @@ const updateData = () => {
</template>
<style lang="scss" scoped>
.label-color {
color: var(--vn-label);
}
.customer-card {
border: 2px solid var(--vn-light-gray);
border-radius: 10px;

View File

@ -23,7 +23,7 @@ const filter = {
},
},
],
where: { clientFk: `${route.params.id}` },
where: { clientFk: route.params.id },
order: ['created DESC'],
limit: 20,
};

View File

@ -1,5 +1,5 @@
<script setup>
import { ref, computed } from 'vue';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
@ -14,7 +14,6 @@ const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const workerId = ref(null);
const rows = ref([]);
const filter = {
@ -27,7 +26,7 @@ const filter = {
},
},
],
where: { clientFk: `${route.params.id}` },
where: { clientFk: route.params.id },
order: ['created DESC'],
limit: 20,
};
@ -36,17 +35,17 @@ const tableColumnComponents = {
created: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
employee: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: ({ row }) => (workerId.value = row.clientFk),
event: () => {},
},
amount: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
};
@ -93,6 +92,7 @@ const toCustomerCreditCreate = () => {
:rows="rows"
class="full-width q-mt-md"
row-key="id"
v-if="rows?.length"
>
<template #body-cell="props">
<QTd :props="props">
@ -104,12 +104,19 @@ const toCustomerCreditCreate = () => {
v-bind="tableColumnComponents[props.col.name].props(props)"
>
{{ props.value }}
<WorkerDescriptorProxy :id="workerId" />
<WorkerDescriptorProxy
:id="props.row.clientFk"
v-if="props.col.name === 'employee'"
/>
</component>
</QTr>
</QTd>
</template>
</QTable>
<h5 class="flex justify-center label-color" v-else>
{{ t('globals.noResults') }}
</h5>
</QPage>
<QPageSticky :offset="[18, 18]">
@ -120,6 +127,12 @@ const toCustomerCreditCreate = () => {
</QPageSticky>
</template>
<style lang="scss">
.label-color {
color: var(--vn-label);
}
</style>
<i18n>
es:
Since: Desde

View File

@ -1,3 +1,263 @@
<script setup>
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import { date, QBadge, QBtn, QCheckbox } from 'quasar';
import { downloadFile } from 'src/composables/downloadFile';
import FetchData from 'components/FetchData.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import CustomerFileManagementActions from 'src/pages/Customer/components/CustomerFileManagementActions.vue';
const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const ClientDmsRef = ref(null);
const rows = ref([]);
const filter = {
include: {
relation: 'dms',
scope: {
fields: [
'dmsTypeFk',
'reference',
'hardCopyNumber',
'workerFk',
'description',
'hasFile',
'file',
'created',
],
include: [
{ relation: 'dmsType', scope: { fields: ['name'] } },
{
relation: 'worker',
scope: {
fields: ['id'],
include: { relation: 'user', scope: { fields: ['name'] } },
},
},
],
},
},
where: { clientFk: route.params.id },
order: ['dmsFk DESC'],
limit: 20,
};
const tableColumnComponents = {
id: {
component: 'span',
props: () => {},
event: () => {},
},
type: {
component: 'span',
props: () => {},
event: () => {},
},
order: {
component: QBadge,
props: () => {},
event: () => {},
},
reference: {
component: 'span',
props: () => {},
event: () => {},
},
description: {
component: 'span',
props: () => {},
event: () => {},
},
original: {
component: QCheckbox,
props: (prop) => ({
disable: true,
'model-value': Boolean(prop.value),
}),
event: () => {},
},
file: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: ({ row }) => downloadFile(row.dmsFk),
},
employee: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: () => {},
},
created: {
component: 'span',
props: () => {},
event: () => {},
},
actions: {
component: CustomerFileManagementActions,
props: (prop) => ({
id: prop.row.dmsFk,
promise: setData,
}),
event: () => {},
},
};
const columns = computed(() => [
{
align: 'left',
field: ({ dms }) => dms.id,
label: t('Id'),
name: 'id',
},
{
align: 'left',
field: ({ dms }) => dms.dmsType.name,
label: t('Type'),
name: 'type',
},
{
align: 'left',
field: ({ dms }) => dms.hardCopyNumber,
label: t('Order'),
name: 'order',
},
{
align: 'left',
field: ({ dms }) => dms.reference,
label: t('Reference'),
name: 'reference',
},
{
align: 'left',
field: ({ dms }) => dms.description,
label: t('Description'),
name: 'description',
},
{
align: 'left',
field: ({ dms }) => dms.hasFile,
label: t('Original'),
name: 'original',
},
{
align: 'left',
field: ({ dms }) => dms.file,
label: t('File'),
name: 'file',
},
{
align: 'left',
field: ({ dms }) => dms.worker.user.name,
label: t('Employee'),
name: 'employee',
},
{
align: 'left',
field: (value) => value.dms.created,
label: t('Created'),
name: 'created',
format: (value) => date.formatDate(value, 'DD/MM/YYYY hh:mm'),
},
{
align: 'right',
field: 'actions',
label: '',
name: 'actions',
},
]);
const setData = () => {
ClientDmsRef.value.fetch();
};
const toCustomerFileManagementCreate = () => {
router.push({ name: 'CustomerFileManagementCreate' });
};
</script>
<template>
<div class="flex justify-center">Customer file management</div>
<FetchData
ref="ClientDmsRef"
:filter="filter"
@on-fetch="(data) => (rows = data)"
auto-load
url="ClientDms"
/>
<QPage class="column items-center q-pa-md">
<QTable
:columns="columns"
:pagination="{ rowsPerPage: 12 }"
:rows="rows"
class="full-width q-mt-md"
row-key="id"
v-if="rows?.length"
>
<template #body-cell="props">
<QTd :props="props">
<QTr :props="props" class="cursor-pointer">
<component
:is="
props.col.name === 'order' && !props.value
? 'span'
: tableColumnComponents[props.col.name].component
"
@click="tableColumnComponents[props.col.name].event(props)"
class="col-content"
v-bind="tableColumnComponents[props.col.name].props(props)"
>
<template v-if="props.col.name !== 'original'">
{{ props.value }}
</template>
<WorkerDescriptorProxy
:id="props.row.clientFk"
v-if="props.col.name === 'employee'"
/>
</component>
</QTr>
</QTd>
</template>
</QTable>
<h5 class="flex justify-center label-color" v-else>
{{ t('globals.noResults') }}
</h5>
</QPage>
<QPageSticky :offset="[18, 18]">
<QBtn
@click.stop="toCustomerFileManagementCreate()"
color="primary"
fab
icon="add"
/>
<QTooltip>
{{ t('Upload file') }}
</QTooltip>
</QPageSticky>
</template>
<style lang="scss">
.label-color {
color: var(--vn-label);
}
</style>
<i18n>
es:
Id: Id
Type: Tipo
Order: Orden
Reference: Referencia
Description: Descripción
Original: Original
File: Fichero
Employee: Empleado
Created: Fecha creación
Upload file: Subir fichero
</i18n>

View File

@ -16,7 +16,6 @@ const router = useRouter();
const rows = ref([]);
const totalAmount = ref(0);
const workerId = ref(null);
const filter = {
include: [
@ -44,27 +43,27 @@ const tableColumnComponents = {
date: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
createdBy: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: ({ row }) => (workerId.value = row.clientFk),
event: () => {},
},
comment: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
type: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
amount: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
};
@ -121,18 +120,18 @@ const toCustomerGreugeCreate = () => {
<QPage class="column items-center q-pa-md">
<QCard class="full-width" v-if="totalAmount">
<h6 class="flex justify-end q-my-lg q-pr-lg">
<span class="label-color q-mr-md">{{ t('Total') }}:</span>
<span class="color-vn-label q-mr-md">{{ t('Total') }}:</span>
{{ toCurrency(totalAmount) }}
</h6>
</QCard>
<QTable
:columns="columns"
:no-data-label="t('globals.noResults')"
:pagination="{ rowsPerPage: 12 }"
:rows="rows"
class="full-width q-mt-md"
row-key="id"
v-if="rows?.length"
>
<template #body-cell="props">
<QTd :props="props">
@ -144,18 +143,15 @@ const toCustomerGreugeCreate = () => {
@click="tableColumnComponents[props.col.name].event(props)"
>
{{ props.value }}
<WorkerDescriptorProxy :id="workerId" />
<WorkerDescriptorProxy
:id="props.row.clientFk"
v-if="props.col.name === 'createdBy'"
/>
</component>
</QTr>
</QTd>
</template>
</QTable>
<QCard class="full-width" v-else>
<h5 class="flex justify-center label-color">
{{ t('globals.noResults') }}
</h5>
</QCard>
</QPage>
<QPageSticky :offset="[18, 18]">
@ -172,10 +168,6 @@ const toCustomerGreugeCreate = () => {
border-radius: 10px;
padding: 10px;
}
.label-color {
color: var(--vn-label);
}
</style>
<i18n>

View File

@ -124,7 +124,7 @@ const setInq = (value, status) => {
:url="urlClientLogsModels"
/>
<h5 class="flex justify-center label-color">
<h5 class="flex justify-center color-vn-label">
{{ t('globals.noResults') }}
</h5>

View File

@ -5,13 +5,7 @@ const { t } = useI18n();
</script>
<template>
<h5 class="flex justify-center label-color">
<h5 class="flex justify-center color-vn-label">
{{ t('globals.noResults') }}
</h5>
</template>
<style lang="scss">
.label-color {
color: var(--vn-label);
}
</style>

View File

@ -43,8 +43,8 @@ const toCustomerNoteCreate = () => {
}"
>
<div class="flex justify-between">
<p class="label-color">{{ item.worker.user.nickname }}</p>
<p class="label-color">
<p class="color-vn-label">{{ item.worker.user.nickname }}</p>
<p class="color-vn-label">
{{
date.formatDate(item?.created, 'DD-MM-YYYY HH:mm:ss')
}}
@ -55,7 +55,7 @@ const toCustomerNoteCreate = () => {
</div>
<div v-else>
<h5 class="flex justify-center label-color">
<h5 class="flex justify-center color-vn-label">
{{ t('globals.noResults') }}
</h5>
</div>
@ -89,8 +89,4 @@ const toCustomerNoteCreate = () => {
border-radius: 10px;
padding: 10px;
}
.label-color {
color: var(--vn-label);
}
</style>

View File

@ -15,7 +15,7 @@ const router = useRouter();
const rows = ref([]);
const filter = {
where: { clientFk: `${route.params.id}` },
where: { clientFk: route.params.id },
order: ['started DESC'],
limit: 20,
};
@ -89,11 +89,11 @@ const toCustomerRecoverieCreate = () => {
<QPage class="column items-center q-pa-md">
<QTable
:columns="columns"
:no-data-label="t('globals.noResults')"
:pagination="{ rowsPerPage: 12 }"
:rows="rows"
class="full-width q-mt-md"
row-key="id"
v-if="rows?.length"
>
<template #body-cell="props">
<QTd :props="props">
@ -110,12 +110,6 @@ const toCustomerRecoverieCreate = () => {
</QTd>
</template>
</QTable>
<QCard class="full-width" v-else>
<h5 class="flex justify-center label-color">
{{ t('globals.noResults') }}
</h5>
</QCard>
</QPage>
<QPageSticky :offset="[18, 18]">
@ -132,10 +126,6 @@ const toCustomerRecoverieCreate = () => {
border-radius: 10px;
padding: 10px;
}
.label-color {
color: var(--vn-label);
}
</style>
<i18n>

View File

@ -12,7 +12,6 @@ const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const workerId = ref(null);
const rows = ref([]);
const filter = {
@ -30,22 +29,22 @@ const tableColumnComponents = {
sent: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
description: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
worker: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: ({ row }) => (workerId.value = row.clientFk),
event: () => {},
},
company: {
component: 'span',
props: () => {},
event: () => (workerId.value = null),
event: () => {},
},
};
@ -71,7 +70,7 @@ const columns = computed(() => [
},
{
align: 'left',
field: (value) => value.company.code,
field: (value) => value.company?.code,
label: t('Company'),
name: 'company',
},
@ -97,7 +96,7 @@ const toCustomerSamplesCreate = () => {
:rows="rows"
class="full-width q-mt-md"
row-key="id"
v-if="rows?.length"
:no-data-label="t('globals.noResults')"
>
<template #body-cell="props">
<QTd :props="props">
@ -109,18 +108,15 @@ const toCustomerSamplesCreate = () => {
@click="tableColumnComponents[props.col.name].event(props)"
>
{{ props.value }}
<WorkerDescriptorProxy :id="workerId" />
<WorkerDescriptorProxy
:id="props.row.clientFk"
v-if="props.col.name === 'worker'"
/>
</component>
</QTr>
</QTd>
</template>
</QTable>
<QCard class="full-width" v-else>
<h5 class="flex justify-center label-color">
{{ t('globals.noResults') }}
</h5>
</QCard>
</QPage>
<QPageSticky :offset="[18, 18]">
@ -137,10 +133,6 @@ const toCustomerSamplesCreate = () => {
border-radius: 10px;
padding: 10px;
}
.label-color {
color: var(--vn-label);
}
</style>
<i18n>

View File

@ -1,3 +1,57 @@
<script setup>
import { reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import FormModel from 'components/FormModel.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInput from 'src/components/common/VnInput.vue';
const { t } = useI18n();
const route = useRoute();
const unpaidClient = ref(false);
const initialData = reactive({
dated: '2001-01-01T11:00:00.000Z',
clientFk: 1,
});
const onFetch = () => {
unpaidClient.value = true;
};
</script>
<template>
<div class="flex justify-center">Customer unpaid</div>
<FormModel
:form-initial-data="initialData"
:observe-form-changes="true"
:url="`ClientUnpaids/${route.params.id}`"
@on-fetch="onFetch"
url-create="ClientUnpaids"
auto-load
>
<template #form="{ data }">
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<QCheckbox :label="t('Unpaid client')" v-model="unpaidClient" />
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md" v-if="unpaidClient">
<div class="col">
<VnInputDate :label="t('Date')" v-model="data.dated" />
</div>
<div class="col">
<VnInput :label="t('Amount')" type="number" v-model="data.amount" />
</div>
</VnRow>
</template>
</FormModel>
</template>
<i18n>
es:
Unpaid client: Cliente impagado
Date: Fecha
Amount: Importe
</i18n>

View File

@ -5,13 +5,7 @@ const { t } = useI18n();
</script>
<template>
<h5 class="flex justify-center label-color">
<h5 class="flex justify-center color-vn-label">
{{ t('globals.noResults') }}
</h5>
</template>
<style lang="scss">
.label-color {
color: var(--vn-label);
}
</style>

View File

@ -18,7 +18,6 @@ const { t } = useI18n();
const quasar = useQuasar();
const balanceDueTotal = ref(0);
const customerId = ref(0);
const selected = ref([]);
const workerId = ref(0);
const rows = ref([]);
@ -27,7 +26,7 @@ const tableColumnComponents = {
client: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: ({ row }) => selectCustomerId(row.clientFk),
event: () => {},
},
isWorker: {
component: QCheckbox,
@ -36,10 +35,10 @@ const tableColumnComponents = {
'model-value': Boolean(row.selected),
}),
},
salesperson: {
salesPerson: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: ({ row }) => selectWorkerId(row.salesPersonFk),
event: () => {},
},
country: {
component: 'span',
@ -59,7 +58,7 @@ const tableColumnComponents = {
author: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: ({ row }) => selectWorkerId(row.workerFk),
event: () => {},
},
lastObservation: {
component: 'span',
@ -100,7 +99,7 @@ const columns = computed(() => [
align: 'left',
field: 'salesPersonName',
label: t('Salesperson'),
name: 'salesperson',
name: 'salesPerson',
},
{
align: 'left',
@ -159,16 +158,6 @@ const setRows = (data) => {
}, 0);
};
const selectCustomerId = (id) => {
workerId.value = 0;
customerId.value = id;
};
const selectWorkerId = (id) => {
customerId.value = 0;
workerId.value = id;
};
const viewAddObservation = (rowsSelected) => {
quasar.dialog({
component: CustomerDefaulterAddObservation,
@ -234,8 +223,18 @@ const refreshData = () => {
>
{{ props.value }}
<WorkerDescriptorProxy v-if="workerId" :id="workerId" />
<CustomerDescriptorProxy v-else :id="customerId" />
<WorkerDescriptorProxy
:id="props.row.salesPersonFk"
v-if="props.col.name === 'salesPerson'"
/>
<WorkerDescriptorProxy
:id="props.row.workerFk"
v-if="props.col.name === 'author'"
/>
<CustomerDescriptorProxy
:id="props.row.clientFk"
v-if="props.col.name === 'client'"
/>
</component>
</QTr>
</QTd>

View File

@ -3,7 +3,9 @@ import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import axios from 'axios';
import { useQuasar } from 'quasar';
import { useDialogPluginComponent } from 'quasar';
import useNotify from 'src/composables/useNotify';
import VnRow from 'components/ui/VnRow.vue';
@ -18,8 +20,9 @@ const $props = defineProps({
},
});
const { dialogRef } = useDialogPluginComponent();
const { notify } = useNotify();
const { t } = useI18n();
const quasar = useQuasar();
const newObservation = ref(null);
@ -38,15 +41,9 @@ const onSubmit = async () => {
await $props.promise();
quasar.notify({
message: t('globals.dataSaved'),
type: 'positive',
});
notify('globals.dataSaved', 'positive');
} catch (error) {
quasar.notify({
message: t(`${error.message}`),
type: 'negative',
});
notify(error.message, 'negative');
}
};
</script>

View File

@ -0,0 +1,96 @@
<script setup>
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import { useQuasar } from 'quasar';
import { downloadFile } from 'src/composables/downloadFile';
import CustomerFileManagementDelete from 'src/pages/Customer/components/CustomerFileManagementDelete.vue';
const { t } = useI18n();
const quasar = useQuasar();
const route = useRoute();
const router = useRouter();
const $props = defineProps({
id: {
type: Number,
required: true,
},
promise: {
type: Function,
required: true,
},
});
const setDownloadFile = () => downloadFile($props.id);
const toCustomerFileManagementEdit = () => {
router.push({
name: 'CustomerFileManagementEdit',
params: {
id: route.params.id,
dmsId: $props.id,
},
});
};
const showCustomerFileManagementDeleteDialog = () => {
quasar.dialog({
component: CustomerFileManagementDelete,
componentProps: {
id: $props.id,
promise: setData,
},
});
};
const setData = () => {
$props.promise();
};
</script>
<template>
<div>
<QIcon
@click.stop="setDownloadFile"
color="primary"
name="cloud_download"
size="sm"
>
<QTooltip>
{{ t('Download file') }}
</QTooltip>
</QIcon>
<QIcon
@click.stop="toCustomerFileManagementEdit"
class="q-ml-md"
color="primary"
name="edit"
size="sm"
>
<QTooltip>
{{ t('Edit file') }}
</QTooltip>
</QIcon>
<QIcon
@click.stop="showCustomerFileManagementDeleteDialog"
class="q-ml-md"
color="primary"
name="delete"
size="sm"
>
<QTooltip>
{{ t('Remove file') }}
</QTooltip>
</QIcon>
</div>
</template>
<i18n>
es:
Download file: Descargar fichero
Edit file: Editar fichero
Remove file: Eliminar fichero
</i18n>

View File

@ -0,0 +1,241 @@
<script setup>
import { onBeforeMount, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import axios from 'axios';
import { useState } from 'src/composables/useState';
import useNotify from 'src/composables/useNotify';
import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
import VnInput from 'src/components/common/VnInput.vue';
const { notify } = useNotify();
const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const state = useState();
const user = state.getUser();
const filterFindOne = { where: { code: 'paymentsLaw' } };
const filterCompanies = { order: ['code'] };
const filterWarehouses = { order: ['name'] };
const client = ref({});
const findOne = ref([]);
const allowedContentTypes = ref([]);
const optionsCompanies = ref([]);
const optionsWarehouses = ref([]);
const optionsDmsTypes = ref([]);
const isLoading = ref(false);
const dms = ref({
hasFile: false,
});
onBeforeMount(() => {
const { companyFk, warehouseFk } = user.value;
dms.value.reference = route.params.id;
dms.value.companyId = companyFk;
dms.value.warehouseId = warehouseFk;
});
watch([client, findOne], ([newClient, newFindOne]) => {
dms.value.description = t('clientFileDescription', {
dmsTypeName: newFindOne.name?.toUpperCase(),
clientName: newClient.name?.toUpperCase(),
clientId: newClient.id,
});
dms.value.dmsTypeId = newFindOne.id;
});
const saveData = async () => {
try {
const formData = new FormData();
if (dms.value.files) {
for (let i = 0; i < dms.value.files.length; i++)
formData.append(dms.value.files[i].name, dms.value.files[i]);
dms.value.hasFileAttached = true;
}
const url = `clients/${route.params.id}/uploadFile`;
await axios.post(url, formData, {
params: dms.value,
});
notify('globals.dataSaved', 'positive');
router.push({ name: 'CustomerFileManagement' });
} catch (error) {
notify(error.message, 'negative');
}
};
const inputFileRef = ref();
</script>
<template>
<fetch-data
@on-fetch="(data) => (client = data)"
auto-load
:url="`Clients/${route.params.id}/getCard`"
/>
<fetch-data
:filter="filterFindOne"
@on-fetch="(data) => (findOne = data)"
auto-load
url="DmsTypes/findOne"
/>
<fetch-data
@on-fetch="(data) => (allowedContentTypes = data)"
auto-load
url="DmsContainers/allowedContentTypes"
/>
<fetch-data
:filter="filterCompanies"
@on-fetch="(data) => (optionsCompanies = data)"
auto-load
url="Companies"
/>
<fetch-data
:filter="filterWarehouses"
@on-fetch="(data) => (optionsWarehouses = data)"
auto-load
url="Warehouses"
/>
<fetch-data
:filter="filterWarehouses"
@on-fetch="(data) => (optionsDmsTypes = data)"
auto-load
url="DmsTypes"
/>
<QForm>
<QCard class="q-pa-lg">
<QCardSection>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnInput :label="t('Reference')" v-model="dms.reference" />
</div>
<div class="col">
<VnSelectFilter
:label="t('Company')"
:options="optionsCompanies"
option-label="code"
option-value="id"
v-model="dms.companyId"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnSelectFilter
:label="t('Warehouse')"
:options="optionsWarehouses"
option-label="name"
option-value="id"
v-model="dms.warehouseId"
/>
</div>
<div class="col">
<VnSelectFilter
:label="t('Type')"
:options="optionsDmsTypes"
option-label="name"
option-value="id"
v-model="dms.dmsTypeId"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnInput
:label="t('Description')"
type="textarea"
v-model="dms.description"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<QFile
ref="inputFileRef"
class="required"
:label="t('File')"
v-model="dms.files"
multiple
:accept="allowedContentTypes.join(',')"
clearable
clear-icon="close"
>
<template #append>
<QBtn
icon="attach_file_add"
flat
round
padding="xs"
@click="inputFileRef.pickFiles()"
>
<QTooltip>
{{ t('Select a file') }}
</QTooltip>
</QBtn>
<QBtn icon="info" flat round padding="xs">
<QTooltip max-width="30rem">
{{
`${t(
'Allowed content types'
)}: ${allowedContentTypes.join(', ')}`
}}
</QTooltip>
</QBtn>
</template>
</QFile>
</div>
</VnRow>
<QCheckbox
:label="t('Generate identifier for original file')"
v-model="dms.hasFile"
/>
</QCardSection>
<QCardActions class="flex justify-end">
<QBtn
:disabled="isLoading"
:label="t('globals.cancel')"
:loading="isLoading"
class="q-mr-xl"
color="primary"
flat
/>
<QBtn
:disabled="isLoading"
:label="t('globals.save')"
:loading="isLoading"
color="primary"
@click.stop="saveData"
/>
</QCardActions>
</QCard>
</QForm>
</template>
<i18n>
en:
clientFileDescription: '{dmsTypeName} FROM CLIENT {clientName} ID {clientId}'
es:
Reference: Referencia
Company: Empresa
Warehouse: Almacén
Type: Tipo
Description: Descripción
clientFileDescription: '{dmsTypeName} DEL CLIENTE {clientName} ID {clientId}'
File: Fichero
Select a file: Selecciona un fichero
Allowed content types: Tipos de archivo permitidos
Generate identifier for original file: Generar identificador para archivo original
</i18n>

View File

@ -0,0 +1,81 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useDialogPluginComponent } from 'quasar';
import axios from 'axios';
import useNotify from 'src/composables/useNotify';
const $props = defineProps({
id: {
type: Number,
required: true,
},
promise: {
type: Function,
required: true,
},
});
const { dialogRef } = useDialogPluginComponent();
const { notify } = useNotify();
const { t } = useI18n();
const closeButton = ref(null);
const isLoading = ref(false);
const deleteDms = async () => {
isLoading.value = true;
try {
await axios.post(`ClientDms/${$props.id}/removeFile`);
if ($props.promise) await $props.promise();
notify('globals.dataDeleted', 'positive');
} catch (error) {
notify(error.message, 'negative');
} finally {
closeButton.value.click();
isLoading.value = false;
}
};
</script>
<template>
<QDialog ref="dialogRef">
<QCard class="q-pa-md q-mb-md">
<span ref="closeButton" class="row justify-end close-icon" v-close-popup>
<QIcon name="close" size="sm" />
</span>
<QCardSection>
<div class="mt-1 text-h6">{{ t('This file will be deleted') }}</div>
<div>{{ t('Are you sure you want to continue?') }}</div>
</QCardSection>
<QCardActions class="flex justify-end">
<QBtn
:disabled="isLoading"
:label="t('globals.cancel')"
:loading="isLoading"
class="q-mr-xl"
color="primary"
flat
v-close-popup
/>
<QBtn
:disabled="isLoading"
:label="t('globals.save')"
:loading="isLoading"
@click.stop="deleteDms"
color="primary"
/>
</QCardActions>
</QCard>
</QDialog>
</template>
<i18n>
es:
This file will be deleted: Este fichero va a ser borrado
Are you sure you want to continue?: ¿Seguro que quieres continuar?
</i18n>

View File

@ -0,0 +1,220 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import axios from 'axios';
import useNotify from 'src/composables/useNotify';
import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
import VnInput from 'src/components/common/VnInput.vue';
const { notify } = useNotify();
const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const filterCompanies = { order: ['code'] };
const filterWarehouses = { order: ['name'] };
const allowedContentTypes = ref([]);
const optionsCompanies = ref([]);
const optionsWarehouses = ref([]);
const optionsDmsTypes = ref([]);
const isLoading = ref(false);
const dms = ref({
hasFile: true,
});
const setCurrentDms = (data) => {
dms.value.reference = data.reference;
dms.value.companyId = data.companyFk;
dms.value.warehouseId = data.warehouseFk;
dms.value.dmsTypeId = data.dmsTypeFk;
dms.value.description = data.description;
};
const saveData = async () => {
try {
const formData = new FormData();
if (dms.value.files) {
for (let i = 0; i < dms.value.files.length; i++)
formData.append(dms.value.files[i].name, dms.value.files[i]);
dms.value.hasFileAttached = true;
}
const url = `dms/${route.params.dmsId}/updateFile`;
await axios.post(url, formData, {
params: dms.value,
});
notify('globals.dataSaved', 'positive');
router.push({ name: 'CustomerFileManagement' });
} catch (error) {
notify(error.message, 'negative');
}
};
const inputFileRef = ref();
</script>
<template>
<fetch-data :url="`Dms/${route.params.dmsId}`" @on-fetch="setCurrentDms" auto-load />
<fetch-data
@on-fetch="(data) => (allowedContentTypes = data)"
auto-load
url="DmsContainers/allowedContentTypes"
/>
<fetch-data
:filter="filterCompanies"
@on-fetch="(data) => (optionsCompanies = data)"
auto-load
url="Companies"
/>
<fetch-data
:filter="filterWarehouses"
@on-fetch="(data) => (optionsWarehouses = data)"
auto-load
url="Warehouses"
/>
<fetch-data
:filter="filterWarehouses"
@on-fetch="(data) => (optionsDmsTypes = data)"
auto-load
url="DmsTypes"
/>
<QForm>
<QCard class="q-pa-lg">
<QCardSection>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnInput :label="t('Reference')" v-model="dms.reference" />
</div>
<div class="col">
<VnSelectFilter
:label="t('Company')"
:options="optionsCompanies"
option-label="code"
option-value="id"
v-model="dms.companyId"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnSelectFilter
:label="t('Warehouse')"
:options="optionsWarehouses"
option-label="name"
option-value="id"
v-model="dms.warehouseId"
/>
</div>
<div class="col">
<VnSelectFilter
:label="t('Type')"
:options="optionsDmsTypes"
option-label="name"
option-value="id"
v-model="dms.dmsTypeId"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnInput
:label="t('Description')"
type="textarea"
v-model="dms.description"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<QFile
ref="inputFileRef"
class="required"
:label="t('File')"
v-model="dms.files"
multiple
:accept="allowedContentTypes.join(',')"
clearable
clear-icon="close"
>
<template #append>
<QBtn
icon="attach_file_add"
flat
round
padding="xs"
@click="inputFileRef.pickFiles()"
>
<QTooltip>
{{ t('Select a file') }}
</QTooltip>
</QBtn>
<QBtn icon="info" flat round padding="xs">
<QTooltip max-width="30rem">
{{
`${t(
'Allowed content types'
)}: ${allowedContentTypes.join(', ')}`
}}
</QTooltip>
</QBtn>
</template>
</QFile>
</div>
</VnRow>
<QCheckbox
:label="t('Generate identifier for original file')"
v-model="dms.hasFile"
disable
/>
</QCardSection>
<QCardActions class="flex justify-end">
<QBtn
:disabled="isLoading"
:label="t('globals.cancel')"
:loading="isLoading"
class="q-mr-xl"
color="primary"
flat
/>
<QBtn
:disabled="isLoading"
:label="t('globals.save')"
:loading="isLoading"
color="primary"
@click.stop="saveData"
/>
</QCardActions>
</QCard>
</QForm>
</template>
<i18n>
en:
clientFileDescription: '{dmsTypeName} FROM CLIENT {clientName} ID {clientId}'
es:
Reference: Referencia
Company: Empresa
Warehouse: Almacén
Type: Tipo
Description: Descripción
clientFileDescription: '{dmsTypeName} DEL CLIENTE {clientName} ID {clientId}'
File: Fichero
Select a file: Selecciona un fichero
Allowed content types: Tipos de archivo permitidos
Generate identifier for original file: Generar identificador para archivo original
</i18n>

View File

@ -356,12 +356,12 @@ export default {
{
name: 'CustomerCreditContracts',
title: 'creditContracts',
icon: 'paid',
icon: 'vn:solunion',
},
{
name: 'CustomerCreditOpinion',
title: 'creditOpinion',
icon: 'paid',
icon: 'vn:linesprepaired',
},
],
},
@ -371,7 +371,6 @@ export default {
name: 'CustomerCreditContracts',
meta: {
title: 'creditContracts',
icon: 'paid',
},
component: () =>
import(
@ -388,7 +387,6 @@ export default {
name: 'CustomerCreditContracts',
meta: {
title: 'creditContracts',
icon: 'paid',
},
component: () =>
import(
@ -418,7 +416,6 @@ export default {
name: 'CustomerCreditOpinion',
meta: {
title: 'creditOpinion',
icon: 'paid',
},
component: () =>
import(
@ -437,37 +434,37 @@ export default {
{
name: 'CustomerSamples',
title: 'samples',
icon: 'pending',
icon: 'vn:notes',
},
{
name: 'CustomerConsumption',
title: 'consumption',
icon: 'pending',
icon: 'vn:lines',
},
{
name: 'CustomerMandates',
title: 'mandates',
icon: 'pending',
icon: 'vn:mandatory',
},
{
name: 'CustomerContacts',
title: 'contacts',
icon: 'pending',
icon: 'contact_phone',
},
{
name: 'CustomerWebPayment',
title: 'webPayment',
icon: 'pending',
icon: 'vn:onlinepayment',
},
{
name: 'CustomerFileManagement',
title: 'fileManagement',
icon: 'pending',
icon: 'Upload',
},
{
name: 'CustomerUnpaid',
title: 'unpaid',
icon: 'pending',
icon: 'vn:supplierfalse',
},
],
},
@ -477,7 +474,6 @@ export default {
name: 'CustomerSamples',
meta: {
title: 'samples',
icon: 'paid',
},
component: () =>
import('src/pages/Customer/Card/CustomerSamples.vue'),
@ -492,7 +488,6 @@ export default {
name: 'CustomerSamples',
meta: {
title: 'samples',
icon: 'paid',
},
component: () =>
import(
@ -514,7 +509,6 @@ export default {
name: 'CustomerConsumption',
meta: {
title: 'consumption',
icon: 'paid',
},
component: () =>
import('src/pages/Customer/Card/CustomerConsumption.vue'),
@ -524,7 +518,6 @@ export default {
name: 'CustomerMandates',
meta: {
title: 'mandates',
icon: 'paid',
},
component: () =>
import('src/pages/Customer/Card/CustomerMandates.vue'),
@ -534,7 +527,6 @@ export default {
name: 'CustomerContacts',
meta: {
title: 'contacts',
icon: 'paid',
},
component: () =>
import('src/pages/Customer/Card/CustomerContacts.vue'),
@ -544,7 +536,6 @@ export default {
name: 'CustomerWebPayment',
meta: {
title: 'webPayment',
icon: 'paid',
},
component: () =>
import('src/pages/Customer/Card/CustomerWebPayment.vue'),
@ -554,7 +545,6 @@ export default {
name: 'CustomerFileManagement',
meta: {
title: 'fileManagement',
icon: 'paid',
},
component: () =>
import(
@ -571,7 +561,6 @@ export default {
name: 'CustomerFileManagement',
meta: {
title: 'fileManagement',
icon: 'paid',
},
component: () =>
import(
@ -586,6 +575,14 @@ export default {
'src/pages/Customer/components/CustomerFileManagementCreate.vue'
),
},
{
path: ':dmsId/edit',
name: 'CustomerFileManagementEdit',
component: () =>
import(
'src/pages/Customer/components/CustomerFileManagementEdit.vue'
),
},
],
},
{
@ -593,7 +590,6 @@ export default {
name: 'CustomerUnpaid',
meta: {
title: 'unpaid',
icon: 'paid',
},
component: () =>
import('src/pages/Customer/Card/CustomerUnpaid.vue'),