Merge branch 'develop'
This commit is contained in:
commit
55c15585f8
22 changed files with 403 additions and 115 deletions
|
|
@ -57,7 +57,9 @@ api.interceptors.response.use(
|
||||||
persistent: true,
|
persistent: true,
|
||||||
enablei18n: true,
|
enablei18n: true,
|
||||||
message: `dialog.backend.${parseError(err.response.status, err.response.data)}`,
|
message: `dialog.backend.${parseError(err.response.status, err.response.data)}`,
|
||||||
action: () => {},
|
action: () => {
|
||||||
|
if (err.response.status === 401) window.location.reload();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ const firstName = defineModel<string>('firstName');
|
||||||
const namePrefix = defineModel<string>('namePrefix');
|
const namePrefix = defineModel<string>('namePrefix');
|
||||||
const passportNumber = defineModel<string>('passportNumber');
|
const passportNumber = defineModel<string>('passportNumber');
|
||||||
|
|
||||||
|
const passportValidator = /[a-zA-Z]{1}[a-zA-Z0-9]{1}[0-9]{5,7}$/;
|
||||||
|
|
||||||
const genderOptions = ref<Record<string, unknown>[]>([]);
|
const genderOptions = ref<Record<string, unknown>[]>([]);
|
||||||
let genderFilter: (
|
let genderFilter: (
|
||||||
value: string,
|
value: string,
|
||||||
|
|
@ -275,7 +277,6 @@ watch(
|
||||||
</q-item>
|
</q-item>
|
||||||
</template>
|
</template>
|
||||||
</q-select>
|
</q-select>
|
||||||
|
|
||||||
<q-input
|
<q-input
|
||||||
:for="`${prefixId}-input-previous-passport-Number`"
|
:for="`${prefixId}-input-previous-passport-Number`"
|
||||||
:dense="dense"
|
:dense="dense"
|
||||||
|
|
@ -287,8 +288,9 @@ watch(
|
||||||
v-model="previousPassportRef"
|
v-model="previousPassportRef"
|
||||||
:rules="[
|
:rules="[
|
||||||
(v) =>
|
(v) =>
|
||||||
(!!v && v.length === 6) ||
|
!v ||
|
||||||
$t('form.error.requireLength', { msg: 6 }),
|
passportValidator.test(v) ||
|
||||||
|
$t('form.error.passportFormat'),
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -484,7 +486,9 @@ watch(
|
||||||
:label="$t('customerEmployee.form.passportNo')"
|
:label="$t('customerEmployee.form.passportNo')"
|
||||||
v-model="passportNumber"
|
v-model="passportNumber"
|
||||||
:rules="[
|
:rules="[
|
||||||
(val) => (val && val.length > 0) || $t('form.error.required'),
|
(val) => !!val || $t('form.error.required'),
|
||||||
|
(val) =>
|
||||||
|
passportValidator.test(val) || $t('form.error.passportFormat'),
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
127
src/components/shared/select/SelectAgent.vue
Normal file
127
src/components/shared/select/SelectAgent.vue
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { getRole } from 'src/services/keycloak';
|
||||||
|
|
||||||
|
import { createSelect, SelectProps } from './select';
|
||||||
|
import SelectInput from '../SelectInput.vue';
|
||||||
|
|
||||||
|
import { User } from 'src/stores/user/types';
|
||||||
|
|
||||||
|
import useStore from 'src/stores/user';
|
||||||
|
|
||||||
|
type SelectOption = User;
|
||||||
|
|
||||||
|
const value = defineModel<string | null | undefined>('value', {
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
const valueOption = defineModel<SelectOption>('valueOption', {
|
||||||
|
required: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const selectOptions = ref<SelectOption[]>([]);
|
||||||
|
|
||||||
|
const { fetchList: getList, fetchById: getById } = useStore();
|
||||||
|
|
||||||
|
defineEmits<{
|
||||||
|
(e: 'create'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
type ExclusiveProps = {
|
||||||
|
codeOnly?: boolean;
|
||||||
|
selectFirstValue?: boolean;
|
||||||
|
branchVirtual?: boolean;
|
||||||
|
checkRole?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = defineProps<SelectProps<typeof getList> & ExclusiveProps>();
|
||||||
|
|
||||||
|
const { getOptions, setFirstValue, getSelectedOption, filter } =
|
||||||
|
createSelect<SelectOption>(
|
||||||
|
{
|
||||||
|
value,
|
||||||
|
valueOption,
|
||||||
|
selectOptions,
|
||||||
|
getList: async (query) => {
|
||||||
|
const ret = await getList({
|
||||||
|
query,
|
||||||
|
...props.params,
|
||||||
|
includeBranch: true,
|
||||||
|
pageSize: 99999,
|
||||||
|
userType: 'DELEGATE',
|
||||||
|
status: 'ACTIVE',
|
||||||
|
});
|
||||||
|
if (ret) return ret.result;
|
||||||
|
},
|
||||||
|
getByValue: async (id) => {
|
||||||
|
const ret = await getById(id);
|
||||||
|
if (ret) return ret;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ valueField: 'id' },
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getOptions();
|
||||||
|
|
||||||
|
if (props.autoSelectOnSingle && selectOptions.value.length === 1) {
|
||||||
|
setFirstValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.selectFirstValue) {
|
||||||
|
setDefaultValue();
|
||||||
|
} else await getSelectedOption();
|
||||||
|
});
|
||||||
|
|
||||||
|
function setDefaultValue() {
|
||||||
|
setFirstValue();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<SelectInput
|
||||||
|
v-model="value"
|
||||||
|
incremental
|
||||||
|
option-value="id"
|
||||||
|
:label
|
||||||
|
:placeholder
|
||||||
|
:readonly
|
||||||
|
:disable="disabled"
|
||||||
|
:option="selectOptions"
|
||||||
|
:hide-selected="false"
|
||||||
|
:fill-input="false"
|
||||||
|
:rules="[
|
||||||
|
(v: string) => !props.required || !!v || $t('form.error.required'),
|
||||||
|
]"
|
||||||
|
@filter="filter"
|
||||||
|
>
|
||||||
|
<template #selected-item="{ opt }">
|
||||||
|
{{
|
||||||
|
$i18n.locale === 'tha'
|
||||||
|
? opt.firstName + ' ' + opt.lastName
|
||||||
|
: opt.firstNameEN + ' ' + opt.lastNameEN
|
||||||
|
}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #option="{ opt, scope }">
|
||||||
|
<q-item v-bind="scope.itemProps">
|
||||||
|
<span class="row items-center">
|
||||||
|
{{
|
||||||
|
$i18n.locale === 'tha'
|
||||||
|
? opt.firstName + ' ' + opt.lastName
|
||||||
|
: opt.firstNameEN + ' ' + opt.lastNameEN
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-separator class="q-mx-sm" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #append v-if="clearable">
|
||||||
|
<q-icon
|
||||||
|
v-if="!readonly && value"
|
||||||
|
name="mdi-close-circle"
|
||||||
|
@click.stop="value = ''"
|
||||||
|
class="cursor-pointer clear-btn"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</SelectInput>
|
||||||
|
</template>
|
||||||
|
|
@ -139,6 +139,7 @@ export default {
|
||||||
import: 'Import',
|
import: 'Import',
|
||||||
numberOfDay: 'Number of days',
|
numberOfDay: 'Number of days',
|
||||||
other: 'Other',
|
other: 'Other',
|
||||||
|
agencyAddress: 'Agency Address',
|
||||||
},
|
},
|
||||||
|
|
||||||
menu: {
|
menu: {
|
||||||
|
|
@ -299,6 +300,7 @@ export default {
|
||||||
branchNameField: "Only letters, numbers, or the characters . , - ' &.",
|
branchNameField: "Only letters, numbers, or the characters . , - ' &.",
|
||||||
branchNameENField:
|
branchNameENField:
|
||||||
"Only English letters, numbers, or the characters . , - ' &.",
|
"Only English letters, numbers, or the characters . , - ' &.",
|
||||||
|
passportFormat: 'Please enter the passport number in the correct format.',
|
||||||
},
|
},
|
||||||
warning: {
|
warning: {
|
||||||
title: 'Warning {msg}',
|
title: 'Warning {msg}',
|
||||||
|
|
@ -958,6 +960,10 @@ export default {
|
||||||
Validate: 'Validate',
|
Validate: 'Validate',
|
||||||
Complete: 'Complete',
|
Complete: 'Complete',
|
||||||
Canceled: 'Canceled',
|
Canceled: 'Canceled',
|
||||||
|
Restart: 'go proceed again',
|
||||||
|
receive: {
|
||||||
|
Canceled: 'Canceled',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
receiveTask: 'Receive Task',
|
receiveTask: 'Receive Task',
|
||||||
|
|
@ -977,7 +983,7 @@ export default {
|
||||||
noRequestAvailable: 'There is no request list available for processing',
|
noRequestAvailable: 'There is no request list available for processing',
|
||||||
validate: 'Validate',
|
validate: 'Validate',
|
||||||
done: 'Done',
|
done: 'Done',
|
||||||
confirmValidate: 'Confirm Validate',
|
confirmEndWork: 'Confirm end of work',
|
||||||
},
|
},
|
||||||
|
|
||||||
dialog: {
|
dialog: {
|
||||||
|
|
@ -1012,6 +1018,10 @@ export default {
|
||||||
confirmValidate: 'Do you confirm the validation?',
|
confirmValidate: 'Do you confirm the validation?',
|
||||||
warningSelectDeliveryStaff:
|
warningSelectDeliveryStaff:
|
||||||
'You have not yet selected a document delivery staff.',
|
'You have not yet selected a document delivery staff.',
|
||||||
|
|
||||||
|
confirmEndWorkWarning:
|
||||||
|
"Do you want to end the work now? The current statuses 'Pending', 'In Progress', 'To Be Reprocessed' will be changed to 'Redo All'.",
|
||||||
|
confirmEndWork: 'Do you want to end the work?',
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
ok: 'OK',
|
ok: 'OK',
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,7 @@ export default {
|
||||||
next: 'ถัดไป',
|
next: 'ถัดไป',
|
||||||
numberOfDay: 'จำนวนวัน',
|
numberOfDay: 'จำนวนวัน',
|
||||||
other: 'อื่นๆ',
|
other: 'อื่นๆ',
|
||||||
|
agencyAddress: 'ที่อยู่หน่วยงาน ',
|
||||||
},
|
},
|
||||||
|
|
||||||
menu: {
|
menu: {
|
||||||
|
|
@ -298,6 +299,7 @@ export default {
|
||||||
branchNameField: "โปรดใช้ตัวอักษร ตัวเลข หรือ . , - ' & เท่านั้น",
|
branchNameField: "โปรดใช้ตัวอักษร ตัวเลข หรือ . , - ' & เท่านั้น",
|
||||||
branchNameENField:
|
branchNameENField:
|
||||||
"โปรดใช้ตัวอักษรภาษาอังกฤษ ตัวเลข หรือ . , - ' & เท่านั้น",
|
"โปรดใช้ตัวอักษรภาษาอังกฤษ ตัวเลข หรือ . , - ' & เท่านั้น",
|
||||||
|
passportFormat: 'กรุณากรอกหมายเลขพาสปอร์ตให้ถูกต้องตามรูปแบบ',
|
||||||
},
|
},
|
||||||
warning: {
|
warning: {
|
||||||
title: 'แจ้งเตือน {msg}',
|
title: 'แจ้งเตือน {msg}',
|
||||||
|
|
@ -941,12 +943,15 @@ export default {
|
||||||
InProgress: 'กำลังดำเนินการ ',
|
InProgress: 'กำลังดำเนินการ ',
|
||||||
Success: 'ดำเนินการสำเร็จ',
|
Success: 'ดำเนินการสำเร็จ',
|
||||||
Failed: 'ดำเนินการไม่สำเร็จ',
|
Failed: 'ดำเนินการไม่สำเร็จ',
|
||||||
Redo: 'ทำใหม่',
|
Redo: 'ยกเลิกรอดำเนินการใหม่',
|
||||||
Validate: 'ตรวจสอบความถูกต้อง',
|
Validate: 'ตรวจสอบความถูกต้อง',
|
||||||
Complete: 'ดำเนินการเสร็จสิ้น',
|
Complete: 'ดำเนินการเสร็จสิ้น',
|
||||||
Canceled: ' รายการคำขอถูกยกเลิก',
|
Canceled: 'รายการคำขอถูกยกเลิก',
|
||||||
|
Restart: 'ไปดำเนินการใหม่',
|
||||||
|
receive: {
|
||||||
|
Canceled: 'ยกเลิก',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
receiveTask: 'รับงาน',
|
receiveTask: 'รับงาน',
|
||||||
receiveScan: 'รับงานแบบสแกน',
|
receiveScan: 'รับงานแบบสแกน',
|
||||||
receiveCustom: 'รับงานแบบเลือกเอง',
|
receiveCustom: 'รับงานแบบเลือกเอง',
|
||||||
|
|
@ -964,7 +969,7 @@ export default {
|
||||||
noRequestAvailable: 'ไม่มีใบรายการคำขอที่สามารถดำเนินการได้',
|
noRequestAvailable: 'ไม่มีใบรายการคำขอที่สามารถดำเนินการได้',
|
||||||
validate: 'ตรวจสอบสินค้า',
|
validate: 'ตรวจสอบสินค้า',
|
||||||
done: 'ดำเนินการแล้ว',
|
done: 'ดำเนินการแล้ว',
|
||||||
confirmValidate: 'ยืนยันการตรวจสอบ',
|
confirmEndWork: 'ยืนยันการจบงาน',
|
||||||
},
|
},
|
||||||
|
|
||||||
dialog: {
|
dialog: {
|
||||||
|
|
@ -996,7 +1001,8 @@ export default {
|
||||||
confirmSavingStatus:
|
confirmSavingStatus:
|
||||||
'คุณต้องการยืนยันการบันทึกข้อมูลการเปลี่ยนสถานะใช่หรือไม่',
|
'คุณต้องการยืนยันการบันทึกข้อมูลการเปลี่ยนสถานะใช่หรือไม่',
|
||||||
confirmSending: 'ยืนยันการส่งงานใช่หรือไม่',
|
confirmSending: 'ยืนยันการส่งงานใช่หรือไม่',
|
||||||
confirmValidate: 'ยืนยันการตรวจสอบใช่หรือไม่',
|
confirmEndWorkWarning: `ท่านต้องการให้ดำเนินการจบงานในขณะนี้หรือไม่? สถานะปัจจุบันที่แสดงว่า 'รอดำเนินการ' 'กำลังดำเนินการ' 'ไปดำเนินการใหม่' จะถูกเปลี่ยนเป็น 'ทำใหม่ทั้งหมด'`,
|
||||||
|
confirmEndWork: 'ท่านต้องการจบงานใช่หรือไม่',
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
ok: 'ยืนยัน',
|
ok: 'ยืนยัน',
|
||||||
|
|
|
||||||
|
|
@ -4630,7 +4630,7 @@ const emptyCreateDialog = ref(false);
|
||||||
"
|
"
|
||||||
class="q-mb-xl"
|
class="q-mb-xl"
|
||||||
/>
|
/>
|
||||||
<FormPerso
|
<FormPerson
|
||||||
id="drawer-form-personal"
|
id="drawer-form-personal"
|
||||||
prefix-id="drawer-info-employee"
|
prefix-id="drawer-info-employee"
|
||||||
dense
|
dense
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import useUserStore from 'stores/user';
|
import SelectAgent from 'src/components/shared/select/SelectAgent.vue';
|
||||||
import { ref } from 'vue';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
|
|
||||||
import SelectInput from 'src/components/shared/SelectInput.vue';
|
|
||||||
import { QSelect } from 'quasar';
|
|
||||||
|
|
||||||
const userStore = useUserStore();
|
|
||||||
const { locale } = useI18n({ useScope: 'global' });
|
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
|
|
@ -20,41 +12,6 @@ const officeTel = defineModel<string>('officeTel');
|
||||||
const agent = defineModel<string>('agent');
|
const agent = defineModel<string>('agent');
|
||||||
|
|
||||||
const agentUserId = defineModel<string>('agentUserId');
|
const agentUserId = defineModel<string>('agentUserId');
|
||||||
|
|
||||||
const agentOptions = ref<{ id: string; label: string; labelEN: string }[]>([]);
|
|
||||||
|
|
||||||
async function fetchAgentOptions(query: string) {
|
|
||||||
const res = await userStore.fetchList({
|
|
||||||
includeBranch: true,
|
|
||||||
query: query,
|
|
||||||
pageSize: 99999,
|
|
||||||
userType: 'DELEGATE',
|
|
||||||
status: 'ACTIVE',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
agentOptions.value = res.result.map((v) => ({
|
|
||||||
id: v.id,
|
|
||||||
label: v.firstName + ' ' + v.lastName,
|
|
||||||
labelEN: v.firstNameEN + ' ' + v.lastNameEN,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function filter(val: string, update: (...args: unknown[]) => void) {
|
|
||||||
update(
|
|
||||||
async () => {
|
|
||||||
await fetchAgentOptions(val);
|
|
||||||
},
|
|
||||||
|
|
||||||
(ref: QSelect) => {
|
|
||||||
if (val !== '' && ref.options && ref.options?.length > 0) {
|
|
||||||
ref.setOptionIndex(-1);
|
|
||||||
ref.moveOptionSelection(1, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -153,18 +110,12 @@ async function filter(val: string, update: (...args: unknown[]) => void) {
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
||||||
<SelectInput
|
<SelectAgent
|
||||||
@click="fetchAgentOptions"
|
:label="$t('customer.form.agent')"
|
||||||
|
v-model:value="agentUserId"
|
||||||
:readonly
|
:readonly
|
||||||
incremental
|
|
||||||
v-model="agentUserId"
|
|
||||||
id="quotation-branch"
|
id="quotation-branch"
|
||||||
class="col-md-6 col-12"
|
class="col-md-6 col-12"
|
||||||
:option="agentOptions"
|
|
||||||
:label="$t('customer.form.agent')"
|
|
||||||
option-value="id"
|
|
||||||
:option-label="locale === 'eng' ? 'labelEN' : 'label'"
|
|
||||||
@filter="(val: string, update) => filter(val, update)"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -59,10 +59,12 @@ const { state: customerFormState, currentFormData: customerFormData } =
|
||||||
const { currentMyBranch } = storeToRefs(userBranch);
|
const { currentMyBranch } = storeToRefs(userBranch);
|
||||||
|
|
||||||
const fieldSelectedOption = computed(() => {
|
const fieldSelectedOption = computed(() => {
|
||||||
return columnQuotation.map((v) => ({
|
return columnQuotation
|
||||||
label: v.label,
|
.filter((v) => v.name !== 'action')
|
||||||
value: v.name,
|
.map((v) => ({
|
||||||
}));
|
label: v.label,
|
||||||
|
value: v.name,
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
const special = ref(false);
|
const special = ref(false);
|
||||||
const branchId = ref('');
|
const branchId = ref('');
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { getInstance } from 'src/services/keycloak';
|
||||||
import { useNavigator } from 'src/stores/navigator';
|
import { useNavigator } from 'src/stores/navigator';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
|
import { initLang } from 'src/utils/ui';
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const { locale } = useI18n();
|
const { locale } = useI18n();
|
||||||
|
|
@ -25,6 +26,8 @@ function sendMessage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
initLang();
|
||||||
|
currentLocale.value = locale.value;
|
||||||
navigatorStore.current.title = 'menu.dms';
|
navigatorStore.current.title = 'menu.dms';
|
||||||
navigatorStore.current.path = [
|
navigatorStore.current.path = [
|
||||||
{
|
{
|
||||||
|
|
@ -47,12 +50,14 @@ watch(
|
||||||
watch([locale, $q.dark], () => {
|
watch([locale, $q.dark], () => {
|
||||||
sendMessage();
|
sendMessage();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const currentLocale = ref(locale.value);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<iframe
|
<iframe
|
||||||
ref="iframe"
|
ref="iframe"
|
||||||
:src="`${EDM_SERVICE}/?at=${at}&rt=${rt}&lang=${locale}`"
|
:src="`${EDM_SERVICE}/?at=${at}&rt=${rt}&lang=${currentLocale}`"
|
||||||
frameborder="0"
|
frameborder="0"
|
||||||
class="full-width full-height rounded"
|
class="full-width full-height rounded"
|
||||||
allowtransparency="true"
|
allowtransparency="true"
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ async function fetchStats() {
|
||||||
function triggerCancel(id: string) {
|
function triggerCancel(id: string) {
|
||||||
dialogWarningClose(t, {
|
dialogWarningClose(t, {
|
||||||
message: t('form.warning.cancel'),
|
message: t('form.warning.cancel'),
|
||||||
|
actionText: t('dialog.action.ok'),
|
||||||
action: async () => {
|
action: async () => {
|
||||||
const res = await requestListStore.cancelRequest(id);
|
const res = await requestListStore.cancelRequest(id);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
|
@ -222,6 +223,10 @@ watch([() => pageState.inputSearch, () => pageState.statusFilter], () =>
|
||||||
label: $t('requestList.status.Completed'),
|
label: $t('requestList.status.Completed'),
|
||||||
value: RequestDataStatus.Completed,
|
value: RequestDataStatus.Completed,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: $t('requestList.status.Canceled'),
|
||||||
|
value: RequestDataStatus.Canceled,
|
||||||
|
},
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
<q-select
|
<q-select
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,14 @@ import {
|
||||||
PropString,
|
PropString,
|
||||||
} from 'src/stores/product-service/types';
|
} from 'src/stores/product-service/types';
|
||||||
|
|
||||||
import { Attributes } from 'src/stores/request-list/types';
|
import { Attributes, RequestData } from 'src/stores/request-list/types';
|
||||||
|
|
||||||
|
import { getCustomerName, getEmployeeName } from 'src/stores/utils';
|
||||||
import useOptionStore from 'src/stores/options';
|
import useOptionStore from 'src/stores/options';
|
||||||
import { useRequestList } from 'src/stores/request-list';
|
import { useRequestList } from 'src/stores/request-list';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { locale } = useI18n();
|
||||||
const optionStore = useOptionStore();
|
const optionStore = useOptionStore();
|
||||||
const requestListStore = useRequestList();
|
const requestListStore = useRequestList();
|
||||||
|
|
||||||
|
|
@ -24,6 +27,7 @@ const props = withDefaults(
|
||||||
id: string;
|
id: string;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
propertiesToShow: (PropString | PropNumber | PropDate | PropOptions)[];
|
propertiesToShow: (PropString | PropNumber | PropDate | PropOptions)[];
|
||||||
|
requestListData: RequestData;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
|
|
@ -31,6 +35,8 @@ const props = withDefaults(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const readonlyField = ['quotationNo', 'contactPerson', 'telephone', 'employer'];
|
||||||
|
|
||||||
const formRemark = ref<string>('');
|
const formRemark = ref<string>('');
|
||||||
const formData = ref<{
|
const formData = ref<{
|
||||||
[field: string]: string | number | null | undefined;
|
[field: string]: string | number | null | undefined;
|
||||||
|
|
@ -77,10 +83,22 @@ function triggerEdit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function assignToForm() {
|
function assignToForm() {
|
||||||
|
const requestData = props.requestListData;
|
||||||
|
// console.log(requestData);
|
||||||
formRemark.value = attributes.value?.remark || '';
|
formRemark.value = attributes.value?.remark || '';
|
||||||
formData.value = JSON.parse(
|
formData.value = JSON.parse(
|
||||||
JSON.stringify(attributes.value?.properties || {}),
|
JSON.stringify(attributes.value?.properties || {}),
|
||||||
);
|
);
|
||||||
|
formData.value['quotationNo'] = requestData.quotation.code;
|
||||||
|
formData.value['contactPerson'] = requestData.quotation.contactName;
|
||||||
|
formData.value['telephone'] = requestData.quotation.contactTel;
|
||||||
|
formData.value['employee'] = getEmployeeName(requestData.employee, {
|
||||||
|
locale: locale.value,
|
||||||
|
});
|
||||||
|
formData.value['employer'] = getCustomerName(
|
||||||
|
requestData.quotation.customerBranch,
|
||||||
|
{ locale: locale.value },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
|
|
@ -143,7 +161,7 @@ defineEmits<{
|
||||||
{{ i + 1 }} {{ optionStore.mapOption(prop.fieldName) }}
|
{{ i + 1 }} {{ optionStore.mapOption(prop.fieldName) }}
|
||||||
</article>
|
</article>
|
||||||
<PropertiesToInput
|
<PropertiesToInput
|
||||||
:readonly="!state.isEdit"
|
:readonly="!state.isEdit || readonlyField.includes(prop.fieldName)"
|
||||||
:prop="prop"
|
:prop="prop"
|
||||||
:placeholder="optionStore.mapOption(prop.fieldName)"
|
:placeholder="optionStore.mapOption(prop.fieldName)"
|
||||||
v-model="formData[prop.fieldName]"
|
v-model="formData[prop.fieldName]"
|
||||||
|
|
|
||||||
|
|
@ -816,6 +816,7 @@ function goToQuotation(
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<PropertiesExpansion
|
<PropertiesExpansion
|
||||||
|
:request-list-data="data"
|
||||||
:id="value.id"
|
:id="value.id"
|
||||||
:readonly="
|
:readonly="
|
||||||
data.requestDataStatus === RequestDataStatus.Canceled
|
data.requestDataStatus === RequestDataStatus.Canceled
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,10 @@ function taskOrderStatus(value: TaskOrderStatus, type: 'status' | 'color') {
|
||||||
status: 'taskOrder.sentTask',
|
status: 'taskOrder.sentTask',
|
||||||
color: '--blue-6-hsl',
|
color: '--blue-6-hsl',
|
||||||
},
|
},
|
||||||
|
[TaskOrderStatus.Restart]: {
|
||||||
|
status: 'taskOrder.status.Restart',
|
||||||
|
color: '--red-5-hsl',
|
||||||
|
},
|
||||||
}[value][type];
|
}[value][type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,7 +161,13 @@ const emit = defineEmits<{
|
||||||
{{ props.row.code || '-' }}
|
{{ props.row.code || '-' }}
|
||||||
</div>
|
</div>
|
||||||
</q-td>
|
</q-td>
|
||||||
<q-td v-if="visibleColumns.includes('issueBranch')">-</q-td>
|
<q-td v-if="visibleColumns.includes('issueBranch')">
|
||||||
|
{{
|
||||||
|
$i18n.locale === 'eng'
|
||||||
|
? props.row.registeredBranch.nameEN || '-'
|
||||||
|
: props.row.registeredBranch.name || '-'
|
||||||
|
}}
|
||||||
|
</q-td>
|
||||||
<q-td v-if="visibleColumns.includes('institution')">
|
<q-td v-if="visibleColumns.includes('institution')">
|
||||||
{{
|
{{
|
||||||
$i18n.locale === 'eng'
|
$i18n.locale === 'eng'
|
||||||
|
|
@ -251,7 +261,10 @@ const emit = defineEmits<{
|
||||||
:custom-data="[
|
:custom-data="[
|
||||||
{
|
{
|
||||||
label: $t('taskOrder.issueBranch'),
|
label: $t('taskOrder.issueBranch'),
|
||||||
value: props.row.issueBranch,
|
value:
|
||||||
|
$i18n.locale === 'eng'
|
||||||
|
? props.row.registeredBranch.nameEN || '-'
|
||||||
|
: props.row.registeredBranch.name || '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('general.agencies'),
|
label: $t('general.agencies'),
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,9 @@ function hideIcon() {
|
||||||
:label="
|
:label="
|
||||||
currStatus?.value === TaskStatus.Validate && type === 'order'
|
currStatus?.value === TaskStatus.Validate && type === 'order'
|
||||||
? $t('taskOrder.done')
|
? $t('taskOrder.done')
|
||||||
: $t(`taskOrder.status.${status}`)
|
: currStatus?.value === TaskStatus.Redo && type === 'receive'
|
||||||
|
? $t(`taskOrder.status.receive.Canceled`)
|
||||||
|
: $t(`taskOrder.status.${status}`)
|
||||||
"
|
"
|
||||||
class="text-capitalize text-weight-regular product-status rounded"
|
class="text-capitalize text-weight-regular product-status rounded"
|
||||||
:class="{
|
:class="{
|
||||||
|
|
@ -90,7 +92,8 @@ function hideIcon() {
|
||||||
negative:
|
negative:
|
||||||
currStatus?.value === TaskStatus.Failed ||
|
currStatus?.value === TaskStatus.Failed ||
|
||||||
currStatus?.value === TaskStatus.Redo ||
|
currStatus?.value === TaskStatus.Redo ||
|
||||||
currStatus?.value === TaskStatus.Canceled,
|
currStatus?.value === TaskStatus.Canceled ||
|
||||||
|
currStatus?.value === TaskStatus.Restart,
|
||||||
'pointer-events-none': {
|
'pointer-events-none': {
|
||||||
order: !['Success', 'Failed', 'Validate'].includes(status || ''),
|
order: !['Success', 'Failed', 'Validate'].includes(status || ''),
|
||||||
receive: status !== TaskStatus.InProgress,
|
receive: status !== TaskStatus.InProgress,
|
||||||
|
|
@ -110,7 +113,9 @@ function hideIcon() {
|
||||||
(v) => v.value === TaskStatus.Complete,
|
(v) => v.value === TaskStatus.Complete,
|
||||||
),
|
),
|
||||||
Failed: taskStatusOrderToggle.filter(
|
Failed: taskStatusOrderToggle.filter(
|
||||||
(v) => v.value === TaskStatus.Redo,
|
(v) =>
|
||||||
|
v.value === TaskStatus.Redo ||
|
||||||
|
v.value === TaskStatus.Restart,
|
||||||
),
|
),
|
||||||
Validate: taskStatusOrderToggle.filter(
|
Validate: taskStatusOrderToggle.filter(
|
||||||
(v) => v.value !== TaskStatus.InProgress,
|
(v) => v.value !== TaskStatus.InProgress,
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@ export const taskStatusOpts = [
|
||||||
status: TaskStatus.Complete,
|
status: TaskStatus.Complete,
|
||||||
name: 'taskOrder.status.Complete',
|
name: 'taskOrder.status.Complete',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
status: TaskStatus.Restart,
|
||||||
|
name: 'taskOrder.status.Restart',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const pageTabs = [
|
export const pageTabs = [
|
||||||
|
|
@ -89,6 +93,11 @@ export const taskStatusOrderToggle = [
|
||||||
icon: 'mdi-file-remove-outline',
|
icon: 'mdi-file-remove-outline',
|
||||||
color: 'negative',
|
color: 'negative',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: TaskStatus.Restart,
|
||||||
|
icon: 'mdi-file-remove-outline',
|
||||||
|
color: 'negative',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const column = [
|
export const column = [
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ defineProps<{
|
||||||
<span>{{ branch.webUrl }}</span>
|
<span>{{ branch.webUrl }}</span>
|
||||||
</article>
|
</article>
|
||||||
<article>
|
<article>
|
||||||
<b>ลูกค้า</b>
|
<b>{{ $t('general.agencyAddress') }}</b>
|
||||||
<span>
|
<span>
|
||||||
{{
|
{{
|
||||||
formatAddress({
|
formatAddress({
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// NOTE: Import stores
|
// NOTE: Import stores
|
||||||
import { dateFormat } from 'src/utils/datetime';
|
import { dateFormatJS } from 'src/utils/datetime';
|
||||||
|
|
||||||
// NOTE Import Types
|
// NOTE Import Types
|
||||||
import {
|
import {
|
||||||
|
|
@ -19,8 +19,8 @@ defineProps<{
|
||||||
contactTel?: string;
|
contactTel?: string;
|
||||||
contactUrl?: string;
|
contactUrl?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
receivedDate?: Date | string;
|
acceptedAt?: Date | string;
|
||||||
deliveryDate?: Date | string;
|
submittedAt?: Date | string;
|
||||||
status?: UserTaskStatus;
|
status?: UserTaskStatus;
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -96,7 +96,11 @@ defineProps<{
|
||||||
:label="$t('taskOrder.workStartDate')"
|
:label="$t('taskOrder.workStartDate')"
|
||||||
>
|
>
|
||||||
<template #value>
|
<template #value>
|
||||||
{{ receivedDate ? dateFormat(receivedDate) : '-' }}
|
{{
|
||||||
|
acceptedAt
|
||||||
|
? dateFormatJS({ date: acceptedAt, withTime: true })
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
</template>
|
</template>
|
||||||
</DataDisplay>
|
</DataDisplay>
|
||||||
|
|
||||||
|
|
@ -105,7 +109,11 @@ defineProps<{
|
||||||
:label="$t('taskOrder.workSubmissionDate')"
|
:label="$t('taskOrder.workSubmissionDate')"
|
||||||
>
|
>
|
||||||
<template #value>
|
<template #value>
|
||||||
{{ deliveryDate ? dateFormat(deliveryDate) : '-' }}
|
{{
|
||||||
|
submittedAt
|
||||||
|
? dateFormatJS({ date: submittedAt, withTime: true })
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
</template>
|
</template>
|
||||||
</DataDisplay>
|
</DataDisplay>
|
||||||
|
|
||||||
|
|
@ -121,6 +129,7 @@ defineProps<{
|
||||||
Pending: 'waitReceive',
|
Pending: 'waitReceive',
|
||||||
Accept: 'receiveTask',
|
Accept: 'receiveTask',
|
||||||
Submit: 'sentTask',
|
Submit: 'sentTask',
|
||||||
|
Restart: 'status.Restart',
|
||||||
}[status] ?? 'waitReceive'
|
}[status] ?? 'waitReceive'
|
||||||
}`,
|
}`,
|
||||||
)
|
)
|
||||||
|
|
@ -130,6 +139,7 @@ defineProps<{
|
||||||
Pending: '--info-bg',
|
Pending: '--info-bg',
|
||||||
Accept: '--info-bg',
|
Accept: '--info-bg',
|
||||||
Submit: '--positive-bg',
|
Submit: '--positive-bg',
|
||||||
|
Restart: '--negative-bg',
|
||||||
}[status] ?? '--info-bg'
|
}[status] ?? '--info-bg'
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -467,6 +467,7 @@ async function getFileList(taskId: string) {
|
||||||
async function remove(taskId: string, n: string) {
|
async function remove(taskId: string, n: string) {
|
||||||
dialogWarningClose(t, {
|
dialogWarningClose(t, {
|
||||||
message: t('dialog.message.confirmDelete'),
|
message: t('dialog.message.confirmDelete'),
|
||||||
|
actionText: t('dialog.action.ok'),
|
||||||
action: async () => {
|
action: async () => {
|
||||||
const res = await taskOrderStore.delAttachment({
|
const res = await taskOrderStore.delAttachment({
|
||||||
parentId: taskId,
|
parentId: taskId,
|
||||||
|
|
@ -876,6 +877,16 @@ watch([currentFormData.value.taskStatus], () => {
|
||||||
(l) => l.userId === v.responsibleUser.id,
|
(l) => l.userId === v.responsibleUser.id,
|
||||||
)?.userTaskStatus || UserTaskStatus.Pending
|
)?.userTaskStatus || UserTaskStatus.Pending
|
||||||
"
|
"
|
||||||
|
:accepted-at="
|
||||||
|
fullTaskOrder?.userTask.find(
|
||||||
|
(l) => l.userId === v.responsibleUser.id,
|
||||||
|
)?.acceptedAt
|
||||||
|
"
|
||||||
|
:submitted-at="
|
||||||
|
fullTaskOrder?.userTask.find(
|
||||||
|
(l) => l.userId === v.responsibleUser.id,
|
||||||
|
)?.submittedAt
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<template #product>
|
<template #product>
|
||||||
<FormGroupHead>
|
<FormGroupHead>
|
||||||
|
|
@ -977,12 +988,21 @@ watch([currentFormData.value.taskStatus], () => {
|
||||||
>
|
>
|
||||||
<template #append="{ props: subProps }">
|
<template #append="{ props: subProps }">
|
||||||
<TaskStatusComponent
|
<TaskStatusComponent
|
||||||
|
:key="subProps.row.id"
|
||||||
:no-action="view !== TaskOrderStatus.Validate"
|
:no-action="view !== TaskOrderStatus.Validate"
|
||||||
type="order"
|
type="order"
|
||||||
:readonly="
|
:readonly="
|
||||||
fullTaskOrder?.userTask.find(
|
(() => {
|
||||||
(l) => l.userId === v.responsibleUser.id,
|
const _userStatus =
|
||||||
)?.userTaskStatus !== UserTaskStatus.Submit
|
fullTaskOrder?.userTask.find(
|
||||||
|
(l) => l.userId === v.responsibleUser.id,
|
||||||
|
)?.userTaskStatus;
|
||||||
|
console.log(_userStatus);
|
||||||
|
return (
|
||||||
|
_userStatus !== UserTaskStatus.Submit &&
|
||||||
|
_userStatus !== UserTaskStatus.Restart
|
||||||
|
);
|
||||||
|
})()
|
||||||
"
|
"
|
||||||
:status="subProps.row.taskStatus"
|
:status="subProps.row.taskStatus"
|
||||||
@click-failed="
|
@click-failed="
|
||||||
|
|
@ -1066,27 +1086,40 @@ watch([currentFormData.value.taskStatus], () => {
|
||||||
solid
|
solid
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<SaveButton
|
<SaveButton
|
||||||
v-if="state.mode !== 'create' && view === TaskOrderStatus.Validate"
|
v-if="state.mode !== 'create' && view === TaskOrderStatus.Validate"
|
||||||
:disabled="
|
:disabled="
|
||||||
!fullTaskOrder?.taskList.every(
|
!fullTaskOrder?.taskList.some((t) =>
|
||||||
(t) =>
|
[
|
||||||
t.taskStatus === TaskStatus.Complete ||
|
TaskStatus.Complete,
|
||||||
t.taskStatus === TaskStatus.Redo ||
|
TaskStatus.Redo,
|
||||||
t.taskStatus === TaskStatus.Canceled,
|
TaskStatus.Canceled,
|
||||||
) || fullTaskOrder.taskOrderStatus === TaskOrderStatus.Complete
|
TaskStatus.Validate,
|
||||||
|
].includes(t.taskStatus),
|
||||||
|
) || fullTaskOrder?.taskOrderStatus === TaskOrderStatus.Complete
|
||||||
"
|
"
|
||||||
@click="
|
@click="
|
||||||
dialogWarningClose(t, {
|
dialogWarningClose(t, {
|
||||||
message: t('dialog.message.confirmValidate'),
|
message: $t(
|
||||||
|
`${
|
||||||
|
fullTaskOrder?.taskList.some(
|
||||||
|
(t) =>
|
||||||
|
t.taskStatus === TaskStatus.Pending ||
|
||||||
|
t.taskStatus === TaskStatus.InProgress ||
|
||||||
|
t.taskStatus === TaskStatus.Restart,
|
||||||
|
)
|
||||||
|
? 'dialog.message.confirmEndWorkWarning'
|
||||||
|
: 'dialog.message.confirmEndWork'
|
||||||
|
}`,
|
||||||
|
),
|
||||||
|
actionText: $t('dialog.action.ok'),
|
||||||
action: async () => {
|
action: async () => {
|
||||||
await completeValidate();
|
await completeValidate();
|
||||||
},
|
},
|
||||||
cancel: () => {},
|
cancel: () => {},
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
:label="$t('taskOrder.confirmValidate')"
|
:label="$t('taskOrder.confirmEndWork')"
|
||||||
icon="mdi-check"
|
icon="mdi-check"
|
||||||
solid
|
solid
|
||||||
></SaveButton>
|
></SaveButton>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { computed, onMounted, ref, watch } from 'vue';
|
||||||
import { getUserId } from 'src/services/keycloak';
|
import { getUserId } from 'src/services/keycloak';
|
||||||
|
|
||||||
// NOTE: Import Components
|
// NOTE: Import Components
|
||||||
import { SaveButton, MainButton } from 'src/components/button';
|
import { SaveButton } from 'src/components/button';
|
||||||
import { StateButton } from 'components/button';
|
import { StateButton } from 'components/button';
|
||||||
import InfoMessengerExpansion from '../expansion/receive/InfoMessengerExpansion.vue';
|
import InfoMessengerExpansion from '../expansion/receive/InfoMessengerExpansion.vue';
|
||||||
import InfoProductExpansion from '../expansion/receive/InfoProductExpansion.vue';
|
import InfoProductExpansion from '../expansion/receive/InfoProductExpansion.vue';
|
||||||
|
|
@ -61,6 +61,7 @@ const statusTabForm = ref<
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
const failedDialog = ref(false);
|
const failedDialog = ref(false);
|
||||||
|
const failedDialogReadonly = ref(false);
|
||||||
const taskStatusRecords = ref<
|
const taskStatusRecords = ref<
|
||||||
{
|
{
|
||||||
requestWorkId: string;
|
requestWorkId: string;
|
||||||
|
|
@ -72,6 +73,7 @@ const taskStatusRecords = ref<
|
||||||
>([]);
|
>([]);
|
||||||
const selectedEmployee = ref<
|
const selectedEmployee = ref<
|
||||||
(RequestWork & {
|
(RequestWork & {
|
||||||
|
taskStatus: TaskStatus;
|
||||||
_template?: {
|
_template?: {
|
||||||
id: string;
|
id: string;
|
||||||
templateName: string;
|
templateName: string;
|
||||||
|
|
@ -207,15 +209,6 @@ let taskListGroup = computed(() => {
|
||||||
// NOTE: Function
|
// NOTE: Function
|
||||||
async function sendTask() {
|
async function sendTask() {
|
||||||
if (!fullTaskOrder.value) return;
|
if (!fullTaskOrder.value) return;
|
||||||
if (
|
|
||||||
!fullTaskOrder.value.taskList.every(
|
|
||||||
(t) =>
|
|
||||||
t.taskStatus === TaskStatus.Success ||
|
|
||||||
t.taskStatus === TaskStatus.Failed ||
|
|
||||||
t.taskStatus === TaskStatus.Canceled,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
await useTaskOrderStore().submitTaskOrder(
|
await useTaskOrderStore().submitTaskOrder(
|
||||||
fullTaskOrder.value.id,
|
fullTaskOrder.value.id,
|
||||||
getUserId(),
|
getUserId(),
|
||||||
|
|
@ -477,6 +470,20 @@ watch([currentFormData.value.taskStatus], () => {
|
||||||
fullTaskOrder?.taskList[0].requestWorkStep.responsibleUserId,
|
fullTaskOrder?.taskList[0].requestWorkStep.responsibleUserId,
|
||||||
)?.userTaskStatus || UserTaskStatus.Pending
|
)?.userTaskStatus || UserTaskStatus.Pending
|
||||||
"
|
"
|
||||||
|
:accepted-at="
|
||||||
|
fullTaskOrder.userTask.find(
|
||||||
|
(l) =>
|
||||||
|
l.userId ===
|
||||||
|
fullTaskOrder?.taskList[0].requestWorkStep.responsibleUserId,
|
||||||
|
)?.acceptedAt
|
||||||
|
"
|
||||||
|
:submitted-at="
|
||||||
|
fullTaskOrder.userTask.find(
|
||||||
|
(l) =>
|
||||||
|
l.userId ===
|
||||||
|
fullTaskOrder?.taskList[0].requestWorkStep.responsibleUserId,
|
||||||
|
)?.submittedAt
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<InfoProductExpansion
|
<InfoProductExpansion
|
||||||
|
|
@ -633,6 +640,15 @@ watch([currentFormData.value.taskStatus], () => {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
failedDialog = true;
|
failedDialog = true;
|
||||||
|
failedDialogReadonly =
|
||||||
|
fullTaskOrder?.userTask.find(
|
||||||
|
(l) =>
|
||||||
|
l.userId ===
|
||||||
|
fullTaskOrder?.taskList[0].requestWorkStep
|
||||||
|
.responsibleUserId,
|
||||||
|
)?.userTaskStatus === UserTaskStatus.Submit
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@change-status="
|
@change-status="
|
||||||
|
|
@ -654,6 +670,7 @@ watch([currentFormData.value.taskStatus], () => {
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
|
|
||||||
<FailRemarkDialog
|
<FailRemarkDialog
|
||||||
|
:readonly="failedDialogReadonly"
|
||||||
:fail-task-option="list"
|
:fail-task-option="list"
|
||||||
v-model:open="failedDialog"
|
v-model:open="failedDialog"
|
||||||
v-model:set-task-status-list="taskStatusRecords"
|
v-model:set-task-status-list="taskStatusRecords"
|
||||||
|
|
@ -688,6 +705,7 @@ watch([currentFormData.value.taskStatus], () => {
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<!-- SEC: footer -->
|
<!-- SEC: footer -->
|
||||||
|
|
||||||
<footer
|
<footer
|
||||||
v-if="fullTaskOrder.taskOrderStatus !== TaskOrderStatus.Pending"
|
v-if="fullTaskOrder.taskOrderStatus !== TaskOrderStatus.Pending"
|
||||||
class="surface-1 q-pa-md full-width"
|
class="surface-1 q-pa-md full-width"
|
||||||
|
|
@ -695,16 +713,22 @@ watch([currentFormData.value.taskStatus], () => {
|
||||||
<nav class="row justify-end">
|
<nav class="row justify-end">
|
||||||
<SaveButton
|
<SaveButton
|
||||||
:disabled="
|
:disabled="
|
||||||
!fullTaskOrder.taskList.every(
|
fullTaskOrder.taskList.some(
|
||||||
(t) =>
|
(t) =>
|
||||||
t.taskStatus === TaskStatus.Success ||
|
t.taskStatus === TaskStatus.Pending ||
|
||||||
t.taskStatus === TaskStatus.Failed ||
|
t.taskStatus === TaskStatus.InProgress ||
|
||||||
t.taskStatus === TaskStatus.Canceled,
|
t.taskStatus === TaskStatus.Restart,
|
||||||
)
|
) ||
|
||||||
|
fullTaskOrder?.userTask.find(
|
||||||
|
(l) =>
|
||||||
|
l.userId ===
|
||||||
|
fullTaskOrder?.taskList[0].requestWorkStep.responsibleUserId,
|
||||||
|
)?.userTaskStatus !== UserTaskStatus.Accept
|
||||||
"
|
"
|
||||||
@click="
|
@click="
|
||||||
dialogWarningClose($t, {
|
dialogWarningClose($t, {
|
||||||
message: $t('dialog.message.confirmSending'),
|
message: $t('dialog.message.confirmSending'),
|
||||||
|
actionText: $t('dialog.action.ok'),
|
||||||
action: async () => {
|
action: async () => {
|
||||||
await sendTask();
|
await sendTask();
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ export enum TaskOrderStatus {
|
||||||
Complete = 'Complete',
|
Complete = 'Complete',
|
||||||
Accept = 'Accept', // messenger only
|
Accept = 'Accept', // messenger only
|
||||||
Submit = 'Submit', // messenger only
|
Submit = 'Submit', // messenger only
|
||||||
|
Restart = 'Restart',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TaskStatus {
|
export enum TaskStatus {
|
||||||
|
|
@ -23,6 +24,7 @@ export enum TaskStatus {
|
||||||
Validate = 'Validate',
|
Validate = 'Validate',
|
||||||
Complete = 'Complete',
|
Complete = 'Complete',
|
||||||
Canceled = 'Canceled',
|
Canceled = 'Canceled',
|
||||||
|
Restart = 'Restart',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TaskOrder {
|
export interface TaskOrder {
|
||||||
|
|
@ -61,6 +63,8 @@ export interface UserTask {
|
||||||
taskOrderId: string;
|
taskOrderId: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
userTaskStatus: UserTaskStatus;
|
userTaskStatus: UserTaskStatus;
|
||||||
|
acceptedAt?: Date | string;
|
||||||
|
submittedAt?: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Institution {
|
export interface Institution {
|
||||||
|
|
@ -196,6 +200,7 @@ export enum UserTaskStatus {
|
||||||
Pending = 'Pending',
|
Pending = 'Pending',
|
||||||
Accept = 'Accept',
|
Accept = 'Accept',
|
||||||
Submit = 'Submit',
|
Submit = 'Submit',
|
||||||
|
Restart = 'Restart',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SetTaskStatusPayload {
|
export interface SetTaskStatusPayload {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ import { getRole } from 'src/services/keycloak';
|
||||||
|
|
||||||
import GlobalDialog from 'components/GlobalDialog.vue';
|
import GlobalDialog from 'components/GlobalDialog.vue';
|
||||||
import DialogDuplicateData from 'components/DialogDuplicateData.vue';
|
import DialogDuplicateData from 'components/DialogDuplicateData.vue';
|
||||||
|
import useOptionStore from '../options';
|
||||||
|
import { CustomerBranch } from '../customer/types';
|
||||||
|
import { CustomerBranchRelation } from '../quotations';
|
||||||
|
import { Employee } from '../employee/types';
|
||||||
|
|
||||||
export const baseUrl = import.meta.env.VITE_API_BASE_URL;
|
export const baseUrl = import.meta.env.VITE_API_BASE_URL;
|
||||||
|
|
||||||
|
|
@ -53,6 +57,7 @@ export function dialogWarningClose(
|
||||||
t: ComposerTranslation,
|
t: ComposerTranslation,
|
||||||
opts: {
|
opts: {
|
||||||
message?: string;
|
message?: string;
|
||||||
|
actionText?: string;
|
||||||
action?: (...args: unknown[]) => unknown;
|
action?: (...args: unknown[]) => unknown;
|
||||||
cancel?: (...args: unknown[]) => unknown;
|
cancel?: (...args: unknown[]) => unknown;
|
||||||
},
|
},
|
||||||
|
|
@ -61,7 +66,7 @@ export function dialogWarningClose(
|
||||||
color: 'warning',
|
color: 'warning',
|
||||||
icon: 'mdi-alert',
|
icon: 'mdi-alert',
|
||||||
title: t('form.warning.title'),
|
title: t('form.warning.title'),
|
||||||
actionText: t('dialog.action.close'),
|
actionText: opts.actionText || t('dialog.action.close'),
|
||||||
message: opts.message || t('dialog.message.warningClose'),
|
message: opts.message || t('dialog.message.warningClose'),
|
||||||
action: async () => {
|
action: async () => {
|
||||||
if (opts.action) opts.action();
|
if (opts.action) opts.action();
|
||||||
|
|
@ -542,3 +547,42 @@ export function changeMode(mode: string) {
|
||||||
export function capitalizeFirstLetter(val: string) {
|
export function capitalizeFirstLetter(val: string) {
|
||||||
return String(val).charAt(0).toUpperCase() + String(val).slice(1);
|
return String(val).charAt(0).toUpperCase() + String(val).slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCustomerName(
|
||||||
|
record: CustomerBranch | CustomerBranchRelation,
|
||||||
|
opts?: {
|
||||||
|
locale?: string;
|
||||||
|
noCode?: boolean;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const customer = record;
|
||||||
|
|
||||||
|
return (
|
||||||
|
{
|
||||||
|
['CORP']: {
|
||||||
|
['eng']: customer.registerNameEN,
|
||||||
|
['tha']: customer.registerName,
|
||||||
|
}[opts?.locale || 'eng'],
|
||||||
|
['PERS']:
|
||||||
|
{
|
||||||
|
['eng']: `${useOptionStore().mapOption(customer?.namePrefix || '')} ${customer?.firstNameEN} ${customer?.lastNameEN}`,
|
||||||
|
['tha']: `${useOptionStore().mapOption(customer?.namePrefix || '')} ${customer?.firstName} ${customer?.lastName}`,
|
||||||
|
}[opts?.locale || 'eng'] || '-',
|
||||||
|
}[customer.customer.customerType] +
|
||||||
|
(opts?.noCode ? '' : ' ' + `(${customer.code})`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEmployeeName(
|
||||||
|
record: Employee,
|
||||||
|
opts?: {
|
||||||
|
locale?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const employee = record;
|
||||||
|
|
||||||
|
return {
|
||||||
|
['eng']: `${useOptionStore().mapOption(employee.namePrefix)} ${employee.firstNameEN} ${employee.lastNameEN}`,
|
||||||
|
['tha']: `${useOptionStore().mapOption(employee.namePrefix)} ${employee.firstName} ${employee.lastName}`,
|
||||||
|
}[opts?.locale || 'eng'];
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ export function dateFormatJS(opts: {
|
||||||
noDay?: boolean;
|
noDay?: boolean;
|
||||||
noMonth?: boolean;
|
noMonth?: boolean;
|
||||||
noYear?: boolean;
|
noYear?: boolean;
|
||||||
}) {
|
withTime?: boolean;
|
||||||
|
}): string {
|
||||||
const dt = opts.date ? new Date(opts.date) : new Date();
|
const dt = opts.date ? new Date(opts.date) : new Date();
|
||||||
|
|
||||||
const { locale } = i18n.global;
|
const { locale } = i18n.global;
|
||||||
|
|
@ -35,6 +36,17 @@ export function dateFormatJS(opts: {
|
||||||
opts.timeStyle = opts.timeStyle || 'short';
|
opts.timeStyle = opts.timeStyle || 'short';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let timeText = opts.withTime
|
||||||
|
? ' ' +
|
||||||
|
dateFormatJS({
|
||||||
|
date: opts.date,
|
||||||
|
timeOnly: true,
|
||||||
|
timeStyle: opts.timeStyle,
|
||||||
|
})
|
||||||
|
: '';
|
||||||
|
|
||||||
|
if (timeText) opts.timeStyle = undefined;
|
||||||
|
|
||||||
let formatted = new Intl.DateTimeFormat(opts.locale, {
|
let formatted = new Intl.DateTimeFormat(opts.locale, {
|
||||||
day: opts.noDay ? undefined : opts.dayStyle || 'numeric',
|
day: opts.noDay ? undefined : opts.dayStyle || 'numeric',
|
||||||
month: opts.noMonth ? undefined : opts.monthStyle || 'short',
|
month: opts.noMonth ? undefined : opts.monthStyle || 'short',
|
||||||
|
|
@ -46,11 +58,13 @@ export function dateFormatJS(opts: {
|
||||||
case Lang.Thai:
|
case Lang.Thai:
|
||||||
case 'th-TH':
|
case 'th-TH':
|
||||||
case 'th-Th':
|
case 'th-Th':
|
||||||
return formatted.replace(/(\d{4})/, (year) =>
|
return (
|
||||||
(parseInt(year) - 543).toString(),
|
formatted.replace(/(\d{4})/, (year) =>
|
||||||
|
(parseInt(year) - 543).toString(),
|
||||||
|
) + timeText
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return formatted;
|
return formatted + timeText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue