#8448 - devToTest #1254

Merged
alexm merged 365 commits from 8448-devToTest into test 2025-01-21 10:44:46 +00:00
4 changed files with 114 additions and 42 deletions
Showing only changes of commit c193ce33f6 - Show all commits

View File

@ -2,7 +2,7 @@
import CreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue';
import VnSelectDialog from 'components/common/VnSelectDialog.vue';
import { useI18n } from 'vue-i18n';
import { computed } from 'vue';
import { ref, watch } from 'vue';
import { useAttrs } from 'vue';
import { useRequired } from 'src/composables/useRequired';
const { t } = useI18n();
@ -16,6 +16,14 @@ const props = defineProps({
},
});
watch(
() => props.location,
(newValue) => {
if (!modelValue.value) return;
modelValue.value = formatLocation(newValue) ?? null;
}
);
const mixinRules = [requiredFieldRule];
const locationProperties = [
'postcode',
@ -43,9 +51,7 @@ const formatLocation = (obj, properties = locationProperties) => {
return filteredParts.join(', ');
};
const modelValue = computed(() =>
props.location ? formatLocation(props.location, locationProperties) : null
);
const modelValue = ref(props.location ? formatLocation(props.location) : null);
function showLabel(data) {
const dataProperties = [

View File

@ -0,0 +1,72 @@
import { createWrapper } from 'app/test/vitest/helper.js';
import { describe, it, expect } from 'vitest';
import VnInputDate from 'components/common/VnInputDate.vue';
let vm;
let wrapper;
function generateWrapper(date, outlined, required) {
wrapper = createWrapper(VnInputDate, {
props: {
modelValue: date,
},
attrs: {
isOutlined: outlined,
required: required
},
});
wrapper = wrapper.wrapper;
vm = wrapper.vm;
};
describe('VnInputDate', () => {
describe('formattedDate', () => {
it('formats a valid date correctly', async () => {
generateWrapper('2023-12-25', false, false);
await vm.$nextTick();
expect(vm.formattedDate).toBe('25/12/2023');
});
it('updates the model value when a new date is set', async () => {
const input = wrapper.find('input');
await input.setValue('31/12/2023');
expect(wrapper.emitted()['update:modelValue']).toBeTruthy();
expect(wrapper.emitted()['update:modelValue'][0][0]).toBe('2023-12-31T00:00:00.000Z');
});
it('should not update the model value when an invalid date is set', async () => {
const input = wrapper.find('input');
await input.setValue('invalid-date');
expect(wrapper.emitted()['update:modelValue'][0][0]).toBe('2023-12-31T00:00:00.000Z');
});
});
describe('styleAttrs', () => {
it('should return empty styleAttrs when isOutlined is false', async () => {
generateWrapper('2023-12-25', false, false);
await vm.$nextTick();
expect(vm.styleAttrs).toEqual({});
});
it('should set styleAttrs when isOutlined is true', async () => {
generateWrapper('2023-12-25', true, false);
await vm.$nextTick();
expect(vm.styleAttrs.outlined).toBe(true);
});
});
describe('required', () => {
it('should not applies required class when isRequired is false', async () => {
generateWrapper('2023-12-25', false, false);
await vm.$nextTick();
expect(wrapper.find('.vn-input-date').classes()).not.toContain('required');
});
it('should applies required class when isRequired is true', async () => {
generateWrapper('2023-12-25', false, true);
await vm.$nextTick();
expect(wrapper.find('.vn-input-date').classes()).toContain('required');
});
});
});

View File

@ -1,5 +1,5 @@
<script setup>
import { ref, computed, onMounted } from 'vue';
import { ref, computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
@ -11,16 +11,9 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
import { useState } from 'src/composables/useState';
const state = useState();
const customer = ref();
onMounted(async () => {
customer.value = state.get('customer');
if (customer.value) customer.value.webAccess = data.value?.account?.isActive;
});
const customerDebt = ref();
const customerCredit = ref();
const $props = defineProps({
id: {
type: Number,
@ -42,10 +35,12 @@ const entityId = computed(() => {
const data = ref(useCardDescription());
const setData = (entity) => {
customerDebt.value = entity?.debt;
customerCredit.value = entity?.credit;
data.value = useCardDescription(entity?.name, entity?.id);
};
const debtWarning = computed(() => {
return customer.value?.debt > customer.value?.credit ? 'negative' : 'primary';
return customerDebt.value > customerCredit.value ? 'negative' : 'primary';
});
</script>
@ -97,26 +92,21 @@ const debtWarning = computed(() => {
:value="entity.businessType.description"
/>
</template>
<template #icons>
<QCardActions v-if="customer" class="q-gutter-x-md">
<template #icons="{ entity }">
<QCardActions class="q-gutter-x-md">
<QIcon
v-if="!customer.isActive"
v-if="!entity.isActive"
name="vn:disabled"
size="xs"
color="primary"
>
<QTooltip>{{ t('customer.card.isDisabled') }}</QTooltip>
</QIcon>
<QIcon
v-if="customer.isFreezed"
name="vn:frozen"
size="xs"
color="primary"
>
<QIcon v-if="entity.isFreezed" name="vn:frozen" size="xs" color="primary">
<QTooltip>{{ t('customer.card.isFrozen') }}</QTooltip>
</QIcon>
<QIcon
v-if="!customer.account?.active"
v-if="!entity.account?.active"
color="primary"
name="vn:noweb"
size="xs"
@ -124,7 +114,7 @@ const debtWarning = computed(() => {
<QTooltip>{{ t('customer.card.webAccountInactive') }}</QTooltip>
</QIcon>
<QIcon
v-if="customer.debt > customer.credit"
v-if="entity.debt > entity.credit"
name="vn:risk"
size="xs"
:color="debtWarning"
@ -132,7 +122,7 @@ const debtWarning = computed(() => {
<QTooltip>{{ t('customer.card.hasDebt') }}</QTooltip>
</QIcon>
<QIcon
v-if="!customer.isTaxDataChecked"
v-if="!entity.isTaxDataChecked"
name="vn:no036"
size="xs"
color="primary"
@ -140,7 +130,7 @@ const debtWarning = computed(() => {
<QTooltip>{{ t('customer.card.notChecked') }}</QTooltip>
</QIcon>
<QBtn
v-if="customer.unpaid"
v-if="entity.unpaid"
flat
size="sm"
icon="vn:Client_unpaid"

View File

@ -7,7 +7,14 @@ import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
const { notify } = useNotify();
const initInvoicing = {
invoicing: false,
nRequests: 0,
nPdfs: 0,
totalPdfs: 0,
addressIndex: 0,
errors: [],
};
export const useInvoiceOutGlobalStore = defineStore({
id: 'invoiceOutGlobal',
state: () => ({
@ -23,16 +30,11 @@ export const useInvoiceOutGlobalStore = defineStore({
addresses: [],
minInvoicingDate: null,
parallelism: null,
invoicing: false,
isInvoicing: false,
status: null,
addressIndex: 0,
errors: [],
printer: null,
nRequests: 0,
nPdfs: 0,
totalPdfs: 0,
formData: null,
...initInvoicing,
}),
actions: {
async init() {
@ -117,12 +119,13 @@ export const useInvoiceOutGlobalStore = defineStore({
);
throw new Error("There aren't addresses to invoice");
}
this.invoicing = false;
this.status = 'invoicing';
this.formData = formData;
this.addressIndex = 0;
this.errors = [];
await this.invoiceClient();
this.status = 'invoicing';
//reset data
for (const key in initInvoicing) {
this[key] = initInvoicing[key];
}
this.invoiceClient();
} catch (err) {
this.handleError(err);
}
@ -184,7 +187,6 @@ export const useInvoiceOutGlobalStore = defineStore({
async invoiceClient() {
if (this.invoicing || this.nRequests >= this.parallelism) return;
const address = this.addresses[this.addressIndex];
if (!address || !this.status || this.status == 'stopping') {
this.status = 'stopping';
this.invoicing = false;
@ -192,6 +194,7 @@ export const useInvoiceOutGlobalStore = defineStore({
}
try {
this.invoicing = true;
this.nRequests++;
const params = {
clientId: address.clientId,
addressId: address.id,
@ -215,6 +218,7 @@ export const useInvoiceOutGlobalStore = defineStore({
}
} finally {
this.invoicing = false;
this.nRequests--;
this.addressIndex++;
this.invoiceClient();
}