diff --git a/package.json b/package.json index cdf5646..c0a48c7 100644 --- a/package.json +++ b/package.json @@ -1,68 +1,69 @@ { - "name": "ehr", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "vite", - "build": "run-p build-only", - "preview": "vite preview", - "test:unit": "vitest --environment jsdom --root src/", - "test:e2e": "start-server-and-test preview :4173 'cypress run --e2e'", - "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' :4173 'cypress open --e2e'", - "build-only": "vite build", - "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false", - "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", - "format": "prettier ./src --write" - }, - "dependencies": { - "@fullcalendar/core": "^6.0.1", - "@fullcalendar/daygrid": "^6.0.1", - "@fullcalendar/interaction": "^6.0.2", - "@fullcalendar/list": "^6.0.2", - "@fullcalendar/react": "^6.0.1", - "@fullcalendar/timegrid": "^6.0.2", - "@fullcalendar/vue3": "^6.0.1", - "@quasar/extras": "^1.15.8", - "@tato30/vue-pdf": "^1.5.1", - "@vuepic/vue-datepicker": "^3.6.3", - "bma-org-chart": "^0.0.7", - "dom-to-image-more": "^3.6.0", - "keycloak-js": "^20.0.2", - "moment": "^2.29.4", - "pdf-lib": "^1.17.1", - "pinia": "^2.0.29", - "quasar": "^2.11.1", - "socket.io-client": "^4.7.4", - "structure-chart": "^0.0.9", - "vue": "^3.4.15", - "vue-router": "^4.1.6", - "vue3-datepicker": "^0.3.4", - "vue3-pdfjs": "^0.1.6" - }, - "devDependencies": { - "@quasar/vite-plugin": "^1.3.0", - "@rushstack/eslint-patch": "^1.1.4", - "@types/jsdom": "^20.0.1", - "@types/node": "^18.11.12", - "@vitejs/plugin-vue": "^4.0.0", - "@vitejs/plugin-vue-jsx": "^3.0.0", - "@vue/eslint-config-prettier": "^7.0.0", - "@vue/eslint-config-typescript": "^11.0.0", - "@vue/test-utils": "^2.2.6", - "@vue/tsconfig": "^0.1.3", - "cypress": "^12.0.2", - "eslint": "^8.22.0", - "eslint-plugin-cypress": "^2.12.1", - "eslint-plugin-vue": "^9.3.0", - "jsdom": "^20.0.3", - "npm-run-all": "^4.1.5", - "prettier": "^2.7.1", - "sass": "^1.32.12", - "start-server-and-test": "^1.15.2", - "typescript": "~4.7.4", - "vite": "^4.0.0", - "vitest": "^0.25.6", - "vue-table-to-excel": "^1.0.6", - "vue-tsc": "^1.0.12" - } + "name": "ehr", + "version": "0.0.0", + "private": true, + "scripts": { + "dev": "vite", + "build": "run-p build-only", + "preview": "vite preview", + "test:unit": "vitest --environment jsdom --root src/", + "test:e2e": "start-server-and-test preview :4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' :4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", + "format": "prettier ./src --write" + }, + "dependencies": { + "@fullcalendar/core": "^6.0.1", + "@fullcalendar/daygrid": "^6.0.1", + "@fullcalendar/interaction": "^6.0.2", + "@fullcalendar/list": "^6.0.2", + "@fullcalendar/react": "^6.0.1", + "@fullcalendar/timegrid": "^6.0.2", + "@fullcalendar/vue3": "^6.0.1", + "@quasar/extras": "^1.15.8", + "@tato30/vue-pdf": "^1.5.1", + "@vuepic/vue-datepicker": "^3.6.3", + "bma-org-chart": "^0.0.7", + "dom-to-image-more": "^3.6.0", + "keycloak-js": "^20.0.2", + "moment": "^2.29.4", + "pdf-lib": "^1.17.1", + "pinia": "^2.0.29", + "quasar": "^2.11.1", + "socket.io-client": "^4.7.4", + "structure-chart": "^0.0.9", + "vue": "^3.4.15", + "vue-router": "^4.1.6", + "vue3-datepicker": "^0.3.4", + "vue3-pdfjs": "^0.1.6", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@quasar/vite-plugin": "^1.3.0", + "@rushstack/eslint-patch": "^1.1.4", + "@types/jsdom": "^20.0.1", + "@types/node": "^18.11.12", + "@vitejs/plugin-vue": "^4.0.0", + "@vitejs/plugin-vue-jsx": "^3.0.0", + "@vue/eslint-config-prettier": "^7.0.0", + "@vue/eslint-config-typescript": "^11.0.0", + "@vue/test-utils": "^2.2.6", + "@vue/tsconfig": "^0.1.3", + "cypress": "^12.0.2", + "eslint": "^8.22.0", + "eslint-plugin-cypress": "^2.12.1", + "eslint-plugin-vue": "^9.3.0", + "jsdom": "^20.0.3", + "npm-run-all": "^4.1.5", + "prettier": "^2.7.1", + "sass": "^1.32.12", + "start-server-and-test": "^1.15.2", + "typescript": "~4.7.4", + "vite": "^4.0.0", + "vitest": "^0.25.6", + "vue-table-to-excel": "^1.0.6", + "vue-tsc": "^1.0.12" + } } diff --git a/src/api/index.ts b/src/api/index.ts index a45d8af..e5e225c 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -12,8 +12,8 @@ export const apiUrlConfigReport = import.meta.env.VITE_API_REPORT_URL; const config = ref({ development: { // API_URI: "https://localhost:7260/api", - API_URI: "https://bma-ehr.frappet.synology.me/api/v1", - API_URL_SUPPORT: "https://bma-ehr.frappet.synology.me/api/v1/support", + API_URI: "https://hrmsbkk.case-collection.com/api/v1", + API_URL_SUPPORT: "https://hrmsbkk.case-collection.com/api/v1/support", MEET_URI: "meet.frappet.com", LINK_EVALUATE_PUBLISH: "https://bma-ehr-publish.frappet.synology.me", API_REPORT_TEMPLATE_URI: diff --git a/src/api/org/api.org.ts b/src/api/org/api.org.ts index 1c2fcb7..ae33413 100644 --- a/src/api/org/api.org.ts +++ b/src/api/org/api.org.ts @@ -3,7 +3,6 @@ import env from "../index"; const metadata = `${env.API_URI}/org/metadata/`; const org = `${env.API_URI}/org`; const profileOrg = `${env.API_URI}/org/profile`; -const report = `${env.API_URI}/org`; const workflow = `${env.API_URI}/org/workflow`; export default { orgCommandCode: `${metadata}commandCode`, @@ -70,9 +69,9 @@ export default { dataUserOtherByType: (type: string) => `${org}/profile${type}/other/user`, profileReportId: (profileId: string, type: string) => - `${report}/${type}/kk1/${profileId}`, + `${org}/${type}/kk1/${profileId}`, profileKp7ShortId: (profileId: string, type: string) => - `${report}/${type}/kp7-short/${profileId}`, + `${org}/${type}/kp7-short/${profileId}`, /** history */ dataUserInformatioHistory: (type: string) => @@ -177,4 +176,7 @@ export default { orgAssistance: (id: string) => `${profileOrg}/assistance/${id}`, orgIssues: `${env.API_URI}/org/issues`, + + // ตรวจสอบข้อมูลตำแหน่งและเงินเดือน + profileSalaryTemp: `${profileOrg}/salaryTemp`, }; diff --git a/src/modules/01_dashboard/views/Dashboard.vue b/src/modules/01_dashboard/views/Dashboard.vue index 12dad21..2479fe9 100644 --- a/src/modules/01_dashboard/views/Dashboard.vue +++ b/src/modules/01_dashboard/views/Dashboard.vue @@ -54,7 +54,8 @@ const items = ref([ icon: "mdi-account-group-outline", title: "แผนผังองค์กร", sub: "ดูแผนผังองค์กร", - color: "blue-3", + // color: "blue-3", + color: "grey-3", path: "/organization-chart", active: false, }, @@ -305,8 +306,14 @@ onMounted(async () => {
{ > {{ item.sub }}
+ + อยู่ระหว่างปรับปรุง
@@ -511,7 +521,7 @@ onMounted(async () => { border: 1px solid #6dbdb142; } .disabledcard { - color: rgba(209, 209, 209, 0.733) !important; + color: rgba(105, 104, 104, 0.733) !important; border-color: rgba(207, 207, 207, 0.322) !important; box-shadow: none !important; border-radius: 12px; diff --git a/src/modules/07_appealComplain/views/Form.vue b/src/modules/07_appealComplain/views/Form.vue index d2b715f..79854eb 100644 --- a/src/modules/07_appealComplain/views/Form.vue +++ b/src/modules/07_appealComplain/views/Form.vue @@ -1,5 +1,5 @@ @@ -255,7 +255,7 @@ watch( lazy-rules hide-bottom-space /> - +
{}); }, - "ยืนยันการแก้ไขอีเมล" + "ยืนยันการแก้ไขอีเมล", ); } } @@ -588,7 +588,18 @@ onMounted(async () => {
-
อีเมล
+
+ อีเมล + + + รอยืนยันอีเมล + +
@@ -606,62 +617,50 @@ onMounted(async () => { @change="isValidEmail = true" />
-
-
- - แก้ไขข้อมูล - -
-
- - บันทึก - - - ยกเลิก - -
-
-
- --> +
+ - รอยืนยันอีเมล - + แก้ไขข้อมูล +
+
+ + บันทึก + + + ยกเลิก + +
+
diff --git a/src/modules/10_registry/02_Government/07_Position.vue b/src/modules/10_registry/02_Government/07_Position.vue index 8ee5ed1..f981efb 100644 --- a/src/modules/10_registry/02_Government/07_Position.vue +++ b/src/modules/10_registry/02_Government/07_Position.vue @@ -27,7 +27,7 @@ const { } = useCounterMixin(); const checkType = ref( - dataPerson.officerType == "OFFICER" ? true : false + dataPerson.officerType == "OFFICER" ? true : false, ); // เช็คประเภทผู้ใช้งาน const mode = ref($q.screen.gt.xs); // เช็คขนาดหน้าจอ ถ้าเป็นขนาดใหญ่กว่า xs จะเป็นโหมดแสดงตาราง const isLoading = reactive({ @@ -320,25 +320,25 @@ const columns = computed(() => { (column) => column.name !== "positionExecutive" && column.name !== "lastUpdateFullName" && - column.name !== "lastUpdatedAt" + column.name !== "lastUpdatedAt", ); } } return baseColumns.value.filter( (e: QTableColumn) => - e.name !== "lastUpdateFullName" && e.name !== "lastUpdatedAt" + e.name !== "lastUpdateFullName" && e.name !== "lastUpdatedAt", ); }); const visibleColumns = ref( baseVisibleColumns.value.filter( - (e: string) => e !== "lastUpdateFullName" && e !== "lastUpdatedAt" - ) + (e: string) => e !== "lastUpdateFullName" && e !== "lastUpdatedAt", + ), ); const columnsHistory = computed(() => { if (!checkType.value) { if (baseColumns.value) { return baseColumns.value.filter( - (column) => column.name !== "positionExecutive" + (column) => column.name !== "positionExecutive", ); } } @@ -445,7 +445,7 @@ function onSearch() { rows.value = onSearchDataTable( filter.value, rowsData.value, - columns.value ? columns.value : [] + columns.value ? columns.value : [], ); } @@ -491,7 +491,7 @@ onMounted(async () => {
-
+ -
+
+import { ref, onMounted, computed, reactive, watch } from "vue"; +import { useQuasar } from "quasar"; +import * as XLSX from "xlsx"; + +import http from "@/plugins/http"; +import config from "@/app.config"; +// import { useRoute } from "vue-router"; +import { useCounterMixin } from "@/stores/mixin"; +// import { useEditPosDataStore } from "@/modules/04_registryPerson/stores/Edit"; +import { useDataStore } from "@/stores/data"; +import { useGovernmentPosDataStore } from "@/modules/10_registry/store/Position"; + +import type { QTableColumn } from "quasar"; +// import type { FormDataSalary } from "@/modules/10_registry/interface/index/Edit"; +import type { DataCommandCode } from "@/modules/10_registry/interface/review/Main"; +import type { DataPosition } from "@/modules/10_registry/interface/review/Edit"; +// import type { +// DataPosType, +// DataPosLevel, +// } from "@/modules/10_registry/interface/response/Position"; + +// import DialogForm from "@/modules/04_registryPerson/views/edit/components/DialogForm.vue"; +// import DialogSort from "@/modules/04_registryPerson/views/edit/components/DialogSort.vue"; +// import CurruncyInput from "@/components/CurruncyInput.vue"; + +const dataStore = useDataStore(); +const store = useGovernmentPosDataStore(); +const $q = useQuasar(); +// const route = useRoute(); + +const { + date2Thai, + findOrgName, + onSearchDataTable, + // dialogRemove, + // showLoader, + // hideLoader, + messageError, + // success, + findOrgNameHtml, + // dialogConfirm, + // convertDateToAPI, +} = useCounterMixin(); + +const tabs = defineModel("tabs", { required: true }); +const isConfirmEdit = defineModel("isConfirmEdit", { required: true }); +const statusCheckEdit = defineModel("statusCheckEdit", { + required: true, +}); +const empType = ref("officer"); +const profileId = ref(""); + +// const amountRef = ref(null); +// const amountSpecialRef = ref(null); +// const currencyPopupRef = ref(null); + +//Table +const isLoad = ref(true); +const rowIndex = ref(0); +const rows = ref([]); +const rowsMain = ref([]); +const keyword = ref(""); +const baseColumns = ref([ + { + name: "no", + align: "left", + label: "ลำดับ", + sortable: false, + field: "no", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + }, + { + name: "commandDateAffect", + align: "left", + label: "วันที่คำสั่งมีผล", + sortable: false, + field: "commandDateAffect", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + format: (v) => date2Thai(v), + }, + { + name: "positionName", + align: "left", + label: empType.value === "employee" ? "ตำแหน่ง" : "ตำแหน่งในสายงาน", + sortable: false, + field: "positionName", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + }, + { + name: "positionType", + align: "left", + label: empType.value === "employee" ? "กลุ่มงาน" : "ตำแหน่งประเภท", + sortable: false, + field: "positionType", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + }, + { + name: "positionLevel", + align: "left", + label: empType.value === "employee" ? "ระดับชั้นงาน" : "ระดับ", + sortable: false, + field: "positionLevel", + format(val, row) { + return `${ + row.positionLevel + ? row.positionLevel + : row.positionCee + ? row.positionCee + : "-" + }`; + }, + headerStyle: "font-size: 14px", + style: "font-size: 14px", + }, + { + name: "positionExecutive", + align: "left", + label: "ตำแหน่งทางการบริหาร", + sortable: false, + field: "positionExecutive", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + }, + { + name: "positionExecutiveField", + align: "left", + label: "ด้านทางการบริหาร", + sortable: false, + field: "positionExecutiveField", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + }, + { + name: "amount", + align: "left", + label: empType.value === "employee" ? "ค่าจ้าง" : "เงินเดือน", + sortable: false, + field: "amount", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + format(v, row) { + return row.amount + ? `${Number(row.amount).toLocaleString()}${ + row.amountSpecial !== 0 && row.amountSpecial + ? ` (${Number(row.amountSpecial).toLocaleString()})` + : "" + }` + : "-"; + }, + }, + { + name: "mouthSalaryAmount", + align: "left", + label: "เงินค่าตอบแทนรายเดือน", + sortable: false, + field: "mouthSalaryAmount", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + format: (v) => (v ? Number(v).toLocaleString() : "-"), + }, + { + name: "positionSalaryAmount", + align: "left", + label: "เงินประจำตำแหน่ง", + sortable: false, + field: "positionSalaryAmount", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + format: (v) => (v ? Number(v).toLocaleString() : "-"), + }, + { + name: "organization", + align: "left", + label: "สังกัด", + sortable: false, + field: "organization", + headerStyle: "font-size: 14px;min-width: 280px", + style: "font-size: 14px", + format(val, row) { + return findOrgName({ + root: row.orgRoot, + child1: row.orgChild1, + child2: row.orgChild2, + child3: row.orgChild3, + child4: row.orgChild4, + }); + }, + }, + { + name: "posNo", + align: "left", + label: empType.value === "employee" ? "ตำแหน่งเลขที่" : "เลขที่ตำแหน่ง", + sortable: false, + field: "posNo", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + format(val, row) { + return row.posNoAbb && row.posNo + ? `${row.posNoAbb} ${row.posNo}` + : row.posNo + ? row.posNo + : "-"; + }, + }, + { + name: "posNumCodeSit", + align: "left", + label: "หน่วยงานที่ออกคำสั่ง", + sortable: false, + field: "posNumCodeSit", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + format(val, row) { + return row.posNumCodeSitAbb && row.posNumCodeSit + ? `${row.posNumCodeSit} (${row.posNumCodeSitAbb})` + : row.posNumCodeSit + ? row.posNumCodeSit + : "-"; + }, + }, + { + name: "commandNo", + align: "left", + label: "เลขที่คำสั่ง", + sortable: false, + field: "commandNo", + format(val, row) { + return row.commandNo && row.commandYear + ? `${row.commandNo}/${Number(row.commandYear) + 543}` + : "-"; + }, + headerStyle: "font-size: 14px", + style: "font-size: 14px", + }, + { + name: "commandDateSign", + align: "left", + label: "วันที่ลงนาม", + sortable: false, + field: "commandDateSign", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + format: (v) => date2Thai(v), + }, + { + name: "commandCode", + align: "left", + label: "ประเภทคำสั่ง", + sortable: false, + field: "commandCode", + format(val, row) { + return store.convertCommandCodeName(val); + }, + headerStyle: "font-size: 14px", + style: "font-size: 14px", + }, + { + name: "remark", + align: "left", + label: "หมายเหตุ", + sortable: false, + field: "remark", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + }, +]); +const visibleColumns = ref([ + "no", + "commandDateAffect", + "positionName", + "positionType", + "positionLevel", + "positionExecutive", + "positionExecutiveField", + "amount", + "mouthSalaryAmount", + "positionSalaryAmount", + "organization", + "posNo", + "posNumCodeSit", + "commandNo", + "commandDateSign", + "commandCode", + "remark", +]); +const columns = computed(() => { + if (empType.value === "employee") { + if (baseColumns.value) { + return baseColumns.value.filter( + (column) => + column.name !== "positionSalaryAmount" && + column.name !== "mouthSalaryAmount" && + column.name !== "positionExecutive" && + column.name !== "positionExecutivefield", + ); + } + } + return baseColumns.value; +}); + +const modal = ref(false); +const modalSort = ref(false); +const isAddPosition = ref(true); // สถานะการเพิ่มตำแหน่ง + +/** function fetch ข้อมูลรายการตำแหน่งเงินเดือน*/ +async function fetchData() { + empType.value = dataStore.officerType.toLowerCase(); + profileId.value = dataStore.profileId; + + isLoad.value = true; + rowsMain.value = []; + rows.value = []; + // const paht = + // tabs.value === "PENDING" + // ? `/${empType.value}/${profileId.value}` + // : `/${empType.value}/done/${profileId.value}`; + http + .get( + `${config.API.profileSalaryTemp}/${empType.value}/done/${profileId.value}`, + ) + .then((res) => { + const data = res.data.result; + rowsMain.value = data; + rows.value = data; + serchDataTable(); + }) + .catch((err) => { + messageError($q, err); + }) + .finally(() => { + isLoad.value = false; + }); +} + +/** function ค้นหาข้อมูลรายการในตาราง*/ +function serchDataTable() { + rows.value = onSearchDataTable( + keyword.value, + rowsMain.value, + columns.value ? columns.value : [], + ); +} + +/** + * funciton + * @param index + */ +function onEditData(index: number) { + rowIndex.value = index; + modal.value = true; + isAddPosition.value = index === -1; // ถ้า index เป็น -1 แสดงว่าเป็นการเพิ่มข้อมูลใหม่ +} + +// /** +// * function สลับตำแหน่งของข้อมูลขึ้นลง +// * @param action up , down +// * @param id id รายการที่ต้องการสลับตะแหน่ง +// */ +// async function onSwapData(action: string, id: string) { +// showLoader(); +// await http +// .get(config.API.salaryTemp + `/swap/${action}/${id}`) +// .then(async () => { +// await fetchData(); +// }) +// .catch((err) => { +// messageError($q, err); +// }) +// .finally(() => { +// hideLoader(); +// }); +// } + +// /** +// * function ลบข้อมูลรายการตำแหน่งเงินเดือน +// * @param id id ที่ต้องการลบข้อมูลรายการตำแหน่งเงินเดือน +// * @param isDelete true ลบข้อมูลรานการตำแหน่งเงินเดือน false นำข้อมูลรายการที่ลบไปกลับมา +// */ +// function onConfirmDeleteData(id: string, isDelete: boolean) { +// isDelete +// ? dialogConfirm( +// $q, +// () => { +// onDeleteData(id, isDelete); +// }, +// "ยืนยันการย้อนกลับข้อมูล", +// "ต้องการยืนยันการย้อนกลับข้อมูลนี้ใช่หรือไม่?" +// ) +// : dialogRemove($q, () => { +// onDeleteData(id, isDelete); +// }); +// } + +// /** +// * function ลบข้อมูลรายการตำแหน่งเงินเดือน +// * @param id id ที่ต้องการลบข้อมูลรายการตำแหน่งเงินเดือน +// * @param isDelete true ลบข้อมูลรานการตำแหน่งเงินเดือน false นำข้อมูลรายการที่ลบไปกลับมา +// */ +// async function onDeleteData(id: string, isDelete: boolean) { +// showLoader(); +// const path = isDelete ? "/delete-renew" : "/delete"; +// await http +// .post(config.API.salaryTemp + `${path}`, { +// type: empType.value, +// salaryId: id, +// }) +// .then(async () => { +// await fetchData(); +// success($q, isDelete ? "ย้อนกลับข้อมูลสำเร็จ" : "ลบข้อมูลสำเร็จ"); +// }) +// .catch((err) => { +// messageError($q, err); +// }) +// .finally(() => { +// hideLoader(); +// }); +// } + +/** + * class สีของข้อความ + * @param isDelete รายการที่ลบ + * @param isEdit รายการที่แก้ไข + * @param isEntry รายการข้อมูลที่มากจาก Entry + * @returns class ส + */ +function classColorRow(isDelete: boolean, isEdit: boolean, isEntry: boolean) { + return isDelete + ? "text-red" + : isEdit + ? "text-orange" + : isEntry + ? "text-grey" + : ""; +} + +/** ฟังก์ชันดาวน์โหลดไฟล Excel */ +function exportToExcel() { + const newData = rows.value.map((e: DataPosition, index: number) => { + return { + no: index + 1, + commandDateAffect: date2Thai(e.commandDateAffect), + positionName: e.positionName, + positionType: e.positionType, + positionLevel: e.positionLevel + ? e.positionLevel + : e.positionCee + ? e.positionCee + : "", + positionExecutive: e.positionExecutive, + amount: e.amount, + mouthSalaryAmount: e.mouthSalaryAmount, + positionSalaryAmount: e.positionSalaryAmount, + organization: findOrgName({ + root: e.orgRoot, + child1: e.orgChild1, + child2: e.orgChild2, + child3: e.orgChild3, + child4: e.orgChild4, + }), + posNo: + e.posNoAbb && e.posNo + ? `${e.posNoAbb} ${e.posNo}` + : e.posNo + ? e.posNo + : "", + posNumCodeSit: + e.posNumCodeSitAbb && e.posNumCodeSit + ? `${e.posNumCodeSit} (${e.posNumCodeSitAbb})` + : e.posNumCodeSit + ? e.posNumCodeSit + : "", + commandNo: + e.commandNo && e.commandYear + ? `${e.commandNo}/${Number(e.commandYear) + 543}` + : "", + commandDateSign: date2Thai(e.commandDateSign), + commandCode: store.convertCommandCodeName(e.commandCode), + remark: e.remark, + }; + }); + + const headers = columns.value.map((item: any) => item.label) || []; // หัวคอลัมน์ภาษาไทย + const worksheet = XLSX.utils.json_to_sheet(newData, { + header: visibleColumns.value, + }); + + //แทรกหัวคอลัมน์ภาษาไทย (ใช้ A1, B1, C1 แทน) + XLSX.utils.sheet_add_aoa(worksheet, [headers], { origin: "A1" }); + + // Create a new workbook and append the worksheet + const workbook = XLSX.utils.book_new(); + + XLSX.utils.book_append_sheet( + workbook, + worksheet, + `รายการประวัติตำแหน่งเงินเดือน`, + ); + XLSX.writeFile(workbook, "รายการประวัติตำแหน่งเงินเดือน.xlsx"); +} + +// const commandCodeOptions = ref(store.commandCodeData); //รายการปรเภทคำสั่ง +// const posTypeOptions = ref(store.posTypeData); //รายการประเภทตำแหน่ง | กลุ่มงาน +// const posLevelOptions = ref(store.posLevelData); //รายการระดับตำแหน่ง | ระดับชั้นงาน +// const dataLevel = ref([]); //รายการ ตำแหน่งเงินเดือน + +// const formData = reactive({ +// positionLevel: "", +// positionCee: "", +// amount: 0, +// amountSpecial: 0, +// posNoAbb: "", +// posNo: "", +// orgRoot: "", +// orgChild1: "", +// orgChild2: "", +// orgChild3: "", +// orgChild4: "", +// commandCode: "", +// posNumCodeSit: "", +// posNumCodeSitAbb: "", +// commandNo: "", +// commandYear: null, +// }); + +// const isPositionName = ref(false); //เช็คว่ามี ตำแหน่งประเภท +// const isUpdateData = ref(false); // สถานะการแก้ไข +// const colNameMain = ref(""); //ชื่อ Coolumn ที่ต้องการแก้ไข +// const salaryId = ref(""); // id ที่ต้องการแก้ไข + +/** function fetch ข้อมูลประเภทคำสั่ง*/ +async function fetchDataCommandCode() { + if (store.commandCodeData.length > 0) return false; + await http + .get(config.API.orgCommandCode) + .then((res) => { + const data = res.data.result; + const options = data.map((e: DataCommandCode) => ({ + id: e.code.toString(), + name: e.name, + })); + + store.commandCodeData = options; + }) + .catch((err) => { + messageError($q, err); + }); +} + +// /** +// * ฟังก์ชันกำหนดค่าที่ต้องการแก้ไข +// * @param data ข้อมูลที่ต้องการแก้ไข +// * @param colName ชื่อ Columns ที่ต้เองการแก้ไข +// */ +// function onShow(data: DataPosition, colName: string) { +// salaryId.value = data.id; +// isUpdateData.value = false; +// commandCodeOptions.value = store.commandCodeData; +// posTypeOptions.value = store.posTypeData; +// if (colName === "positionLevel" && data.positionType) { +// updateSelectType(data.positionType); +// } +// colNameMain.value = colName; +// isPositionName.value = data.positionType ? true : false; +// formData.positionLevel = data.positionLevel; +// formData.positionCee = data.positionCee; +// formData.amount = data.amount; +// formData.amountSpecial = data.amountSpecial; +// formData.orgRoot = data.orgRoot; +// formData.orgChild1 = data.orgChild1; +// formData.orgChild2 = data.orgChild2; +// formData.orgChild3 = data.orgChild3; +// formData.orgChild4 = data.orgChild4; +// formData.posNoAbb = data.posNoAbb; +// formData.posNo = data.posNo; +// formData.commandCode = data.commandCode; +// formData.posNumCodeSit = data.posNumCodeSit; +// formData.posNumCodeSitAbb = data.posNumCodeSitAbb; +// formData.commandNo = data.commandNo; +// formData.commandYear = data.commandYear; +// } + +// /** +// * ฟังก์ชันบันทึกข้อมูลการแก้ไข +// * @param val +// * @param id +// * @param close +// */ +// async function onSave(val: any, id: string, close?: () => void) { +// // ตรวจสอบ validation ถ้า amountRef มีค่าและมี validate method +// if (amountRef.value && typeof amountRef.value.validate === "function") { +// const isValid = amountRef.value.validate(); +// if (isValid === false) { +// return; // หยุดการบันทึกถ้า validation ไม่ผ่าน +// } +// } + +// if (isUpdateData.value) { +// showLoader(); +// const isCol = (key: string) => colNameMain.value === key; +// const toNumber = (v: any) => +// v ? Number(String(v).replace(/,/g, "")) : null; +// const body: Record = {}; +// if (isCol("commandDateAffect")) { +// body.commandDateAffect = convertDateToAPI(val); +// } +// if (isCol("positionName")) { +// body.positionName = val; +// } +// if (isCol("positionType")) { +// body.positionType = val; +// } +// if (isCol("positionLevel")) { +// body.positionLevel = formData.positionLevel; +// body.positionCee = formData.positionCee; +// } +// if (isCol("positionExecutive")) { +// body.positionExecutive = val; +// } +// if (isCol("positionExecutiveField")) { +// body.positionExecutiveField = val; +// } +// if (isCol("amount")) { +// body.amount = toNumber(formData.amount); +// body.amountSpecial = toNumber(formData.amountSpecial); +// } +// if (isCol("positionSalaryAmount")) { +// body.positionSalaryAmount = toNumber(val); +// } +// if (isCol("mouthSalaryAmount")) { +// body.mouthSalaryAmount = toNumber(val); +// } +// if (isCol("organization")) { +// body.orgRoot = formData.orgRoot; +// body.orgChild1 = formData.orgChild1; +// body.orgChild2 = formData.orgChild2; +// body.orgChild3 = formData.orgChild3; +// body.orgChild4 = formData.orgChild4; +// } +// if (isCol("posNo")) { +// body.posNo = formData.posNo; +// body.posNoAbb = formData.posNoAbb; +// } +// if (isCol("posNumCodeSit")) { +// body.posNumCodeSit = formData.posNumCodeSit; +// body.posNumCodeSitAbb = formData.posNumCodeSitAbb; +// } +// if (isCol("commandDateSign")) { +// body.commandDateSign = convertDateToAPI(val); +// } +// if (isCol("commandNo")) { +// body.commandNo = formData.commandNo; +// body.commandYear = formData.commandYear; +// } +// if (isCol("commandCode")) { +// body.commandCode = formData.commandCode; +// } +// if (isCol("remark")) { +// body.remark = val; +// } + +// await http +// .patch(config.API.salaryTemp + `/${salaryId.value}`, body) +// .then(async () => { +// success($q, "บันทึกข้อมูลสำเร็จ"); +// const idx = rows.value.findIndex((item) => item.id === salaryId.value); +// // อัปเดทข้อมูลในตาราง +// if (idx !== -1) { +// rows.value[idx] = { +// ...rows.value[idx], +// ...body, +// }; +// } + +// // อัปเดทข้อมูลหลัก +// const idxMain = rowsMain.value.findIndex( +// (item) => item.id === salaryId.value, +// ); +// if (idxMain !== -1) { +// rowsMain.value[idxMain] = { +// ...rowsMain.value[idxMain], +// ...body, +// }; +// } +// }) +// .catch(async (err) => { +// await fetchData?.(); +// messageError($q, err); +// }) +// .finally(() => { +// hideLoader(); +// if (close) close(); +// }); +// } else { +// if (close) { +// close(); +// } +// } +// } + +// /** +// * ฟิลเตอร์ข้อมูลจาก input +// * @param val ค่าที่ป้อนให้ input +// * @param update function จาก quasar +// * @param filtername type ที่กำหนด ของ input นั้นๆ +// */ +// function filterSelector(val: string, update: Function, filtername: string) { +// switch (filtername) { +// case "commandCode": +// update(() => { +// commandCodeOptions.value = store.commandCodeData.filter( +// (v: DataOption) => v.name.indexOf(val) > -1, +// ); +// }); +// break; + +// case "posType": +// update(() => { +// posTypeOptions.value = store.posTypeData.filter( +// (v: DataOption) => v.name.indexOf(val) > -1, +// ); +// }); +// break; + +// case "posLevel": +// update(() => { +// posLevelOptions.value = store.posLevelData.filter( +// (v: DataOption) => v.name.indexOf(val) > -1, +// ); +// }); +// break; + +// default: +// break; +// } +// } + +// /** ฟังก์ชันเรียกข้อมูลปรเภทตำแหน่งข้าราชการ */ +// async function fetchType() { +// const entpont = +// empType.value === "officer" +// ? config.API.orgPosType +// : config.API.orgEmployeeType; +// await http +// .get(entpont) +// .then((res) => { +// dataLevel.value = res.data.result; +// store.posTypeData = res.data.result.map((e: DataPosType) => ({ +// id: e.id, +// name: e.posTypeName, +// })); +// posTypeOptions.value = store.posTypeData; +// }) +// .catch((err) => { +// messageError($q, err); +// }); +// } + +// /** +// * ฟังก์ชันเลือกประเภทตำแหน่ง +// * @param val id ประเภทตำแหน่ง +// */ +// async function updateSelectType(val: string) { +// const listLevel = val +// ? dataLevel.value.find((e: DataPosType) => e.posTypeName === val) +// : null; + +// // เช็คประเภทตำแหน่งงาน +// if (listLevel) { +// store.posLevelData = listLevel.posLevels.map((e: DataPosLevel) => ({ +// id: e.id, +// name: +// empType.value === "officer" +// ? e.posLevelName +// : `${listLevel.posTypeShortName} ${e.posLevelName}`, +// })); +// } +// } + +// /** ฟังก์ชันอัปเดทการแก้ไข*/ +// function onUpdateData() { +// isUpdateData.value = true; +// } + +// /** +// * ฟังก์ชันตรวจสอบ validation และบันทึกข้อมูลสำหรับทุกประเภท +// */ +// async function validateAndSave( +// val: any, +// id: string, +// close?: () => void, +// fieldType: "amount" | "currency" | "normal" = "normal", +// ) { +// let isValid = true; + +// // ตรวจสอบ validation สำหรับ amount fields +// if (fieldType === "amount") { +// // Validate เงินเดือน +// if (formData.amount !== null && formData.amount !== undefined) { +// const amountNum = +// typeof formData.amount === "number" +// ? formData.amount +// : Number(String(formData.amount).replace(/,/g, "")); +// if (amountNum > 10000000) { +// isValid = false; +// } +// } + +// // Validate เงินค่าตอบแทนพิเศษ +// if ( +// isValid && +// formData.amountSpecial !== null && +// formData.amountSpecial !== undefined +// ) { +// const amountSpecialNum = +// typeof formData.amountSpecial === "number" +// ? formData.amountSpecial +// : Number(String(formData.amountSpecial).replace(/,/g, "")); +// if (amountSpecialNum > 10000000) { +// isValid = false; +// } +// } + +// // Force validate refs ถ้ามี +// if ( +// isValid && +// amountRef.value && +// typeof amountRef.value.validate === "function" +// ) { +// const amountValid = amountRef.value.validate(); +// isValid = isValid && amountValid !== false; +// } + +// if ( +// isValid && +// amountSpecialRef.value && +// typeof amountSpecialRef.value.validate === "function" +// ) { +// const amountSpecialValid = amountSpecialRef.value.validate(); +// isValid = isValid && amountSpecialValid !== false; +// } +// } + +// // ตรวจสอบ validation สำหรับ currency fields อื่นๆ +// else if (fieldType === "currency") { +// // Validate ค่าโดยตรงก่อน +// if (val !== null && val !== undefined) { +// const numVal = +// typeof val === "number" ? val : Number(String(val).replace(/,/g, "")); +// if (numVal > 10000000) { +// isValid = false; +// } +// } + +// // Force validate ref ถ้ามี +// if ( +// isValid && +// currencyPopupRef.value && +// typeof currencyPopupRef.value.validate === "function" +// ) { +// const currencyValid = currencyPopupRef.value.validate(); +// isValid = isValid && currencyValid !== false; +// } +// } + +// // บันทึกข้อมูลถ้า validation ผ่าน +// if (isValid) { +// await onSave(val, id, close); +// return true; +// } else { +// // หยุดการบันทึกถ้า validation ไม่ผ่าน (rules จะแสดง error message เอง) +// return false; +// } +// } + +onMounted(async () => { + // เพิ่ม delay เล็กน้อยเพื่อรอให้ dataStore fetch ข้อมูล position เสร็จก่อน + await new Promise((resolve) => setTimeout(resolve, 800)); + if (dataStore.officerType && dataStore.profileId) { + await Promise.all([fetchData(), fetchDataCommandCode()]); + } +}); + + + + + diff --git a/src/modules/10_registry/interface/review/Edit.ts b/src/modules/10_registry/interface/review/Edit.ts new file mode 100644 index 0000000..04041b2 --- /dev/null +++ b/src/modules/10_registry/interface/review/Edit.ts @@ -0,0 +1,76 @@ +interface DataSalaryPos { + avatar: string; + avatarName: string; + citizenId: string; + firstName: string; + id: string; + lastName: string; + org: string; + orgRevisionId: string; + orgRootShortName: string; + posExecutive: string; + posLevel: string; + posLevelId: string; + posNo: string; + posType: string; + posTypeId: string; + position: string; + prefix: string; + rank: string; + root: string; + rootId: string; + statusCheckEdit: string; + type: string; +} + +interface DataPosition { + no?: number; + amount: number; + amountSpecial: number; + commandCode: string; + commandDateAffect: Date; + commandDateSign: Date; + commandId: string; + commandName: string; + commandNo: string; + commandYear: number; + createdAt: string; + createdFullName: string; + createdUserId: string; + dateGovernment: string; + id: string; + isDelete: boolean; + isEdit: boolean; + isEntry: boolean; + isGovernment: string; + lastUpdateFullName: string; + lastUpdateUserId: string; + lastUpdatedAt: string; + mouthSalaryAmount: number; + order: number; + orgChild1: string; + orgChild2: string; + orgChild3: string; + orgChild4: string; + orgRoot: string; + posNo: string; + posNoAbb: string; + positionCee: string; + positionExecutive: string; + positionLevel: string; + positionLine: string; + positionName: string; + positionPathSide: string; + positionSalaryAmount: number; + positionType: string; + profileEmployeeId: string; + profileId: string; + refId: number; + remark: string; + salaryId: string; + status: string; + posNumCodeSitAbb: string; + posNumCodeSit: string; +} + +export type { DataSalaryPos, DataPosition }; diff --git a/src/modules/10_registry/interface/review/Main.ts b/src/modules/10_registry/interface/review/Main.ts new file mode 100644 index 0000000..9022d50 --- /dev/null +++ b/src/modules/10_registry/interface/review/Main.ts @@ -0,0 +1,155 @@ +interface Pagination { + rowsPerPage: number; +} + +interface DataOption { + id: string; + name: string; +} +interface DataOption2 { + id: number; + name: string; +} + +interface DataOptionSys { + id: string; + name: string; + system: string; +} +interface DataOptionInsignia { + id: string; + name: string; + typeId: string; + typeName: string; +} + +interface DataOptionEducation { + label: string; + value: boolean; +} + +interface DataOptionEducationLevel { + label: string; + value: string; +} + +interface zipCodeOption { + id: string; + name: string; + zipCode: string; +} + +interface InformationOps { + prefixOps: DataOption[]; + rankOps: DataOption[]; + genderOps: DataOption[]; + bloodOps: DataOption[]; + statusOps: DataOption[]; + religionOps: DataOption[]; + employeeClassOps: DataOption[]; + employeeTypeOps: DataOption[]; +} + +interface AddressOps { + provinceOps: DataOption[]; + districtOps: DataOption[]; + districtCOps: DataOption[]; + subdistrictOps: zipCodeOption[]; + subdistrictCOps: zipCodeOption[]; +} + +interface InsigniaOps { + insigniaOptions: DataOptionInsignia[]; +} + +interface ItemTab { + name: string; + icon: string; + label: string; +} + +interface Request { + createdAt: string; + createdFullName: string; + detail: string; + fullname: string; + id: string; + idcard: string; + lastUpdateFullName: string; + lastUpdatedAt: string; + profileId: string; + remark: string; + status: string; + topic: string; +} + +interface InsigniasType { + id: string; + createdAt: Date; + createdUserId: string; + lastUpdatedAt: Date; + lastUpdateUserId: string; + createdFullName: string; + lastUpdateFullName: string; + name: string; + isActive: boolean; + insignias: InsigniasTypeSub[]; +} + +interface InsigniasTypeSub { + id: string; + createdAt: Date; + createdUserId: string; + lastUpdatedAt: Date; + lastUpdateUserId: string; + createdFullName: string; + lastUpdateFullName: string; + name: string; + shortName: string; + level: string; + isActive: string; + note: string; + insigniaTypeId: string; +} + +interface ResFileData { + downloadUrl: string; + fileName: string; + path: string; + pathname: string; +} + +interface DataHistory { + [key: string]: string | number | Date | boolean; +} + +interface DataCommandCode { + id: string; + createdAt: Date; + lastUpdatedAt: Date; + createdFullName: string; + lastUpdateFullName: string; + name: string; + code: number; +} + +export type { + Pagination, + DataOption, + DataOption2, + DataOptionInsignia, + zipCodeOption, + InformationOps, + AddressOps, + InsigniaOps, + DataOptionSys, + ItemTab, + DataOptionEducation, + DataOptionEducationLevel, + Request, + InsigniasType, + InsigniasTypeSub, + ResFileData, + DataHistory, + DataCommandCode, +}; diff --git a/src/modules/10_registry/router.ts b/src/modules/10_registry/router.ts index 8de71c7..a88c4e2 100644 --- a/src/modules/10_registry/router.ts +++ b/src/modules/10_registry/router.ts @@ -17,6 +17,8 @@ const requestEditMain = () => import("@/modules/10_registry/views/requestEditMain.vue"); const requestEditDetail = () => import("@/modules/10_registry/views/requestEditDetail.vue"); +const positionReviewPage = () => + import("@/modules/10_registry/views/positionReview.vue"); export default [ { @@ -93,4 +95,15 @@ export default [ Key: [10], }, }, + + // ตรวจสอบข้อมูลตำแหน่งและเงินเดือน + { + path: "/registry/position-review", + name: "position-review", + component: positionReviewPage, + meta: { + Auth: true, + Key: [10], + }, + }, ]; diff --git a/src/modules/10_registry/store/Position.ts b/src/modules/10_registry/store/Position.ts index ad14276..8ab3a02 100644 --- a/src/modules/10_registry/store/Position.ts +++ b/src/modules/10_registry/store/Position.ts @@ -12,7 +12,7 @@ const {} = mixin; export const useGovernmentPosDataStore = defineStore("GovernmentPos", () => { // commandCode ขอตำแหน่ง const positionCode = ref([ - 0, 1, 2, 3, 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 1, 2, 3, 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, ]); const commandCodeData = ref([]); diff --git a/src/modules/10_registry/tabs/03_salary.vue b/src/modules/10_registry/tabs/03_salary.vue index 22a83ac..12db2d2 100644 --- a/src/modules/10_registry/tabs/03_salary.vue +++ b/src/modules/10_registry/tabs/03_salary.vue @@ -25,7 +25,7 @@ const router = useRouter();
- +
diff --git a/src/modules/10_registry/views/main.vue b/src/modules/10_registry/views/main.vue index 81d75af..5e3a40c 100644 --- a/src/modules/10_registry/views/main.vue +++ b/src/modules/10_registry/views/main.vue @@ -52,11 +52,11 @@ async function onClickDownloadKp7(type: string) { type === "FULL" ? config.API.profileReportId( store.profileId, - dataStore.officerType == "OFFICER" ? "profile" : "profile-employee" + dataStore.officerType == "OFFICER" ? "profile" : "profile-employee", ) : config.API.profileKp7ShortId( store.profileId, - dataStore.officerType == "OFFICER" ? "profile" : "profile-employee" + dataStore.officerType == "OFFICER" ? "profile" : "profile-employee", ); const fileName = type === "FULL" ? "ทปอ. สามัญ" : "ประวัติแบบย่อ"; await http @@ -78,11 +78,6 @@ const clickBack = () => { router.push(`/`); }; -/** ฟังก์ชัน redirect ไปหน้ารายการคำร้องขอแก้ไขข้อมูล*/ -function redirectToPagePetition() { - router.push(`/registry/request-edit`); -} - function onMobile(type: string) { router.push(`/registry/${type}`); } @@ -103,10 +98,20 @@ function onMobile(type: string) { @click="clickBack" /> ข้อมูลทะเบียนประวัติ + + ไปยังหน้าตรวจสอบข้อมูลตำแหน่งและเงินเดือน + + ยื่นคำร้องขอแก้ไขข้อมูล diff --git a/src/modules/10_registry/views/positionReview.vue b/src/modules/10_registry/views/positionReview.vue new file mode 100644 index 0000000..94387f5 --- /dev/null +++ b/src/modules/10_registry/views/positionReview.vue @@ -0,0 +1,197 @@ + + + + +