feat: filter customer by business type, address
This commit is contained in:
parent
56f0a86845
commit
5becbae369
4 changed files with 196 additions and 54 deletions
|
|
@ -198,3 +198,10 @@ i.q-icon.mdi.mdi-chevron-down-circle.q-expansion-item__toggle-icon.q-expansion-i
|
||||||
.q-focus-helper {
|
.q-focus-helper {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.clear-btn {
|
||||||
|
opacity: 0.6;
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch, onMounted, computed } from 'vue';
|
import { ref, watch, onMounted, nextTick, reactive } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { canAccess } from 'stores/utils';
|
import { canAccess } from 'stores/utils';
|
||||||
|
|
||||||
|
import type { District, Province, SubDistrict } from 'src/stores/address';
|
||||||
import useCustomerStore from 'stores/customer';
|
import useCustomerStore from 'stores/customer';
|
||||||
import useEmployeeStore from 'stores/employee';
|
import useEmployeeStore from 'stores/employee';
|
||||||
|
import useAddressStore from 'src/stores/address';
|
||||||
|
import useFlowStore from 'stores/flow';
|
||||||
import { dialog } from 'stores/utils';
|
import { dialog } from 'stores/utils';
|
||||||
import { useNavigator } from 'src/stores/navigator';
|
import { useNavigator } from 'src/stores/navigator';
|
||||||
import useFlowStore from 'stores/flow';
|
|
||||||
import { Status } from 'stores/types';
|
import { Status } from 'stores/types';
|
||||||
import {
|
import {
|
||||||
CustomerStats,
|
CustomerStats,
|
||||||
|
|
@ -17,28 +19,28 @@ import {
|
||||||
CustomerBranch,
|
CustomerBranch,
|
||||||
CustomerType,
|
CustomerType,
|
||||||
} from 'stores/customer/types';
|
} from 'stores/customer/types';
|
||||||
import { Employee, EmployeeHistory } from 'stores/employee/types';
|
|
||||||
import { SaveButton } from 'components/button';
|
|
||||||
|
|
||||||
|
import { SaveButton } from 'components/button';
|
||||||
import TabCustomer from './TabCustomer.vue';
|
import TabCustomer from './TabCustomer.vue';
|
||||||
import FloatingActionButton from 'components/FloatingActionButton.vue';
|
import FloatingActionButton from 'components/FloatingActionButton.vue';
|
||||||
import StatCardComponent from 'components/StatCardComponent.vue';
|
import StatCardComponent from 'components/StatCardComponent.vue';
|
||||||
import BranchPage from './BranchPage.vue';
|
import BranchPage from './BranchPage.vue';
|
||||||
|
import SelectBusinessType from 'src/components/shared/select/SelectBusinessType.vue';
|
||||||
|
import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue';
|
||||||
|
import TabEmployee from './TabEmployee.vue';
|
||||||
|
import SelectInput from 'src/components/shared/SelectInput.vue';
|
||||||
|
|
||||||
import { columnsCustomer, columnsEmployee } from './constant';
|
import { columnsCustomer, columnsEmployee } from './constant';
|
||||||
import { useCustomerForm, useEmployeeForm } from './form';
|
import { useCustomerForm, useEmployeeForm } from './form';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
import { nextTick } from 'vue';
|
|
||||||
import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue';
|
|
||||||
import TabEmployee from './TabEmployee.vue';
|
|
||||||
|
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const flowStore = useFlowStore();
|
const flowStore = useFlowStore();
|
||||||
const navigatorStore = useNavigator();
|
const navigatorStore = useNavigator();
|
||||||
|
const addressStore = useAddressStore();
|
||||||
const customerStore = useCustomerStore();
|
const customerStore = useCustomerStore();
|
||||||
const employeeStore = useEmployeeStore();
|
const employeeStore = useEmployeeStore();
|
||||||
const customerFormStore = useCustomerForm();
|
const customerFormStore = useCustomerForm();
|
||||||
|
|
@ -49,21 +51,21 @@ const { state: customerFormState, currentFormData: customerFormData } =
|
||||||
const { state: employeeFormState, statusEmployeeCreate } =
|
const { state: employeeFormState, statusEmployeeCreate } =
|
||||||
storeToRefs(employeeFormStore);
|
storeToRefs(employeeFormStore);
|
||||||
|
|
||||||
|
// NOTE: Component ref
|
||||||
const refTabCustomer = ref<InstanceType<typeof TabCustomer>>();
|
const refTabCustomer = ref<InstanceType<typeof TabCustomer>>();
|
||||||
const refTabEmployee = ref<InstanceType<typeof TabEmployee>>();
|
const refTabEmployee = ref<InstanceType<typeof TabEmployee>>();
|
||||||
|
|
||||||
// NOTE: Page Data
|
// NOTE: Page Data
|
||||||
const currentCustomer = ref<Customer>();
|
const currentCustomer = ref<Customer>();
|
||||||
const hideStats = ref(false);
|
|
||||||
const statsCustomerType = ref<CustomerStats>({
|
|
||||||
CORP: 0,
|
|
||||||
PERS: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
// NOTE: Page State
|
// NOTE: Page State
|
||||||
|
const hideStats = ref(false);
|
||||||
|
const gridView = ref(false);
|
||||||
|
const employeeStats = ref(0);
|
||||||
|
const inputSearch = ref('');
|
||||||
|
const filterBusinessType = ref('');
|
||||||
const searchDate = ref<string[]>([]);
|
const searchDate = ref<string[]>([]);
|
||||||
const currentTab = ref<'employer' | 'employee'>('employer');
|
const currentTab = ref<'employer' | 'employee'>('employer');
|
||||||
const inputSearch = ref('');
|
|
||||||
const currentStatus = ref<Status | 'All'>('All');
|
const currentStatus = ref<Status | 'All'>('All');
|
||||||
const customerTypeSelected = ref<{
|
const customerTypeSelected = ref<{
|
||||||
label: string;
|
label: string;
|
||||||
|
|
@ -72,14 +74,10 @@ const customerTypeSelected = ref<{
|
||||||
label: t('general.all'),
|
label: t('general.all'),
|
||||||
value: 'all',
|
value: 'all',
|
||||||
});
|
});
|
||||||
|
const statsCustomerType = ref<CustomerStats>({
|
||||||
const employeeStats = ref(0);
|
CORP: 0,
|
||||||
const gridView = ref(false);
|
PERS: 0,
|
||||||
|
});
|
||||||
// image
|
|
||||||
const imageList = ref<{ selectedImage: string; list: string[] }>();
|
|
||||||
const branch = ref<CustomerBranch[]>();
|
|
||||||
|
|
||||||
const fieldDisplayCustomer = ref<
|
const fieldDisplayCustomer = ref<
|
||||||
{
|
{
|
||||||
label: string;
|
label: string;
|
||||||
|
|
@ -106,17 +104,30 @@ const fieldSelected = ref<string[]>(
|
||||||
...columnsCustomer.map((v) => v.name),
|
...columnsCustomer.map((v) => v.name),
|
||||||
].filter((v, index, self) => self.indexOf(v) === index),
|
].filter((v, index, self) => self.indexOf(v) === index),
|
||||||
);
|
);
|
||||||
|
const filterAddress = reactive({
|
||||||
const customerStats = [
|
provinceId: '',
|
||||||
{ id: 1, count: 2, name: 'CORP' },
|
districtId: '',
|
||||||
{ id: 2, count: 3, name: 'PERS' },
|
subDistrictId: '',
|
||||||
];
|
});
|
||||||
|
const addressOpt = reactive<{
|
||||||
|
provinceOpt: Province[];
|
||||||
|
districtOpt: District[];
|
||||||
|
subDistrictOpt: SubDistrict[];
|
||||||
|
}>({
|
||||||
|
provinceOpt: [],
|
||||||
|
districtOpt: [],
|
||||||
|
subDistrictOpt: [],
|
||||||
|
});
|
||||||
const fieldCustomer = [
|
const fieldCustomer = [
|
||||||
'all',
|
'all',
|
||||||
'customerLegalEntity',
|
'customerLegalEntity',
|
||||||
'customerNaturalPerson',
|
'customerNaturalPerson',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
// image
|
||||||
|
const imageList = ref<{ selectedImage: string; list: string[] }>();
|
||||||
|
const branch = ref<CustomerBranch[]>();
|
||||||
|
|
||||||
async function triggerChangeStatus(
|
async function triggerChangeStatus(
|
||||||
id: string,
|
id: string,
|
||||||
status: string,
|
status: string,
|
||||||
|
|
@ -190,16 +201,75 @@ async function fetchImageList(
|
||||||
async function triggerExport() {
|
async function triggerExport() {
|
||||||
switch (currentTab.value) {
|
switch (currentTab.value) {
|
||||||
case 'employer':
|
case 'employer':
|
||||||
customerStore.customerExport({ pageSize: 10000 });
|
customerStore.customerExport({
|
||||||
|
pageSize: 10000,
|
||||||
|
startDate: searchDate.value[0],
|
||||||
|
endDate: searchDate.value[1],
|
||||||
|
businessType: filterBusinessType.value,
|
||||||
|
province: filterAddress.provinceId || undefined,
|
||||||
|
district: filterAddress.districtId || undefined,
|
||||||
|
subDistrict: filterAddress.subDistrictId || undefined,
|
||||||
|
customerType:
|
||||||
|
customerTypeSelected.value.value === 'customerLegalEntity'
|
||||||
|
? CustomerType.Corporate
|
||||||
|
: customerTypeSelected.value.value === 'customerNaturalPerson'
|
||||||
|
? CustomerType.Person
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'employee':
|
case 'employee':
|
||||||
employeeStore.employeeExport({ pageSize: 10000 });
|
employeeStore.employeeExport({
|
||||||
|
pageSize: 10000,
|
||||||
|
startDate: searchDate.value[0],
|
||||||
|
endDate: searchDate.value[1],
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchAddressData(type: 'province' | 'district' | 'subDistrict') {
|
||||||
|
let result;
|
||||||
|
|
||||||
|
if (type === 'province') {
|
||||||
|
result = await addressStore.fetchProvince();
|
||||||
|
if (result) addressOpt.provinceOpt = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'district') {
|
||||||
|
if (!filterAddress.provinceId) return;
|
||||||
|
result = await addressStore.fetchDistrictByProvinceId(
|
||||||
|
filterAddress.provinceId,
|
||||||
|
);
|
||||||
|
if (result) addressOpt.districtOpt = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'subDistrict') {
|
||||||
|
if (!filterAddress.districtId) return;
|
||||||
|
result = await addressStore.fetchSubDistrictByProvinceId(
|
||||||
|
filterAddress.districtId,
|
||||||
|
);
|
||||||
|
if (result) addressOpt.subDistrictOpt = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSelectAddress(type: 'province' | 'district') {
|
||||||
|
if (type === 'province') {
|
||||||
|
filterAddress.districtId = filterAddress.subDistrictId = '';
|
||||||
|
addressOpt.districtOpt = addressOpt.subDistrictOpt = [];
|
||||||
|
|
||||||
|
await fetchAddressData('district');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'district') {
|
||||||
|
filterAddress.subDistrictId = '';
|
||||||
|
await fetchAddressData('subDistrict');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
navigatorStore.current.title = 'menu.customer';
|
navigatorStore.current.title = 'menu.customer';
|
||||||
navigatorStore.current.path = [
|
navigatorStore.current.path = [
|
||||||
|
|
@ -245,6 +315,8 @@ async function init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await fetchAddressData('province');
|
||||||
|
|
||||||
flowStore.rotate();
|
flowStore.rotate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -344,26 +416,24 @@ onMounted(async () => await init());
|
||||||
<div v-if="!hideStats" class="col-12 q-mb-md">
|
<div v-if="!hideStats" class="col-12 q-mb-md">
|
||||||
<div class="scroll">
|
<div class="scroll">
|
||||||
<StatCardComponent
|
<StatCardComponent
|
||||||
v-if="customerStats"
|
v-if="statsCustomerType"
|
||||||
label-i18n
|
label-i18n
|
||||||
:branch="
|
:branch="
|
||||||
customerStats &&
|
currentTab === 'employer'
|
||||||
(currentTab === 'employer'
|
? [
|
||||||
? customerStats.map((v) => ({
|
{
|
||||||
count:
|
count: statsCustomerType.CORP ?? 0,
|
||||||
v.name === 'CORP'
|
label: 'customer.employerLegalEntity',
|
||||||
? (statsCustomerType?.CORP ?? 0)
|
icon: 'mdi-office-building-outline',
|
||||||
: (statsCustomerType?.PERS ?? 0),
|
color: 'purple',
|
||||||
label:
|
},
|
||||||
v.name === 'CORP'
|
{
|
||||||
? 'customer.employerLegalEntity'
|
count: statsCustomerType.PERS ?? 0,
|
||||||
: 'customer.employerNaturalPerson',
|
label: 'customer.employerNaturalPerson',
|
||||||
icon:
|
icon: 'mdi-account-outline',
|
||||||
v.name === 'CORP'
|
color: 'green',
|
||||||
? 'mdi-office-building-outline'
|
},
|
||||||
: 'mdi-account-outline',
|
]
|
||||||
color: v.name === 'CORP' ? 'purple' : 'green',
|
|
||||||
}))
|
|
||||||
: [
|
: [
|
||||||
{
|
{
|
||||||
label: 'customer.employee',
|
label: 'customer.employee',
|
||||||
|
|
@ -371,7 +441,7 @@ onMounted(async () => await init());
|
||||||
icon: 'mdi-account-outline',
|
icon: 'mdi-account-outline',
|
||||||
color: 'pink',
|
color: 'pink',
|
||||||
},
|
},
|
||||||
])
|
]
|
||||||
"
|
"
|
||||||
:dark="$q.dark.isActive"
|
:dark="$q.dark.isActive"
|
||||||
/>
|
/>
|
||||||
|
|
@ -406,7 +476,11 @@ onMounted(async () => await init());
|
||||||
<q-separator vertical inset class="q-mr-xs" />
|
<q-separator vertical inset class="q-mr-xs" />
|
||||||
<AdvanceSearch
|
<AdvanceSearch
|
||||||
v-model="searchDate"
|
v-model="searchDate"
|
||||||
:active="$q.screen.lt.md && currentStatus !== 'All'"
|
:active="
|
||||||
|
($q.screen.lt.md && currentStatus !== 'All') ||
|
||||||
|
!!filterBusinessType ||
|
||||||
|
!!filterAddress.provinceId
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="$q.screen.lt.md"
|
v-if="$q.screen.lt.md"
|
||||||
|
|
@ -432,6 +506,46 @@ onMounted(async () => await init());
|
||||||
{ label: $t('status.INACTIVE'), value: 'INACTIVE' },
|
{ label: $t('status.INACTIVE'), value: 'INACTIVE' },
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
|
<template v-if="currentTab === 'employer'">
|
||||||
|
<div class="q-mt-sm text-weight-medium">
|
||||||
|
{{ $t('customer.form.businessType') }}
|
||||||
|
</div>
|
||||||
|
<SelectBusinessType
|
||||||
|
v-model:value="filterBusinessType"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
<div class="q-mt-sm text-weight-medium">
|
||||||
|
{{ $t('customer.form.address') }}
|
||||||
|
</div>
|
||||||
|
<SelectInput
|
||||||
|
clearable
|
||||||
|
v-model="filterAddress.provinceId"
|
||||||
|
option-value="id"
|
||||||
|
:label="$t('form.province')"
|
||||||
|
:option="addressOpt.provinceOpt"
|
||||||
|
:option-label="locale === 'eng' ? 'nameEN' : 'name'"
|
||||||
|
@update:model-value="handleSelectAddress('province')"
|
||||||
|
/>
|
||||||
|
<SelectInput
|
||||||
|
clearable
|
||||||
|
class="q-mt-sm"
|
||||||
|
option-value="id"
|
||||||
|
v-model="filterAddress.districtId"
|
||||||
|
:option="addressOpt.districtOpt"
|
||||||
|
:label="$t('form.district')"
|
||||||
|
:option-label="locale === 'eng' ? 'nameEN' : 'name'"
|
||||||
|
@update:model-value="handleSelectAddress('district')"
|
||||||
|
/>
|
||||||
|
<SelectInput
|
||||||
|
clearable
|
||||||
|
class="q-mt-sm"
|
||||||
|
option-value="id"
|
||||||
|
v-model="filterAddress.subDistrictId"
|
||||||
|
:option="addressOpt.subDistrictOpt"
|
||||||
|
:label="$t('form.subDistrict')"
|
||||||
|
:option-label="locale === 'eng' ? 'nameEN' : 'name'"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</AdvanceSearch>
|
</AdvanceSearch>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
@ -632,8 +746,11 @@ onMounted(async () => await init());
|
||||||
<TabCustomer
|
<TabCustomer
|
||||||
v-if="currentTab === 'employer'"
|
v-if="currentTab === 'employer'"
|
||||||
ref="refTabCustomer"
|
ref="refTabCustomer"
|
||||||
|
v-model:customer-type-selected="customerTypeSelected"
|
||||||
v-model:stats-customer-type="statsCustomerType"
|
v-model:stats-customer-type="statsCustomerType"
|
||||||
v-model:img-list="imageList"
|
v-model:img-list="imageList"
|
||||||
|
:filter-address="filterAddress"
|
||||||
|
:filter-business-type="filterBusinessType"
|
||||||
:gridView
|
:gridView
|
||||||
:searchDate
|
:searchDate
|
||||||
:currentTab
|
:currentTab
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,12 @@ const props = defineProps<{
|
||||||
inputSearch: string;
|
inputSearch: string;
|
||||||
searchDate: string[];
|
searchDate: string[];
|
||||||
fieldSelected: string[];
|
fieldSelected: string[];
|
||||||
|
filterBusinessType: string;
|
||||||
|
filterAddress: {
|
||||||
|
provinceId: string;
|
||||||
|
districtId: string;
|
||||||
|
subDistrictId: string;
|
||||||
|
};
|
||||||
fetchImageList: (
|
fetchImageList: (
|
||||||
id: string,
|
id: string,
|
||||||
selectedName: string,
|
selectedName: string,
|
||||||
|
|
@ -143,13 +149,10 @@ const fieldCustomer = [
|
||||||
'customerLegalEntity',
|
'customerLegalEntity',
|
||||||
'customerNaturalPerson',
|
'customerNaturalPerson',
|
||||||
] as const;
|
] as const;
|
||||||
const customerTypeSelected = ref<{
|
const customerTypeSelected = defineModel<{
|
||||||
label: string;
|
label: string;
|
||||||
value: 'all' | 'customerLegalEntity' | 'customerNaturalPerson';
|
value: 'all' | 'customerLegalEntity' | 'customerNaturalPerson';
|
||||||
}>({
|
}>('customerTypeSelected');
|
||||||
label: t('general.all'),
|
|
||||||
value: 'all',
|
|
||||||
});
|
|
||||||
const splitPercent = computed(() => ($q.screen.lt.md ? 0 : 15));
|
const splitPercent = computed(() => ($q.screen.lt.md ? 0 : 15));
|
||||||
|
|
||||||
const customerNameInfo = computed(() => {
|
const customerNameInfo = computed(() => {
|
||||||
|
|
@ -186,6 +189,10 @@ async function fetchListCustomer(fetchStats = false, mobileFetch?: boolean) {
|
||||||
? 'ACTIVE'
|
? 'ACTIVE'
|
||||||
: 'INACTIVE',
|
: 'INACTIVE',
|
||||||
query: props.inputSearch,
|
query: props.inputSearch,
|
||||||
|
businessType: props.filterBusinessType,
|
||||||
|
province: props.filterAddress.provinceId || undefined,
|
||||||
|
district: props.filterAddress.districtId || undefined,
|
||||||
|
subDistrict: props.filterAddress.subDistrictId || undefined,
|
||||||
startDate: props.searchDate[0],
|
startDate: props.searchDate[0],
|
||||||
endDate: props.searchDate[1],
|
endDate: props.searchDate[1],
|
||||||
customerType: (
|
customerType: (
|
||||||
|
|
@ -288,6 +295,8 @@ watch(
|
||||||
props.inputSearch,
|
props.inputSearch,
|
||||||
props.searchDate,
|
props.searchDate,
|
||||||
props.currentStatus,
|
props.currentStatus,
|
||||||
|
props.filterBusinessType,
|
||||||
|
props.filterAddress,
|
||||||
customerTypeSelected.value,
|
customerTypeSelected.value,
|
||||||
pageSize.value,
|
pageSize.value,
|
||||||
],
|
],
|
||||||
|
|
@ -302,6 +311,7 @@ watch(
|
||||||
customerFormState.value.currentCustomerId = undefined;
|
customerFormState.value.currentCustomerId = undefined;
|
||||||
flowStore.rotate();
|
flowStore.rotate();
|
||||||
},
|
},
|
||||||
|
{ deep: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,10 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
customerType?: CustomerType;
|
customerType?: CustomerType;
|
||||||
startDate?: string;
|
startDate?: string;
|
||||||
endDate?: string;
|
endDate?: string;
|
||||||
|
businessType?: string;
|
||||||
|
province?: string;
|
||||||
|
district?: string;
|
||||||
|
subDistrict?: string;
|
||||||
},
|
},
|
||||||
Data extends Pagination<
|
Data extends Pagination<
|
||||||
(Customer &
|
(Customer &
|
||||||
|
|
@ -484,6 +488,10 @@ const useCustomerStore = defineStore('api-customer', () => {
|
||||||
activeBranchOnly?: boolean;
|
activeBranchOnly?: boolean;
|
||||||
startDate?: string | Date;
|
startDate?: string | Date;
|
||||||
endDate?: string | Date;
|
endDate?: string | Date;
|
||||||
|
businessType?: string;
|
||||||
|
province?: string;
|
||||||
|
district?: string;
|
||||||
|
subDistrict?: string;
|
||||||
}) {
|
}) {
|
||||||
let url = baseUrl + '/' + 'customer-export';
|
let url = baseUrl + '/' + 'customer-export';
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue