6943-customer_migration_subsection-v2 #591
|
@ -100,7 +100,6 @@ const isResetting = ref(false);
|
||||||
const hasChanges = ref(!$props.observeFormChanges);
|
const hasChanges = ref(!$props.observeFormChanges);
|
||||||
const originalData = ref({});
|
const originalData = ref({});
|
||||||
const formData = computed(() => state.get(modelValue));
|
const formData = computed(() => state.get(modelValue));
|
||||||
const formUrl = computed(() => $props.url);
|
|
||||||
const defaultButtons = computed(() => ({
|
const defaultButtons = computed(() => ({
|
||||||
save: {
|
save: {
|
||||||
color: 'primary',
|
color: 'primary',
|
||||||
|
@ -148,11 +147,14 @@ if (!$props.url)
|
||||||
(val) => updateAndEmit('onFetch', val)
|
(val) => updateAndEmit('onFetch', val)
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(formUrl, async () => {
|
watch(
|
||||||
|
() => [$props.url, $props.filter],
|
||||||
|
|||||||
|
async () => {
|
||||||
originalData.value = null;
|
originalData.value = null;
|
||||||
reset();
|
reset();
|
||||||
await fetch();
|
await fetch();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
onBeforeRouteLeave((to, from, next) => {
|
onBeforeRouteLeave((to, from, next) => {
|
||||||
if (hasChanges.value && $props.observeFormChanges)
|
if (hasChanges.value && $props.observeFormChanges)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onBeforeMount } from 'vue';
|
import { watch, computed } from 'vue';
|
||||||
import { date } from 'quasar';
|
import { date } from 'quasar';
|
||||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
||||||
import VnAvatar from '../ui/VnAvatar.vue';
|
import VnAvatar from '../ui/VnAvatar.vue';
|
||||||
|
@ -10,7 +10,8 @@ const $props = defineProps({
|
||||||
where: { type: Object, default: () => {} },
|
where: { type: Object, default: () => {} },
|
||||||
});
|
});
|
||||||
|
|
||||||
const filter = {
|
const filter = computed(() => {
|
||||||
|
return {
|
||||||
fields: ['smsFk'],
|
fields: ['smsFk'],
|
||||||
include: {
|
include: {
|
||||||
relation: 'sms',
|
relation: 'sms',
|
||||||
|
@ -32,9 +33,9 @@ const filter = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
...{ where: $props.where },
|
||||||
|
};
|
||||||
onBeforeMount(() => (filter.where = $props.where));
|
});
|
||||||
|
|
||||||
function formatNumber(number) {
|
function formatNumber(number) {
|
||||||
if (number.length <= 10) return number;
|
if (number.length <= 10) return number;
|
||||||
|
|
|
@ -90,6 +90,9 @@ globals:
|
||||||
salesPerson: SalesPerson
|
salesPerson: SalesPerson
|
||||||
send: Send
|
send: Send
|
||||||
code: Code
|
code: Code
|
||||||
|
since: Since
|
||||||
|
from: From
|
||||||
|
to: To
|
||||||
pageTitles:
|
pageTitles:
|
||||||
logIn: Login
|
logIn: Login
|
||||||
summary: Summary
|
summary: Summary
|
||||||
|
|
|
@ -90,6 +90,9 @@ globals:
|
||||||
salesPerson: Comercial
|
salesPerson: Comercial
|
||||||
send: Enviar
|
send: Enviar
|
||||||
code: Código
|
code: Código
|
||||||
|
since: Desde
|
||||||
|
from: Desde
|
||||||
|
to: Hasta
|
||||||
pageTitles:
|
pageTitles:
|
||||||
logIn: Inicio de sesión
|
logIn: Inicio de sesión
|
||||||
summary: Resumen
|
summary: Resumen
|
||||||
|
@ -697,8 +700,6 @@ invoiceOut:
|
||||||
percentageText: '{getPercentage}% {getAddressNumber} de {getNAddresses}'
|
percentageText: '{getPercentage}% {getAddressNumber} de {getNAddresses}'
|
||||||
pdfsNumberText: '{nPdfs} de {totalPdfs} PDFs'
|
pdfsNumberText: '{nPdfs} de {totalPdfs} PDFs'
|
||||||
negativeBases:
|
negativeBases:
|
||||||
from: Desde
|
|
||||||
to: Hasta
|
|
||||||
company: Empresa
|
company: Empresa
|
||||||
country: País
|
country: País
|
||||||
clientId: Id cliente
|
clientId: Id cliente
|
||||||
|
@ -1240,8 +1241,6 @@ components:
|
||||||
# LatestBuysFilter
|
# LatestBuysFilter
|
||||||
salesPersonFk: Comprador
|
salesPersonFk: Comprador
|
||||||
supplierFk: Proveedor
|
supplierFk: Proveedor
|
||||||
from: Desde
|
|
||||||
to: Hasta
|
|
||||||
active: Activo
|
active: Activo
|
||||||
visible: Visible
|
visible: Visible
|
||||||
floramondo: Floramondo
|
floramondo: Floramondo
|
||||||
|
|
|
@ -1,262 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onBeforeMount, ref } from 'vue';
|
import VnLog from 'src/components/common/VnLog.vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
|
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
|
||||||
|
|
||||||
import FetchData from 'components/FetchData.vue';
|
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
|
||||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const route = useRoute();
|
|
||||||
const stateStore = useStateStore();
|
|
||||||
|
|
||||||
const clientLogs = ref(null);
|
|
||||||
const urlClientLogsEditors = ref(null);
|
|
||||||
const urlClientLogsModels = ref(null);
|
|
||||||
const clientLogsModelsOptions = ref([]);
|
|
||||||
const clientLogsOptions = ref([]);
|
|
||||||
const clientLogsEditorsOptions = ref([]);
|
|
||||||
const radioButtonValue = ref('all');
|
|
||||||
const insert = ref(false);
|
|
||||||
const update = ref(false);
|
|
||||||
const deletes = ref(false);
|
|
||||||
const select = ref(false);
|
|
||||||
const neq = ref(null);
|
|
||||||
const inq = ref([]);
|
|
||||||
|
|
||||||
const filterClientLogs = {
|
|
||||||
fields: [
|
|
||||||
'id',
|
|
||||||
'originFk',
|
|
||||||
'userFk',
|
|
||||||
'action',
|
|
||||||
'changedModel',
|
|
||||||
'oldInstance',
|
|
||||||
'newInstance',
|
|
||||||
'creationDate',
|
|
||||||
'changedModel',
|
|
||||||
'changedModelId',
|
|
||||||
'changedModelValue',
|
|
||||||
'description',
|
|
||||||
],
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'user',
|
|
||||||
scope: {
|
|
||||||
fields: ['nickname', 'name', 'image'],
|
|
||||||
include: { relation: 'worker', scope: { fields: ['id'] } },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
order: ['creationDate DESC', 'id DESC'],
|
|
||||||
limit: 20,
|
|
||||||
};
|
|
||||||
const filterClientLogsEditors = {
|
|
||||||
fields: ['id', 'nickname', 'name', 'image'],
|
|
||||||
order: 'nickname',
|
|
||||||
limit: 30,
|
|
||||||
};
|
|
||||||
const filterClientLogsModels = { order: ['changedModel'] };
|
|
||||||
const urlBase = `ClientLogs/${route.params.id}`;
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
stateStore.rightDrawer = true;
|
|
||||||
filterClientLogs.where = {
|
|
||||||
and: [
|
|
||||||
{ originFk: `${route.params.id}` },
|
|
||||||
{ userFk: { neq: radioButtonValue.value } },
|
|
||||||
{ action: { inq: inq.value } },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
urlClientLogsEditors.value = `${urlBase}/editors`;
|
|
||||||
urlClientLogsModels.value = `${urlBase}/models`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const getClientLogs = async (value, status) => {
|
|
||||||
if (status === 'neq') {
|
|
||||||
neq.value = value;
|
|
||||||
} else {
|
|
||||||
setInq(value, status);
|
|
||||||
}
|
|
||||||
filterClientLogs.where = {
|
|
||||||
and: [
|
|
||||||
{ originFk: `${route.params.id}` },
|
|
||||||
{ userFk: { neq: neq.value } },
|
|
||||||
{ action: { inq: inq.value } },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
clientLogs.value?.fetch();
|
|
||||||
};
|
|
||||||
|
|
||||||
const setInq = (value, status) => {
|
|
||||||
if (status) {
|
|
||||||
if (!inq.value.includes(value)) {
|
|
||||||
inq.value.push(value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
inq.value = inq.value.filter((item) => item !== value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<VnLog model="Client" />
|
||||||
:filter="filterClientLogs"
|
|
||||||
@on-fetch="(data) => (clientLogsOptions = data)"
|
|
||||||
auto-load
|
|
||||||
url="ClientLogs"
|
|
||||||
ref="clientLogs"
|
|
||||||
/>
|
|
||||||
<FetchData
|
|
||||||
:filter="filterClientLogsEditors"
|
|
||||||
@on-fetch="(data) => (clientLogsEditorsOptions = data)"
|
|
||||||
auto-load
|
|
||||||
:url="urlClientLogsEditors"
|
|
||||||
/>
|
|
||||||
<FetchData
|
|
||||||
:filter="filterClientLogsModels"
|
|
||||||
@on-fetch="(data) => (clientLogsModelsOptions = data)"
|
|
||||||
auto-load
|
|
||||||
:url="urlClientLogsModels"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h5 class="flex justify-center color-vn-label">
|
|
||||||
{{ t('globals.noResults') }}
|
|
||||||
</h5>
|
|
||||||
|
|
||||||
<QDrawer :width="256" show-if-above side="right" v-model="stateStore.rightDrawer">
|
|
||||||
<div class="q-mt-sm q-px-md">
|
|
||||||
<VnInput :label="t('Search')" clearable>
|
|
||||||
<template #append>
|
|
||||||
<QIcon name="info" class="cursor-pointer">
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('Search by id or concept') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QIcon>
|
|
||||||
</template>
|
|
||||||
</VnInput>
|
|
||||||
<VnSelect
|
|
||||||
:label="t('Entity')"
|
|
||||||
:options="[]"
|
|
||||||
class="q-mt-md"
|
|
||||||
hide-selected
|
|
||||||
option-label="name"
|
|
||||||
option-value="id"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="q-mt-lg">
|
|
||||||
<QRadio
|
|
||||||
:dark="true"
|
|
||||||
:label="t('All')"
|
|
||||||
@update:model-value="getClientLogs($event, 'neq')"
|
|
||||||
dense
|
|
||||||
v-model="radioButtonValue"
|
|
||||||
val="all"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="q-mt-md">
|
|
||||||
<QRadio
|
|
||||||
:dark="true"
|
|
||||||
:label="t('User')"
|
|
||||||
@update:model-value="getClientLogs($event, 'neq')"
|
|
||||||
dense
|
|
||||||
v-model="radioButtonValue"
|
|
||||||
val="user"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="q-mt-md">
|
|
||||||
<QRadio
|
|
||||||
:dark="true"
|
|
||||||
:label="t('System')"
|
|
||||||
@update:model-value="getClientLogs($event, 'neq')"
|
|
||||||
dense
|
|
||||||
v-model="radioButtonValue"
|
|
||||||
val="system"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<VnSelect
|
|
||||||
:label="t('User')"
|
|
||||||
:options="[]"
|
|
||||||
class="q-mt-sm"
|
|
||||||
hide-selected
|
|
||||||
option-label="name"
|
|
||||||
option-value="id"
|
|
||||||
/>
|
|
||||||
<VnInput :label="t('Changes')" clearable class="q-mt-sm">
|
|
||||||
<template #append>
|
|
||||||
<QIcon name="info" class="cursor-pointer">
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('Search by changes') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QIcon>
|
|
||||||
</template>
|
|
||||||
</VnInput>
|
|
||||||
|
|
||||||
<div class="q-mt-md">
|
|
||||||
<QCheckbox
|
|
||||||
:label="t('Creates')"
|
|
||||||
@update:model-value="getClientLogs('insert', $event)"
|
|
||||||
v-model="insert"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<QCheckbox
|
|
||||||
:label="t('Edits')"
|
|
||||||
@update:model-value="getClientLogs('update', $event)"
|
|
||||||
v-model="update"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<QCheckbox
|
|
||||||
:label="t('Deletes')"
|
|
||||||
@update:model-value="getClientLogs('delete', $event)"
|
|
||||||
v-model="deletes"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<QCheckbox
|
|
||||||
:label="t('Accesses')"
|
|
||||||
@update:model-value="getClientLogs('select', $event)"
|
|
||||||
v-model="select"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<VnInputDate :label="t('Date')" class="q-mt-sm" />
|
|
||||||
<VnInput :label="t('To')" clearable class="q-mt-md" />
|
|
||||||
</div>
|
|
||||||
</QDrawer>
|
|
||||||
|
|
||||||
<QPageSticky
|
|
||||||
:offset="[18, 18]"
|
|
||||||
v-if="radioButtonValue !== 'all' || insert || update || deletes || select"
|
|
||||||
>
|
|
||||||
<QBtn color="primary" fab icon="filter_alt_off" />
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('Quit filter') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QPageSticky>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
|
||||||
es:
|
|
||||||
Search: Buscar
|
|
||||||
Search by id or concept: xxx
|
|
||||||
Entity: Entidad
|
|
||||||
All: Todo
|
|
||||||
User: Usuario
|
|
||||||
System: Sistema
|
|
||||||
Changes: Cambios
|
|
||||||
Search by changes: xxx
|
|
||||||
Creates: Crea
|
|
||||||
Edits: Modifica
|
|
||||||
Deletes: Elimina
|
|
||||||
Accesses: Accede
|
|
||||||
Date: Fecha
|
|
||||||
To: Hasta
|
|
||||||
Quit filter: Quitar filtro
|
|
||||||
</i18n>
|
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import VnNotes from 'src/components/ui/VnNotes.vue';
|
import VnNotes from 'src/components/ui/VnNotes.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const noteFilter = {
|
const noteFilter = computed(() => {
|
||||||
|
return {
|
||||||
order: 'created DESC',
|
order: 'created DESC',
|
||||||
where: {
|
where: {
|
||||||
clientFk: `${route.params.id}`,
|
clientFk: `${route.params.id}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,146 +1,107 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import axios from 'axios';
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { toCurrency, toDate } from 'src/filters';
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
|
|
||||||
import FetchData from 'components/FetchData.vue';
|
import VnTable from 'components/VnTable/VnTable.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const tableRef = ref();
|
||||||
const rows = ref([]);
|
const filter = computed(() => {
|
||||||
|
return {
|
||||||
const filter = {
|
|
||||||
where: { clientFk: route.params.id },
|
where: { clientFk: route.params.id },
|
||||||
order: ['started DESC'],
|
};
|
||||||
limit: 20,
|
});
|
||||||
|
const componentColumn = (type) => {
|
||||||
|
return {
|
||||||
|
columnFilter: {
|
||||||
|
component: type,
|
||||||
|
},
|
||||||
|
columnCreate: {
|
||||||
|
component: type,
|
||||||
|
},
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const tableColumnComponents = {
|
|
||||||
since: {
|
|
||||||
component: 'span',
|
|
||||||
props: () => {},
|
|
||||||
event: () => {},
|
|
||||||
},
|
|
||||||
to: {
|
|
||||||
component: 'span',
|
|
||||||
props: () => {},
|
|
||||||
event: () => {},
|
|
||||||
},
|
|
||||||
amount: {
|
|
||||||
component: 'span',
|
|
||||||
props: () => {},
|
|
||||||
event: () => {},
|
|
||||||
},
|
|
||||||
period: {
|
|
||||||
component: 'span',
|
|
||||||
props: () => {},
|
|
||||||
event: () => {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'started',
|
label: t('globals.since'),
|
||||||
label: t('Since'),
|
name: 'started',
|
||||||
name: 'since',
|
format: ({ started }) => toDate(started),
|
||||||
format: (value) => toDate(value),
|
create: true,
|
||||||
|
...componentColumn('date'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'finished',
|
name: 'finished',
|
||||||
label: t('To'),
|
label: t('globals.to'),
|
||||||
name: 'to',
|
format: ({ finished }) => toDate(finished),
|
||||||
format: (value) => toDate(value),
|
create: true,
|
||||||
|
...componentColumn('date'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'amount',
|
|
||||||
label: t('Amount'),
|
|
||||||
name: 'amount',
|
name: 'amount',
|
||||||
format: (value) => toCurrency(value),
|
label: t('globals.amount'),
|
||||||
|
format: ({ amount }) => toCurrency(amount),
|
||||||
|
create: true,
|
||||||
|
...componentColumn('number'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'period',
|
|
||||||
label: t('Period'),
|
|
||||||
name: 'period',
|
name: 'period',
|
||||||
|
label: t('Period'),
|
||||||
|
create: true,
|
||||||
|
...componentColumn('number'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'tableActions',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
title: t('Finish that recovery period'),
|
||||||
|
icon: 'lock',
|
||||||
|
show: (row) => !row.finished,
|
||||||
|
action: ({ id }) => setFinished(id),
|
||||||
|
isPrimary: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const toCustomerRecoverieCreate = () => {
|
function setFinished(id) {
|
||||||
router.push({ name: 'CustomerRecoverieCreate' });
|
axios.patch(`Recoveries/${id}`, { finished: Date.vnNow() });
|
||||||
};
|
tableRef.value.reload();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<VnTable
|
||||||
:filter="filter"
|
ref="tableRef"
|
||||||
@on-fetch="(data) => (rows = data)"
|
data-key="Recoveries"
|
||||||
auto-load
|
|
||||||
url="Recoveries"
|
url="Recoveries"
|
||||||
/>
|
search-url="recoveries"
|
||||||
|
:filter="filter"
|
||||||
<div class="full-width flex justify-center">
|
order="started DESC"
|
||||||
<QPage class="card-width q-pa-lg">
|
|
||||||
<QTable
|
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:no-data-label="t('globals.noResults')"
|
:use-model="true"
|
||||||
:pagination="{ rowsPerPage: 12 }"
|
:right-search="false"
|
||||||
:rows="rows"
|
:create="{
|
||||||
class="full-width q-mt-md"
|
urlCreate: 'Recoveries',
|
||||||
row-key="id"
|
title: 'New recovery',
|
||||||
>
|
onDataSaved: () => tableRef.reload(),
|
||||||
<template #body-cell="props">
|
formInitialData: { clientFk: route.params.id, started: Date.vnNew() },
|
||||||
<QTd :props="props">
|
}"
|
||||||
<QTr :props="props" class="cursor-pointer">
|
auto-load
|
||||||
<component
|
/>
|
||||||
:is="tableColumnComponents[props.col.name].component"
|
|
||||||
class="col-content"
|
|
||||||
v-bind="
|
|
||||||
tableColumnComponents[props.col.name].props(props)
|
|
||||||
"
|
|
||||||
@click="
|
|
||||||
tableColumnComponents[props.col.name].event(props)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ props.value }}
|
|
||||||
</component>
|
|
||||||
</QTr>
|
|
||||||
</QTd>
|
|
||||||
</template>
|
|
||||||
</QTable>
|
|
||||||
</QPage>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<QPageSticky :offset="[18, 18]">
|
|
||||||
<QBtn @click.stop="toCustomerRecoverieCreate()" color="primary" fab icon="add" />
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('New recoverie') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QPageSticky>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.consignees-card {
|
|
||||||
border: 2px solid var(--vn-accent-color);
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label-color {
|
|
||||||
color: var(--vn-label-color);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Since: Desde
|
|
||||||
To: Hasta
|
|
||||||
Amount: Importe
|
|
||||||
Period: Periodo
|
Period: Periodo
|
||||||
New recoverie: Nuevo recobro
|
New recovery: Nuevo recobro
|
||||||
|
Finish that recovery period: Terminar recobro
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import VnSms from 'src/components/ui/VnSms.vue';
|
import VnSms from 'src/components/ui/VnSms.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const id = route.params.id;
|
const where = computed(() => {
|
||||||
|
return {
|
||||||
const where = {
|
clientFk: route.params.id,
|
||||||
clientFk: id,
|
|
||||||
ticketFk: null,
|
ticketFk: null,
|
||||||
};
|
};
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="column items-center">
|
|
||||||
<VnSms url="clientSms" :where="where" />
|
<VnSms url="clientSms" :where="where" />
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -2,164 +2,81 @@
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
|
|
||||||
import { useValidator } from 'src/composables/useValidator';
|
|
||||||
import useNotify from 'src/composables/useNotify';
|
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
|
||||||
|
|
||||||
import FetchData from 'components/FetchData.vue';
|
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import CustomerChangePassword from 'src/pages/Customer/components/CustomerChangePassword.vue';
|
import CustomerChangePassword from 'src/pages/Customer/components/CustomerChangePassword.vue';
|
||||||
|
import FormModel from 'components/FormModel.vue';
|
||||||
|
|
||||||
const { notify } = useNotify();
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { validate } = useValidator();
|
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const stateStore = useStateStore();
|
|
||||||
|
|
||||||
const active = ref(false);
|
|
||||||
const canChangePassword = ref(0);
|
const canChangePassword = ref(0);
|
||||||
const email = ref(null);
|
|
||||||
const isLoading = ref(false);
|
|
||||||
const name = ref(null);
|
|
||||||
const usersPreviewRef = ref(null);
|
|
||||||
const user = ref([]);
|
|
||||||
|
|
||||||
const dataChanges = computed(() => {
|
const filter = computed(() => {
|
||||||
return (
|
return {
|
||||||
user.value.active !== active.value ||
|
fields: ['active', 'email', 'name'],
|
||||||
user.value.email !== email.value ||
|
where: { id: route.params.id },
|
||||||
user.value.name !== name.value
|
};
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const filter = { where: { id: `${route.params.id}` } };
|
|
||||||
|
|
||||||
const showChangePasswordDialog = () => {
|
const showChangePasswordDialog = () => {
|
||||||
quasar.dialog({
|
quasar.dialog({
|
||||||
component: CustomerChangePassword,
|
component: CustomerChangePassword,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
id: route.params.id,
|
id: route.params.id,
|
||||||
promise: usersPreviewRef.value.fetch(),
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const setInitialData = () => {
|
async function hasCustomerRole() {
|
||||||
if (user.value.length) {
|
const { data } = await axios(`Clients/${route.params.id}/hasCustomerRole`);
|
||||||
active.value = user.value[0].active;
|
canChangePassword.value = data;
|
||||||
email.value = user.value[0].email;
|
}
|
||||||
name.value = user.value[0].name;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmit = async () => {
|
|
||||||
isLoading.value = true;
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
active: active.value,
|
|
||||||
email: email.value,
|
|
||||||
name: name.value,
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
await axios.patch(`Clients/${route.params.id}/updateUser`, payload);
|
|
||||||
notify('globals.dataSaved', 'positive');
|
|
||||||
if (usersPreviewRef.value) usersPreviewRef.value.fetch();
|
|
||||||
} catch (error) {
|
|
||||||
notify('errors.create', 'negative');
|
|
||||||
} finally {
|
|
||||||
isLoading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FormModel
|
||||||
|
url="VnUsers/preview"
|
||||||
|
:url-update="`Clients/${route.params.id}/updateUser`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
@on-fetch="
|
model="webAccess"
|
||||||
(data) => {
|
:mapper="
|
||||||
user = data;
|
({ active, name, email }) => {
|
||||||
setInitialData();
|
return {
|
||||||
|
active,
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
@on-fetch="hasCustomerRole()"
|
||||||
auto-load
|
auto-load
|
||||||
ref="usersPreviewRef"
|
>
|
||||||
url="VnUsers/preview"
|
<template #form="{ data, validate }">
|
||||||
/>
|
<QCheckbox :label="t('Enable web access')" v-model="data.active" />
|
||||||
<FetchData
|
<VnInput :label="t('User')" clearable v-model="data.name" />
|
||||||
:url="`Clients/${route.params.id}/hasCustomerRole`"
|
|
||||||
@on-fetch="(data) => (canChangePassword = data)"
|
|
||||||
auto-load
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Teleport to="#st-actions" v-if="stateStore?.isSubToolbarShown()">
|
|
||||||
<QBtnGroup push class="q-gutter-x-sm">
|
|
||||||
<QBtn
|
|
||||||
:disabled="isLoading"
|
|
||||||
:label="t('globals.reset')"
|
|
||||||
:loading="isLoading"
|
|
||||||
@click="setInitialData"
|
|
||||||
color="primary"
|
|
||||||
flat
|
|
||||||
icon="restart_alt"
|
|
||||||
type="reset"
|
|
||||||
/>
|
|
||||||
<QBtn
|
|
||||||
:disabled="isLoading"
|
|
||||||
:label="t('Change password')"
|
|
||||||
:loading="isLoading"
|
|
||||||
@click.stop="showChangePasswordDialog()"
|
|
||||||
color="primary"
|
|
||||||
flat
|
|
||||||
icon="edit"
|
|
||||||
v-if="canChangePassword"
|
|
||||||
/>
|
|
||||||
<QBtn
|
|
||||||
:disabled="isLoading || !dataChanges"
|
|
||||||
:label="t('globals.save')"
|
|
||||||
:loading="isLoading"
|
|
||||||
@click="onSubmit"
|
|
||||||
color="primary"
|
|
||||||
icon="save"
|
|
||||||
/>
|
|
||||||
</QBtnGroup>
|
|
||||||
</Teleport>
|
|
||||||
|
|
||||||
<div class="full-width flex justify-center">
|
|
||||||
<QCard class="card-width q-pa-lg">
|
|
||||||
<QCardSection>
|
|
||||||
<QForm>
|
|
||||||
<QCheckbox :label="t('Enable web access')" v-model="active" />
|
|
||||||
|
|
||||||
<div class="q-px-sm">
|
|
||||||
<VnInput :label="t('User')" clearable v-model="name" />
|
|
||||||
<VnInput
|
<VnInput
|
||||||
:label="t('Recovery email')"
|
:label="t('Recovery email')"
|
||||||
:rules="validate('client.email')"
|
:rules="validate('client.email')"
|
||||||
clearable
|
clearable
|
||||||
type="email"
|
type="email"
|
||||||
v-model="email"
|
v-model="data.email"
|
||||||
class="q-mt-sm"
|
class="q-mt-sm"
|
||||||
>
|
:info="t('This email is used for user to regain access their account')"
|
||||||
<template #append>
|
/>
|
||||||
<QIcon name="info" class="cursor-pointer">
|
|
||||||
<QTooltip>{{
|
|
||||||
t(
|
|
||||||
'This email is used for user to regain access their account'
|
|
||||||
)
|
|
||||||
}}</QTooltip>
|
|
||||||
</QIcon>
|
|
||||||
</template>
|
</template>
|
||||||
</VnInput>
|
<template #moreActions>
|
||||||
</div>
|
<QBtn
|
||||||
</QForm>
|
:label="t('Change password')"
|
||||||
</QCardSection>
|
color="primary"
|
||||||
</QCard>
|
icon="edit"
|
||||||
</div>
|
:disable="!canChangePassword"
|
||||||
|
@click="showChangePasswordDialog()"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</FormModel>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -226,11 +226,6 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'recoveries',
|
path: 'recoveries',
|
||||||
name: 'RecoveriesCard',
|
|
||||||
redirect: { name: 'CustomerRecoveries' },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
name: 'CustomerRecoveries',
|
name: 'CustomerRecoveries',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'recoveries',
|
title: 'recoveries',
|
||||||
|
@ -239,19 +234,6 @@ export default {
|
||||||
component: () =>
|
component: () =>
|
||||||
import('src/pages/Customer/Card/CustomerRecoveries.vue'),
|
import('src/pages/Customer/Card/CustomerRecoveries.vue'),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'create',
|
|
||||||
name: 'CustomerRecoverieCreate',
|
|
||||||
meta: {
|
|
||||||
title: 'recoverie-create',
|
|
||||||
},
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
'src/pages/Customer/components/CustomerRecoverieCreate.vue'
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'web-access',
|
path: 'web-access',
|
||||||
name: 'CustomerWebAccess',
|
name: 'CustomerWebAccess',
|
||||||
|
|
Loading…
Reference in New Issue
Aixina detecta els canvis del filter també
Pot ser en algun cas done fallo, en VnPaginate me ha pasat que detectava si en el onMounted fea un fetch, despres detectava el canvi de url/filter i tambe fea el fetch. De moment ho dixaria aixina. Prove a tirar els e2e
PD: els he tirat i no he vist ningun fallo