forked from verdnatura/salix-front
Merge branch 'master' into Hotfix-ZoneEventsExclusion
This commit is contained in:
commit
4193710123
|
@ -10,6 +10,7 @@ import VnPaginate from 'components/ui/VnPaginate.vue';
|
||||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
import SkeletonTable from 'components/ui/SkeletonTable.vue';
|
import SkeletonTable from 'components/ui/SkeletonTable.vue';
|
||||||
import { tMobile } from 'src/composables/tMobile';
|
import { tMobile } from 'src/composables/tMobile';
|
||||||
|
import getDifferences from 'src/filters/getDifferences';
|
||||||
|
|
||||||
const { push } = useRouter();
|
const { push } = useRouter();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
@ -268,28 +269,6 @@ function getChanges() {
|
||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDifferences(obj1, obj2) {
|
|
||||||
let diff = {};
|
|
||||||
delete obj1.$index;
|
|
||||||
delete obj2.$index;
|
|
||||||
|
|
||||||
for (let key in obj1) {
|
|
||||||
if (obj2[key] && JSON.stringify(obj1[key]) !== JSON.stringify(obj2[key])) {
|
|
||||||
diff[key] = obj2[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let key in obj2) {
|
|
||||||
if (
|
|
||||||
obj1[key] === undefined ||
|
|
||||||
JSON.stringify(obj1[key]) !== JSON.stringify(obj2[key])
|
|
||||||
) {
|
|
||||||
diff[key] = obj2[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isEmpty(obj) {
|
function isEmpty(obj) {
|
||||||
if (obj == null) return true;
|
if (obj == null) return true;
|
||||||
if (obj === undefined) return true;
|
if (obj === undefined) return true;
|
||||||
|
|
|
@ -106,6 +106,7 @@ const originalData = ref({});
|
||||||
const formData = computed(() => state.get(modelValue));
|
const formData = computed(() => state.get(modelValue));
|
||||||
const defaultButtons = computed(() => ({
|
const defaultButtons = computed(() => ({
|
||||||
save: {
|
save: {
|
||||||
|
dataCy: 'saveDefaultBtn',
|
||||||
color: 'primary',
|
color: 'primary',
|
||||||
icon: 'save',
|
icon: 'save',
|
||||||
label: 'globals.save',
|
label: 'globals.save',
|
||||||
|
@ -113,6 +114,7 @@ const defaultButtons = computed(() => ({
|
||||||
type: 'submit',
|
type: 'submit',
|
||||||
},
|
},
|
||||||
reset: {
|
reset: {
|
||||||
|
dataCy: 'resetDefaultBtn',
|
||||||
color: 'primary',
|
color: 'primary',
|
||||||
icon: 'restart_alt',
|
icon: 'restart_alt',
|
||||||
label: 'globals.reset',
|
label: 'globals.reset',
|
||||||
|
@ -203,7 +205,9 @@ async function save() {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
try {
|
try {
|
||||||
formData.value = trimData(formData.value);
|
formData.value = trimData(formData.value);
|
||||||
const body = $props.mapper ? $props.mapper(formData.value) : formData.value;
|
const body = $props.mapper
|
||||||
|
? $props.mapper(formData.value, originalData.value)
|
||||||
|
: formData.value;
|
||||||
const method = $props.urlCreate ? 'post' : 'patch';
|
const method = $props.urlCreate ? 'post' : 'patch';
|
||||||
const url =
|
const url =
|
||||||
$props.urlCreate || $props.urlUpdate || $props.url || arrayData.store.url;
|
$props.urlCreate || $props.urlUpdate || $props.url || arrayData.store.url;
|
||||||
|
@ -317,6 +321,7 @@ defineExpose({
|
||||||
:title="t(defaultButtons.reset.label)"
|
:title="t(defaultButtons.reset.label)"
|
||||||
/>
|
/>
|
||||||
<QBtnDropdown
|
<QBtnDropdown
|
||||||
|
data-cy="saveAndContinueDefaultBtn"
|
||||||
v-if="$props.goTo"
|
v-if="$props.goTo"
|
||||||
@click="saveAndGo"
|
@click="saveAndGo"
|
||||||
:label="tMobile('globals.saveAndContinue')"
|
:label="tMobile('globals.saveAndContinue')"
|
||||||
|
|
|
@ -101,6 +101,7 @@ onBeforeRouteLeave((to, from, next) => {
|
||||||
@click="insert"
|
@click="insert"
|
||||||
class="q-mb-xs"
|
class="q-mb-xs"
|
||||||
dense
|
dense
|
||||||
|
data-cy="saveNote"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VnInput>
|
</VnInput>
|
||||||
|
|
|
@ -133,7 +133,7 @@ const addFilter = async (filter, params) => {
|
||||||
async function fetch(params) {
|
async function fetch(params) {
|
||||||
useArrayData(props.dataKey, params);
|
useArrayData(props.dataKey, params);
|
||||||
arrayData.reset(['filter.skip', 'skip', 'page']);
|
arrayData.reset(['filter.skip', 'skip', 'page']);
|
||||||
await arrayData.fetch({ append: false });
|
await arrayData.fetch({ append: false, updateRouter: mounted.value });
|
||||||
return emitStoreData();
|
return emitStoreData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
export default function getDifferences(obj1, obj2) {
|
||||||
|
let diff = {};
|
||||||
|
delete obj1.$index;
|
||||||
|
delete obj2.$index;
|
||||||
|
|
||||||
|
for (let key in obj1) {
|
||||||
|
if (obj2[key] && JSON.stringify(obj1[key]) !== JSON.stringify(obj2[key])) {
|
||||||
|
diff[key] = obj2[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let key in obj2) {
|
||||||
|
if (
|
||||||
|
obj1[key] === undefined ||
|
||||||
|
JSON.stringify(obj1[key]) !== JSON.stringify(obj2[key])
|
||||||
|
) {
|
||||||
|
diff[key] = obj2[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return diff;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
export default function getUpdatedValues(keys, formData) {
|
||||||
|
return keys.reduce((acc, key) => {
|
||||||
|
acc[key] = formData[key];
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
|
@ -11,11 +11,15 @@ import dashIfEmpty from './dashIfEmpty';
|
||||||
import dateRange from './dateRange';
|
import dateRange from './dateRange';
|
||||||
import toHour from './toHour';
|
import toHour from './toHour';
|
||||||
import dashOrCurrency from './dashOrCurrency';
|
import dashOrCurrency from './dashOrCurrency';
|
||||||
|
import getDifferences from './getDifferences';
|
||||||
|
import getUpdatedValues from './getUpdatedValues';
|
||||||
import getParamWhere from './getParamWhere';
|
import getParamWhere from './getParamWhere';
|
||||||
import parsePhone from './parsePhone';
|
import parsePhone from './parsePhone';
|
||||||
import isDialogOpened from './isDialogOpened';
|
import isDialogOpened from './isDialogOpened';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
getUpdatedValues,
|
||||||
|
getDifferences,
|
||||||
isDialogOpened,
|
isDialogOpened,
|
||||||
parsePhone,
|
parsePhone,
|
||||||
toLowerCase,
|
toLowerCase,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { onBeforeMount, ref, watch } from 'vue';
|
import { onBeforeMount, ref, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
|
@ -52,7 +53,6 @@ const addressFilter = {
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
const { id } = route.params;
|
const { id } = route.params;
|
||||||
getAddressesData(id);
|
|
||||||
getClientData(id);
|
getClientData(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -60,23 +60,10 @@ watch(
|
||||||
() => route.params.id,
|
() => route.params.id,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
if (!newValue) return;
|
if (!newValue) return;
|
||||||
getAddressesData(newValue);
|
|
||||||
getClientData(newValue);
|
getClientData(newValue);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const getAddressesData = async (id) => {
|
|
||||||
try {
|
|
||||||
const { data } = await axios.get(`Clients/${id}/addresses`, {
|
|
||||||
params: { filter: JSON.stringify(addressFilter) },
|
|
||||||
});
|
|
||||||
addresses.value = data;
|
|
||||||
sortAddresses();
|
|
||||||
} catch (error) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getClientData = async (id) => {
|
const getClientData = async (id) => {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get(`Clients/${id}`);
|
const { data } = await axios.get(`Clients/${id}`);
|
||||||
|
@ -101,9 +88,9 @@ const setDefault = (address) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const sortAddresses = () => {
|
const sortAddresses = (data) => {
|
||||||
if (!client.value || !addresses.value) return;
|
if (!client.value || !data) return;
|
||||||
addresses.value = addresses.value.sort((a, b) => {
|
addresses.value = data.sort((a, b) => {
|
||||||
return isDefaultAddress(b) - isDefaultAddress(a);
|
return isDefaultAddress(b) - isDefaultAddress(a);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -124,8 +111,17 @@ const toCustomerAddressEdit = (addressId) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<FetchData
|
||||||
|
@on-fetch="sortAddresses"
|
||||||
|
auto-load
|
||||||
|
data-key="CustomerAddresses"
|
||||||
|
order="id DESC"
|
||||||
|
ref="vnPaginateRef"
|
||||||
|
:filter="addressFilter"
|
||||||
|
:url="`Clients/${route.params.id}/addresses`"
|
||||||
|
/>
|
||||||
<div class="full-width flex justify-center">
|
<div class="full-width flex justify-center">
|
||||||
<QCard class="card-width q-pa-lg" v-if="addresses.length">
|
<QCard class="card-width q-pa-lg">
|
||||||
<QCardSection>
|
<QCardSection>
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in addresses"
|
v-for="(item, index) in addresses"
|
||||||
|
|
|
@ -9,6 +9,7 @@ import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import VnAvatar from 'src/components/ui/VnAvatar.vue';
|
import VnAvatar from 'src/components/ui/VnAvatar.vue';
|
||||||
|
import { getDifferences, getUpdatedValues } from 'src/filters';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -30,6 +31,13 @@ const exprBuilder = (param, value) => {
|
||||||
and: [{ active: { neq: false } }, handleSalesModelValue(value)],
|
and: [{ active: { neq: false } }, handleSalesModelValue(value)],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function onBeforeSave(formData, originalData) {
|
||||||
|
return getUpdatedValues(
|
||||||
|
Object.keys(getDifferences(formData, originalData)),
|
||||||
|
formData
|
||||||
|
);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FetchData
|
||||||
|
@ -43,7 +51,12 @@ const exprBuilder = (param, value) => {
|
||||||
@on-fetch="(data) => (businessTypes = data)"
|
@on-fetch="(data) => (businessTypes = data)"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<FormModel :url="`Clients/${route.params.id}`" auto-load model="customer">
|
<FormModel
|
||||||
|
:url="`Clients/${route.params.id}`"
|
||||||
|
auto-load
|
||||||
|
model="customer"
|
||||||
|
:mapper="onBeforeSave"
|
||||||
|
>
|
||||||
<template #form="{ data, validate }">
|
<template #form="{ data, validate }">
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnInput
|
<VnInput
|
||||||
|
@ -94,6 +107,7 @@ const exprBuilder = (param, value) => {
|
||||||
:rules="validate('client.phone')"
|
:rules="validate('client.phone')"
|
||||||
clearable
|
clearable
|
||||||
v-model="data.phone"
|
v-model="data.phone"
|
||||||
|
data-cy="customerPhone"
|
||||||
/>
|
/>
|
||||||
<VnInput
|
<VnInput
|
||||||
:label="t('customer.summary.mobile')"
|
:label="t('customer.summary.mobile')"
|
||||||
|
|
|
@ -28,12 +28,7 @@ const getBankEntities = (data, formData) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FormModel
|
<FormModel :url-update="`Clients/${route.params.id}`" auto-load model="customer">
|
||||||
:url-update="`Clients/${route.params.id}`"
|
|
||||||
:url="`Clients/${route.params.id}/getCard`"
|
|
||||||
auto-load
|
|
||||||
model="customer"
|
|
||||||
>
|
|
||||||
<template #form="{ data, validate }">
|
<template #form="{ data, validate }">
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
|
|
|
@ -93,22 +93,6 @@ const columns = computed(() => [
|
||||||
<WorkerDescriptorProxy :id="row.worker.id" />
|
<WorkerDescriptorProxy :id="row.worker.id" />
|
||||||
</template>
|
</template>
|
||||||
</VnTable>
|
</VnTable>
|
||||||
<!-- <QTable
|
|
||||||
:columns="columns"
|
|
||||||
:pagination="{ rowsPerPage: 0 }"
|
|
||||||
:rows="rows"
|
|
||||||
hide-bottom
|
|
||||||
row-key="id"
|
|
||||||
v-model:selected="selected"
|
|
||||||
class="card-width q-px-lg"
|
|
||||||
>
|
|
||||||
<template #body-cell-employee="{ row }">
|
|
||||||
<QTd @click.stop>
|
|
||||||
<span class="link">{{ row.worker.user.nickname }}</span>
|
|
||||||
<WorkerDescriptorProxy :id="row.clientFk" />
|
|
||||||
</QTd>
|
|
||||||
</template>
|
|
||||||
</QTable> -->
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -36,7 +36,10 @@ const entityId = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = ref(useCardDescription());
|
const data = ref(useCardDescription());
|
||||||
const setData = (entity) => (data.value = useCardDescription(entity?.name, entity?.id));
|
const setData = (entity) => {
|
||||||
|
data.value = useCardDescription(entity?.name, entity?.id);
|
||||||
|
if (customer.value) customer.value.webAccess = data.value?.account?.isActive;
|
||||||
|
};
|
||||||
const debtWarning = computed(() => {
|
const debtWarning = computed(() => {
|
||||||
return customer.value?.debt > customer.value?.credit ? 'negative' : 'primary';
|
return customer.value?.debt > customer.value?.credit ? 'negative' : 'primary';
|
||||||
});
|
});
|
||||||
|
|
|
@ -34,7 +34,6 @@ function handleLocation(data, location) {
|
||||||
/>
|
/>
|
||||||
<FormModel
|
<FormModel
|
||||||
:url-update="`Clients/${route.params.id}/updateFiscalData`"
|
:url-update="`Clients/${route.params.id}/updateFiscalData`"
|
||||||
:url="`Clients/${route.params.id}/getCard`"
|
|
||||||
auto-load
|
auto-load
|
||||||
model="customer"
|
model="customer"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,164 +1,82 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onBeforeMount, ref, watch, nextTick } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import VnInputDate from 'components/common/VnInputDate.vue';
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import FormModel from 'components/FormModel.vue';
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import axios from 'axios';
|
const formModelRef = ref(false);
|
||||||
import useNotify from 'src/composables/useNotify';
|
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { notify } = useNotify();
|
|
||||||
const stateStore = useStateStore();
|
|
||||||
|
|
||||||
const amountInputRef = ref(null);
|
const amountInputRef = ref(null);
|
||||||
const initialDated = Date.vnNew();
|
|
||||||
const unpaidClient = ref(false);
|
|
||||||
const isLoading = ref(false);
|
|
||||||
const amount = ref(null);
|
|
||||||
const dated = ref(initialDated);
|
|
||||||
|
|
||||||
const initialData = ref({
|
const initialData = ref({
|
||||||
dated: initialDated,
|
dated: Date.vnNew(),
|
||||||
|
amount: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasChanged = computed(() => {
|
const filterClientFindOne = {
|
||||||
return (
|
fields: ['unpaid', 'dated', 'amount'],
|
||||||
initialData.value.dated !== dated.value ||
|
where: {
|
||||||
initialData.value.amount !== amount.value
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
getData(route.params.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => route.params.id,
|
|
||||||
(newValue) => {
|
|
||||||
if (!newValue) return;
|
|
||||||
getData(newValue);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const getData = async (id) => {
|
|
||||||
const filter = { where: { clientFk: id } };
|
|
||||||
try {
|
|
||||||
const { data } = await axios.get('ClientUnpaids', {
|
|
||||||
params: { filter: JSON.stringify(filter) },
|
|
||||||
});
|
|
||||||
if (data.length) {
|
|
||||||
setValues(data[0]);
|
|
||||||
} else {
|
|
||||||
defaultValues();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
defaultValues();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const setValues = (data) => {
|
|
||||||
unpaidClient.value = true;
|
|
||||||
amount.value = data.amount;
|
|
||||||
dated.value = data.dated;
|
|
||||||
initialData.value = data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultValues = () => {
|
|
||||||
unpaidClient.value = false;
|
|
||||||
initialData.value.amount = null;
|
|
||||||
setInitialData();
|
|
||||||
};
|
|
||||||
|
|
||||||
const setInitialData = () => {
|
|
||||||
amount.value = initialData.value.amount;
|
|
||||||
dated.value = initialData.value.dated;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmit = async () => {
|
|
||||||
isLoading.value = true;
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
amount: amount.value,
|
|
||||||
clientFk: route.params.id,
|
clientFk: route.params.id,
|
||||||
dated: dated.value,
|
},
|
||||||
};
|
};
|
||||||
try {
|
|
||||||
await axios.patch('ClientUnpaids', payload);
|
|
||||||
notify('globals.dataSaved', 'positive');
|
|
||||||
unpaidClient.value = true;
|
|
||||||
} catch (error) {
|
|
||||||
notify('errors.writeRequest', 'negative');
|
|
||||||
} finally {
|
|
||||||
isLoading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => unpaidClient.value,
|
|
||||||
async (val) => {
|
|
||||||
await nextTick();
|
|
||||||
if (val) amountInputRef.value.focus();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Teleport v-if="stateStore?.isSubToolbarShown()" to="#st-actions">
|
<FetchData
|
||||||
<QBtnGroup push class="q-gutter-x-sm">
|
:filter="filterClientFindOne"
|
||||||
<QBtn
|
auto-load
|
||||||
:disabled="!hasChanged"
|
url="ClientUnpaids"
|
||||||
:label="t('globals.reset')"
|
@on-fetch="
|
||||||
:loading="isLoading"
|
(data) => {
|
||||||
@click="setInitialData"
|
const unpaid = data.length == 1;
|
||||||
color="primary"
|
initialData = { ...data[0], unpaid };
|
||||||
flat
|
}
|
||||||
icon="restart_alt"
|
"
|
||||||
type="reset"
|
|
||||||
/>
|
/>
|
||||||
<QBtn
|
<QCard>
|
||||||
:disabled="!hasChanged"
|
<FormModel
|
||||||
:label="t('globals.save')"
|
v-if="'unpaid' in initialData"
|
||||||
:loading="isLoading"
|
:observe-form-changes="false"
|
||||||
@click="onSubmit"
|
ref="formModelRef"
|
||||||
color="primary"
|
model="unpaid"
|
||||||
icon="save"
|
url-update="ClientUnpaids"
|
||||||
/>
|
:mapper="(formData) => ({ ...formData, clientFk: route.params.id })"
|
||||||
</QBtnGroup>
|
:form-initial-data="initialData"
|
||||||
</Teleport>
|
>
|
||||||
|
<template #form="{ data }">
|
||||||
<div class="full-width flex justify-center">
|
|
||||||
<QCard class="card-width q-pa-lg">
|
|
||||||
<QForm>
|
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<div class="col">
|
<QCheckbox :label="t('Unpaid client')" v-model="data.unpaid" />
|
||||||
<QCheckbox :label="t('Unpaid client')" v-model="unpaidClient" />
|
|
||||||
</div>
|
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
|
||||||
<VnRow class="row q-gutter-md q-mb-md" v-show="unpaidClient">
|
<VnRow class="row q-gutter-md q-mb-md" v-show="data.unpaid">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<VnInputDate :label="t('Date')" v-model="dated" />
|
<VnInputDate
|
||||||
|
data-cy="customerUnpaidDate"
|
||||||
|
:label="t('Date')"
|
||||||
|
v-model="data.dated"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<VnInput
|
<VnInputNumber
|
||||||
|
data-cy="customerUnpaidAmount"
|
||||||
ref="amountInputRef"
|
ref="amountInputRef"
|
||||||
:label="t('Amount')"
|
:label="t('Amount')"
|
||||||
clearable
|
clearable
|
||||||
type="number"
|
v-model="data.amount"
|
||||||
v-model="amount"
|
|
||||||
autofocus
|
autofocus
|
||||||
>
|
>
|
||||||
<template #append>€</template></VnInput
|
<template #append>€</template></VnInputNumber
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
</QForm>
|
</template>
|
||||||
|
</FormModel>
|
||||||
</QCard>
|
</QCard>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -25,10 +25,9 @@ async function hasCustomerRole() {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<FormModel
|
<FormModel
|
||||||
url="VnUsers/preview"
|
|
||||||
:url-update="`Clients/${route.params.id}/updateUser`"
|
:url-update="`Clients/${route.params.id}/updateUser`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
model="webAccess"
|
model="customer"
|
||||||
:mapper="
|
:mapper="
|
||||||
({ active, name, email }) => {
|
({ active, name, email }) => {
|
||||||
return {
|
return {
|
||||||
|
@ -42,7 +41,7 @@ async function hasCustomerRole() {
|
||||||
auto-load
|
auto-load
|
||||||
>
|
>
|
||||||
<template #form="{ data, validate }">
|
<template #form="{ data, validate }">
|
||||||
<QCheckbox :label="t('Enable web access')" v-model="data.active" />
|
<QCheckbox :label="t('Enable web access')" v-model="data.account.active" />
|
||||||
<VnInput :label="t('User')" clearable v-model="data.name" />
|
<VnInput :label="t('User')" clearable v-model="data.name" />
|
||||||
<VnInput
|
<VnInput
|
||||||
:label="t('Recovery email')"
|
:label="t('Recovery email')"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onBeforeMount, ref, watch } 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 FetchData from 'src/components/FetchData.vue';
|
||||||
|
|
||||||
import { toCurrency, toDateHourMin } from 'src/filters';
|
import { toCurrency, toDateHourMin } from 'src/filters';
|
||||||
|
|
||||||
|
@ -20,10 +20,11 @@ const filter = {
|
||||||
{ relation: 'mandateType', scope: { fields: ['id', 'name'] } },
|
{ relation: 'mandateType', scope: { fields: ['id', 'name'] } },
|
||||||
{ relation: 'company', scope: { fields: ['id', 'code'] } },
|
{ relation: 'company', scope: { fields: ['id', 'code'] } },
|
||||||
],
|
],
|
||||||
where: { clientFk: null },
|
where: { clientFk: route.params.id },
|
||||||
order: ['created DESC'],
|
order: ['created DESC'],
|
||||||
limit: 20,
|
limit: 20,
|
||||||
};
|
};
|
||||||
|
const ClientDmsRef = ref(false);
|
||||||
|
|
||||||
const tableColumnComponents = {
|
const tableColumnComponents = {
|
||||||
state: {
|
state: {
|
||||||
|
@ -50,7 +51,7 @@ const tableColumnComponents = {
|
||||||
component: CustomerCheckIconTooltip,
|
component: CustomerCheckIconTooltip,
|
||||||
props: ({ row }) => ({
|
props: ({ row }) => ({
|
||||||
transaction: row,
|
transaction: row,
|
||||||
promise: refreshData,
|
promise: () => ClientDmsRef.value.fetch(),
|
||||||
}),
|
}),
|
||||||
event: () => {},
|
event: () => {},
|
||||||
},
|
},
|
||||||
|
@ -89,38 +90,16 @@ const columns = computed(() => [
|
||||||
name: 'validate',
|
name: 'validate',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
getData(route.params.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => route.params.id,
|
|
||||||
(newValue) => {
|
|
||||||
if (!newValue) return;
|
|
||||||
getData(newValue);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const getData = async (id) => {
|
|
||||||
filter.where.clientFk = id;
|
|
||||||
try {
|
|
||||||
const { data } = await axios.get('clients/transactions', {
|
|
||||||
params: { filter: JSON.stringify(filter) },
|
|
||||||
});
|
|
||||||
rows.value = data;
|
|
||||||
} catch (error) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const refreshData = () => {
|
|
||||||
getData(route.params.id);
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="full-width flex justify-center">
|
<FetchData
|
||||||
|
ref="ClientDmsRef"
|
||||||
|
:filter="filter"
|
||||||
|
@on-fetch="(data) => (rows = data)"
|
||||||
|
auto-load
|
||||||
|
url="Clients/transactions"
|
||||||
|
/>
|
||||||
<QPage class="card-width q-pa-lg">
|
<QPage class="card-width q-pa-lg">
|
||||||
<QTable
|
<QTable
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
|
@ -135,13 +114,9 @@ const refreshData = () => {
|
||||||
<QTr :props="props">
|
<QTr :props="props">
|
||||||
<component
|
<component
|
||||||
:is="tableColumnComponents[props.col.name].component"
|
:is="tableColumnComponents[props.col.name].component"
|
||||||
@click="
|
@click="tableColumnComponents[props.col.name].event(props)"
|
||||||
tableColumnComponents[props.col.name].event(props)
|
|
||||||
"
|
|
||||||
class="rounded-borders q-pa-sm"
|
class="rounded-borders q-pa-sm"
|
||||||
v-bind="
|
v-bind="tableColumnComponents[props.col.name].props(props)"
|
||||||
tableColumnComponents[props.col.name].props(props)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
{{ props.value }}
|
{{ props.value }}
|
||||||
</component>
|
</component>
|
||||||
|
@ -154,7 +129,6 @@ const refreshData = () => {
|
||||||
{{ t('globals.noResults') }}
|
{{ t('globals.noResults') }}
|
||||||
</h5>
|
</h5>
|
||||||
</QPage>
|
</QPage>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onBeforeMount, reactive, ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
import axios from 'axios';
|
|
||||||
import VnLocation from 'src/components/common/VnLocation.vue';
|
import VnLocation from 'src/components/common/VnLocation.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import FormModel from 'components/FormModel.vue';
|
import FormModel from 'components/FormModel.vue';
|
||||||
|
@ -25,20 +24,6 @@ const agencyModes = ref([]);
|
||||||
const incoterms = ref([]);
|
const incoterms = ref([]);
|
||||||
const customsAgents = ref([]);
|
const customsAgents = ref([]);
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
urlCreate.value = `Clients/${route.params.id}/createAddress`;
|
|
||||||
getCustomsAgents();
|
|
||||||
});
|
|
||||||
|
|
||||||
const getCustomsAgents = async () => {
|
|
||||||
const { data } = await axios.get('CustomsAgents');
|
|
||||||
customsAgents.value = data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const refreshData = () => {
|
|
||||||
getCustomsAgents();
|
|
||||||
};
|
|
||||||
|
|
||||||
const toCustomerAddress = () => {
|
const toCustomerAddress = () => {
|
||||||
router.push({
|
router.push({
|
||||||
name: 'CustomerAddress',
|
name: 'CustomerAddress',
|
||||||
|
@ -54,6 +39,11 @@ function handleLocation(data, location) {
|
||||||
data.provinceFk = provinceFk;
|
data.provinceFk = provinceFk;
|
||||||
data.countryFk = countryFk;
|
data.countryFk = countryFk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onAgentCreated(requestResponse, data) {
|
||||||
|
customsAgents.value.push(requestResponse);
|
||||||
|
data.customsAgentFk = requestResponse.id;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -139,6 +129,7 @@ function handleLocation(data, location) {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<VnSelectDialog
|
<VnSelectDialog
|
||||||
|
url="CustomsAgents"
|
||||||
:label="t('Customs agent')"
|
:label="t('Customs agent')"
|
||||||
:options="customsAgents"
|
:options="customsAgents"
|
||||||
hide-selected
|
hide-selected
|
||||||
|
@ -148,7 +139,12 @@ function handleLocation(data, location) {
|
||||||
:tooltip="t('Create a new expense')"
|
:tooltip="t('Create a new expense')"
|
||||||
>
|
>
|
||||||
<template #form>
|
<template #form>
|
||||||
<CustomerNewCustomsAgent @on-data-saved="refreshData()" />
|
<CustomerNewCustomsAgent
|
||||||
|
@on-data-saved="
|
||||||
|
(_, requestResponse) =>
|
||||||
|
onAgentCreated(requestResponse, data)
|
||||||
|
"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VnSelectDialog>
|
</VnSelectDialog>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
|
|
@ -144,7 +144,7 @@ function handleLocation(data, location) {
|
||||||
:url="`Addresses/${route.params.addressId}`"
|
:url="`Addresses/${route.params.addressId}`"
|
||||||
@on-data-saved="onDataSaved()"
|
@on-data-saved="onDataSaved()"
|
||||||
auto-load
|
auto-load
|
||||||
model="client"
|
model="customer"
|
||||||
>
|
>
|
||||||
<template #moreActions>
|
<template #moreActions>
|
||||||
<QBtn
|
<QBtn
|
||||||
|
|
|
@ -82,11 +82,11 @@ const entriesTableColumns = computed(() => [
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
<QCardActions align="right">
|
<QCardActions align="right">
|
||||||
<QBtn
|
<QBtn
|
||||||
:label="t('printLabels')"
|
:label="t('myEntries.printLabels')"
|
||||||
color="primary"
|
color="primary"
|
||||||
icon="print"
|
icon="print"
|
||||||
:loading="isLoading"
|
:loading="isLoading"
|
||||||
@click="openReport(`Entries/${entityId}/print`)"
|
@click="openReport(`Entries/${entityId}/labelSupplier`)"
|
||||||
unelevated
|
unelevated
|
||||||
autofocus
|
autofocus
|
||||||
/>
|
/>
|
||||||
|
@ -126,7 +126,9 @@ const entriesTableColumns = computed(() => [
|
||||||
"
|
"
|
||||||
unelevated
|
unelevated
|
||||||
>
|
>
|
||||||
<QTooltip>{{ t('viewLabel') }}</QTooltip>
|
<QTooltip>{{
|
||||||
|
t('myEntries.viewLabel')
|
||||||
|
}}</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QTr>
|
</QTr>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -101,7 +101,7 @@ const columns = computed(() => [
|
||||||
name: 'tableActions',
|
name: 'tableActions',
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
title: t('printLabels'),
|
title: t('myEntries.printLabels'),
|
||||||
icon: 'print',
|
icon: 'print',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
action: (row) => printBuys(row.id),
|
action: (row) => printBuys(row.id),
|
||||||
|
|
|
@ -321,10 +321,6 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<span v-for="(saleComponent, index) in row.components" :key="index">
|
<span v-for="(saleComponent, index) in row.components" :key="index">
|
||||||
{{ toCurrency(saleComponent.value * row.quantity, 'EUR', 3) }}
|
{{ toCurrency(saleComponent.value * row.quantity, 'EUR', 3) }}
|
||||||
<!-- <QTooltip>
|
|
||||||
{{ saleComponent.component?.name }}:
|
|
||||||
{{ toCurrency(saleComponent.value, 'EUR', 3) }}
|
|
||||||
</QTooltip> -->
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -181,17 +181,34 @@ const resetChanges = async () => {
|
||||||
arrayData.fetch({ append: false });
|
arrayData.fetch({ append: false });
|
||||||
tableRef.value.reload();
|
tableRef.value.reload();
|
||||||
};
|
};
|
||||||
|
const rowToUpdate = ref(null);
|
||||||
|
const changeQuantity = async (sale) => {
|
||||||
|
canProceed.value = await isSalePrepared(sale);
|
||||||
|
if (!canProceed.value) return;
|
||||||
|
if (
|
||||||
|
!sale.itemFk ||
|
||||||
|
sale.quantity == null ||
|
||||||
|
edit.value?.oldQuantity === sale.quantity
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
if (!sale.id) return addSale(sale);
|
||||||
|
|
||||||
const updateQuantity = async (sale) => {
|
|
||||||
const params = { quantity: sale.quantity };
|
|
||||||
try {
|
try {
|
||||||
await axios.post(`Sales/${sale.id}/updateQuantity`, params);
|
if (!rowToUpdate.value) return;
|
||||||
|
rowToUpdate.value = null;
|
||||||
|
await updateQuantity(sale);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
sale.quantity = tableRef.value.CrudModelRef.originalData.find(
|
const { quantity } = tableRef.value.CrudModelRef.originalData.find(
|
||||||
(s) => s.id === sale.id
|
(s) => s.id === sale.id
|
||||||
).quantity;
|
);
|
||||||
|
sale.quantity = quantity;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateQuantity = async ({ quantity, id }) => {
|
||||||
|
const params = { quantity: quantity };
|
||||||
|
await axios.post(`Sales/${id}/updateQuantity`, params);
|
||||||
notify('globals.dataSaved', 'positive');
|
notify('globals.dataSaved', 'positive');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -219,19 +236,6 @@ const addSale = async (sale) => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeQuantity = async (sale) => {
|
|
||||||
canProceed.value = await isSalePrepared(sale);
|
|
||||||
if (!canProceed.value) return;
|
|
||||||
if (
|
|
||||||
!sale.itemFk ||
|
|
||||||
sale.quantity == null ||
|
|
||||||
edit.value?.oldQuantity === sale.quantity
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
if (!sale.id) return addSale(sale);
|
|
||||||
await updateQuantity(sale);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateConcept = async (sale) => {
|
const updateConcept = async (sale) => {
|
||||||
canProceed.value = await isSalePrepared(sale);
|
canProceed.value = await isSalePrepared(sale);
|
||||||
if (!canProceed.value) return;
|
if (!canProceed.value) return;
|
||||||
|
@ -768,16 +772,12 @@ watch(
|
||||||
</template>
|
</template>
|
||||||
<template #column-quantity="{ row }">
|
<template #column-quantity="{ row }">
|
||||||
<VnInput
|
<VnInput
|
||||||
v-if="row.isNew"
|
v-if="row.isNew || isTicketEditable"
|
||||||
v-model.number="row.quantity"
|
|
||||||
type="number"
|
type="number"
|
||||||
@blur="changeQuantity(row)"
|
|
||||||
@focus="edit.oldQuantity = row.quantity"
|
|
||||||
/>
|
|
||||||
<VnInput
|
|
||||||
v-else-if="isTicketEditable"
|
|
||||||
v-model.number="row.quantity"
|
v-model.number="row.quantity"
|
||||||
@blur="changeQuantity(row)"
|
@blur="changeQuantity(row)"
|
||||||
|
@keyup.enter="changeQuantity(row)"
|
||||||
|
@update:model-value="() => (rowToUpdate = row)"
|
||||||
@focus="edit.oldQuantity = row.quantity"
|
@focus="edit.oldQuantity = row.quantity"
|
||||||
/>
|
/>
|
||||||
<span v-else>{{ row.quantity }}</span>
|
<span v-else>{{ row.quantity }}</span>
|
||||||
|
|
|
@ -3,11 +3,17 @@ describe('Client basic data', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.viewport(1280, 720);
|
cy.viewport(1280, 720);
|
||||||
cy.login('developer');
|
cy.login('developer');
|
||||||
cy.visit('#/customer/1110/basic-data', {
|
cy.visit('#/customer/1102/basic-data');
|
||||||
timeout: 5000,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
it('Should load layout', () => {
|
it('Should load layout', () => {
|
||||||
cy.get('.q-card').should('be.visible');
|
cy.get('.q-card').should('be.visible');
|
||||||
|
cy.dataCy('customerPhone').filter('input').should('be.visible');
|
||||||
|
cy.dataCy('customerPhone').filter('input').type('123456789');
|
||||||
|
cy.get('.q-btn-group > .q-btn--standard').click();
|
||||||
|
cy.intercept('PATCH', '/api/Clients/1102', (req) => {
|
||||||
|
const { body } = req;
|
||||||
|
cy.wrap(body).should('have.property', 'phone', '123456789');
|
||||||
|
});
|
||||||
|
cy.get('.q-notification__message').should('have.text', 'Data saved');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,6 +8,6 @@ describe('Client billing data', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should load layout', () => {
|
it('Should load layout', () => {
|
||||||
cy.get('.q-card').should('be.visible');
|
cy.get('.q-page').should('be.visible');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,12 +17,14 @@ describe('Client list', () => {
|
||||||
|
|
||||||
it('Client list create new client', () => {
|
it('Client list create new client', () => {
|
||||||
cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click();
|
cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click();
|
||||||
|
const randomInt = Math.floor(Math.random() * 90) + 10;
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
Name: { val: 'Name 1' },
|
Name: { val: `Name ${randomInt}` },
|
||||||
'Social name': { val: 'TEST 1' },
|
'Social name': { val: `TEST ${randomInt}` },
|
||||||
'Tax number': { val: '20852113Z' },
|
'Tax number': { val: `20852${randomInt.length}3Z` },
|
||||||
'Web user': { val: 'user_test_1' },
|
'Web user': { val: `user_test_${randomInt}` },
|
||||||
Street: { val: 'C/ STREET 1' },
|
Street: { val: `C/ STREET ${randomInt}` },
|
||||||
Email: { val: 'user.test@1.com' },
|
Email: { val: 'user.test@1.com' },
|
||||||
'Sales person': { val: 'employee', type: 'select' },
|
'Sales person': { val: 'employee', type: 'select' },
|
||||||
Location: { val: '46000, Valencia(Province one), España', type: 'select' },
|
Location: { val: '46000, Valencia(Province one), España', type: 'select' },
|
||||||
|
@ -32,7 +34,7 @@ describe('Client list', () => {
|
||||||
|
|
||||||
cy.get('.q-mt-lg > .q-btn--standard').click();
|
cy.get('.q-mt-lg > .q-btn--standard').click();
|
||||||
|
|
||||||
cy.checkNotification('created');
|
cy.checkNotification('Data saved');
|
||||||
cy.url().should('include', '/summary');
|
cy.url().should('include', '/summary');
|
||||||
});
|
});
|
||||||
it('Client list search client', () => {
|
it('Client list search client', () => {
|
||||||
|
@ -54,8 +56,8 @@ describe('Client list', () => {
|
||||||
cy.openActionDescriptor('Create ticket');
|
cy.openActionDescriptor('Create ticket');
|
||||||
cy.waitForElement('#formModel');
|
cy.waitForElement('#formModel');
|
||||||
cy.waitForElement('.q-form');
|
cy.waitForElement('.q-form');
|
||||||
cy.checkValueSelectForm(1, search);
|
cy.checkValueForm(1, search);
|
||||||
cy.checkValueSelectForm(2, search);
|
cy.checkValueForm(2, search);
|
||||||
});
|
});
|
||||||
it('Client founded create order', () => {
|
it('Client founded create order', () => {
|
||||||
const search = 'Jessica Jones';
|
const search = 'Jessica Jones';
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
/// <reference types="cypress" />
|
||||||
|
describe('Client notes', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport(1280, 720);
|
||||||
|
cy.login('developer');
|
||||||
|
cy.visit('#/customer/1101/sms');
|
||||||
|
});
|
||||||
|
it('Should load layout', () => {
|
||||||
|
cy.get('.q-page').should('be.visible');
|
||||||
|
cy.get('.q-page > :nth-child(2) > :nth-child(1)').should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,11 +3,26 @@ describe('Client web-access', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.viewport(1280, 720);
|
cy.viewport(1280, 720);
|
||||||
cy.login('developer');
|
cy.login('developer');
|
||||||
cy.visit('#/customer/1110/web-access', {
|
|
||||||
timeout: 5000,
|
|
||||||
});
|
});
|
||||||
});
|
it('Should test buttons ', () => {
|
||||||
it('Should load layout', () => {
|
cy.visit('#/customer/1101/web-access');
|
||||||
|
cy.get('.q-page').should('be.visible');
|
||||||
|
cy.get('#formModel').should('be.visible');
|
||||||
cy.get('.q-card').should('be.visible');
|
cy.get('.q-card').should('be.visible');
|
||||||
|
cy.get('.q-btn-group > :nth-child(1)').should('not.be.disabled');
|
||||||
|
cy.get('.q-checkbox__inner').click();
|
||||||
|
cy.get('.q-btn-group > .q-btn--standard.q-btn--actionable').should(
|
||||||
|
'not.be.disabled'
|
||||||
|
);
|
||||||
|
cy.get('.q-btn-group > .q-btn--flat').should('not.be.disabled');
|
||||||
|
cy.get('.q-btn-group > :nth-child(1)').click();
|
||||||
|
cy.get('.q-dialog__inner > .q-card > :nth-child(1)')
|
||||||
|
.should('be.visible')
|
||||||
|
.find('.text-h6')
|
||||||
|
.should('have.text', 'Change password');
|
||||||
|
});
|
||||||
|
it('Should disabled buttons', () => {
|
||||||
|
cy.visit('#/customer/1110/web-access');
|
||||||
|
cy.get('.q-btn-group > :nth-child(1)').should('be.disabled');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/// <reference types="cypress" />
|
/// <reference types="cypress" />
|
||||||
describe('Client credit opinion', () => {
|
describe('Client credit contracts', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.viewport(1280, 720);
|
cy.viewport(1280, 720);
|
||||||
cy.login('developer');
|
cy.login('developer');
|
||||||
|
@ -8,6 +8,6 @@ describe('Client credit opinion', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should load layout', () => {
|
it('Should load layout', () => {
|
||||||
cy.get('.q-card').should('be.visible');
|
cy.get('.q-page').should('be.visible');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,11 +3,17 @@ describe('Client unpaid', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.viewport(1280, 720);
|
cy.viewport(1280, 720);
|
||||||
cy.login('developer');
|
cy.login('developer');
|
||||||
cy.visit('#/customer/1110/others/unpaid', {
|
|
||||||
timeout: 5000,
|
|
||||||
});
|
});
|
||||||
});
|
it('Should add unpaid', () => {
|
||||||
it('Should load layout', () => {
|
cy.visit('#/customer/1102/others/unpaid');
|
||||||
cy.get('.q-card').should('be.visible');
|
cy.get('.q-card').should('be.visible');
|
||||||
|
cy.get('.q-checkbox__inner').click();
|
||||||
|
cy.dataCy('customerUnpaidAmount').find('input').type('100');
|
||||||
|
cy.dataCy('customerUnpaidDate').find('input').type('01/01/2001');
|
||||||
|
cy.get('.q-btn-group > .q-btn--standard').click();
|
||||||
|
cy.reload();
|
||||||
|
cy.get('.q-checkbox__inner')
|
||||||
|
.should('be.visible')
|
||||||
|
.and('not.have.class', 'q-checkbox__inner--active');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -254,6 +254,7 @@ Cypress.Commands.add('writeSearchbar', (value) => {
|
||||||
value
|
value
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('validateContent', (selector, expectedValue) => {
|
Cypress.Commands.add('validateContent', (selector, expectedValue) => {
|
||||||
cy.get(selector).should('have.text', expectedValue);
|
cy.get(selector).should('have.text', expectedValue);
|
||||||
});
|
});
|
||||||
|
@ -275,16 +276,38 @@ Cypress.Commands.add('clickButtonsDescriptor', (id) => {
|
||||||
.click();
|
.click();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add('openActionDescriptor', (opt) => {
|
||||||
|
cy.openActionsDescriptor();
|
||||||
|
const listItem = '[role="menu"] .q-list .q-item';
|
||||||
|
cy.contains(listItem, opt).click();
|
||||||
|
1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add('clickButtonsDescriptor', (id) => {
|
||||||
|
cy.get(`.actions > .q-card__actions> .q-btn:nth-child(${id})`)
|
||||||
|
.invoke('removeAttr', 'target')
|
||||||
|
.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add('openActionDescriptor', (opt) => {
|
||||||
|
cy.openActionsDescriptor();
|
||||||
|
const listItem = '[role="menu"] .q-list .q-item';
|
||||||
|
cy.contains(listItem, opt).click();
|
||||||
|
1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add('clickButtonsDescriptor', (id) => {
|
||||||
|
cy.get(`.actions > .q-card__actions> .q-btn:nth-child(${id})`)
|
||||||
|
.invoke('removeAttr', 'target')
|
||||||
|
.click();
|
||||||
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('openUserPanel', () => {
|
Cypress.Commands.add('openUserPanel', () => {
|
||||||
cy.get(
|
cy.get(
|
||||||
'.column > .q-avatar > .q-avatar__content > .q-img > .q-img__container > .q-img__image'
|
'.column > .q-avatar > .q-avatar__content > .q-img > .q-img__container > .q-img__image'
|
||||||
).click();
|
).click();
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('openActions', (row) => {
|
|
||||||
cy.get('tbody > tr').eq(row).find('.actions > .q-btn').click();
|
|
||||||
});
|
|
||||||
|
|
||||||
Cypress.Commands.add('checkNotification', (text) => {
|
Cypress.Commands.add('checkNotification', (text) => {
|
||||||
cy.get('.q-notification')
|
cy.get('.q-notification')
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
|
@ -295,10 +318,14 @@ Cypress.Commands.add('checkNotification', (text) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add('openActions', (row) => {
|
||||||
|
cy.get('tbody > tr').eq(row).find('.actions > .q-btn').click();
|
||||||
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('checkValueForm', (id, search) => {
|
Cypress.Commands.add('checkValueForm', (id, search) => {
|
||||||
cy.get(
|
cy.get(`.grid-create > :nth-child(${id}) `)
|
||||||
`.grid-create > :nth-child(${id}) > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > .q-field__input`
|
.find('input')
|
||||||
).should('have.value', search);
|
.should('have.value', search);
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('checkValueSelectForm', (id, search) => {
|
Cypress.Commands.add('checkValueSelectForm', (id, search) => {
|
||||||
|
@ -310,3 +337,7 @@ Cypress.Commands.add('checkValueSelectForm', (id, search) => {
|
||||||
Cypress.Commands.add('searchByLabel', (label, value) => {
|
Cypress.Commands.add('searchByLabel', (label, value) => {
|
||||||
cy.get(`[label="${label}"] > .q-field > .q-field__inner`).type(`${value}{enter}`);
|
cy.get(`[label="${label}"] > .q-field > .q-field__inner`).type(`${value}{enter}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add('dataCy', (tag, attr = 'data-cy') => {
|
||||||
|
return cy.get(`[${attr}="${tag}"]`);
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue