From a8920b4473d6ca5687b49b6a2d4bc5f298b452d6 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Wed, 10 Jun 2026 10:59:06 +0700 Subject: [PATCH 01/44] feat(changeName): change Rank --- .../02_NameChangeHistory.vue | 68 ++++++++++++++++++- .../interface/request/Main.ts | 1 + 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue b/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue index cbe7f361e..a4c9efd6b 100644 --- a/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue +++ b/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue @@ -59,6 +59,7 @@ const changeNameData = reactive({ profileId: profileId.value, prefixId: "", // id คำนำหน้า prefix: "", // คำนำหน้า + rank: "", // ยศ firstName: "", // ชื่อ lastName: "", // นามสกุล status: "", // สถานะ @@ -69,11 +70,13 @@ const selection = ref([]); // ตัวเลือก const prefixChange = ref(""); // เปลี่ยนคำนำหน้า const firstNameChange = ref(""); // เปลียนชื่อ const lastNameChange = ref(""); // เปลี่ยนนามสกุล +const rankChange = ref(""); // เปลี่ยนยศ const profileInfo = ref(); // ข้อมูล Profile const statusOption = ref([ "เปลี่ยนคำนำหน้าชื่อ", + "เปลี่ยนยศ", "เปลี่ยนชื่อ", "เปลี่ยนนามสกุล", "เปลี่ยนชื่อ-นามสกุล", @@ -84,6 +87,7 @@ const statusOption = ref([ const statusOptionFilter = ref([ "เปลี่ยนคำนำหน้าชื่อ", "เปลี่ยนชื่อ", + "เปลี่ยนยศ", "เปลี่ยนนามสกุล", "เปลี่ยนชื่อ-นามสกุล", "เปลี่ยนคำนำหน้าชื่อ และชื่อ", @@ -107,6 +111,17 @@ const columns = ref([ sort: (a: string, b: string) => a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), }, + { + name: "rank", + align: "left", + label: "ยศ", + sortable: true, + field: "rank", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + sort: (a: string, b: string) => + a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), + }, { name: "firstName", align: "left", @@ -156,6 +171,7 @@ const columns = ref([ ]); const visibleColumns = ref([ "prefix", + "rank", "firstName", "lastName", "lastUpdateFullName", @@ -215,6 +231,7 @@ function onSubmit() { firstName: changeNameData.firstName, lastName: changeNameData.lastName, status: changeNameData.status, + rank: changeNameData.rank, documentId: changeNameData.documentId, }) .then(async (res) => { @@ -346,6 +363,14 @@ function filterSelector(val: string, update: Function, refData: string) { ); }); break; + + case "rankOps": + update(() => { + store.Ops.rankOps = store.OpsFilter.rankOps.filter( + (v: DataOption) => v.name.indexOf(val) > -1 + ); + }); + break; default: break; } @@ -390,12 +415,14 @@ watch( changeNameData.prefix, changeNameData.firstName, changeNameData.lastName, + changeNameData.rank, ], () => { submitDisable.value = changeNameData.prefix === prefixChange.value && changeNameData.firstName === firstNameChange.value && - changeNameData.lastName === lastNameChange.value; + changeNameData.lastName === lastNameChange.value && + changeNameData.rank === rankChange.value; } ); @@ -411,6 +438,9 @@ watch( if (!selection.value.includes("lastname")) { changeNameData.lastName = lastNameChange.value; } + if (!selection.value.includes("rank")) { + changeNameData.rank = rankChange.value; + } } ); /** ทำงานเมื่อ Components ถูกเรียกใช้งาน*/ @@ -445,12 +475,14 @@ onMounted(async () => { icon="add" @click=" () => { - changeNameData.prefix = profileInfo?.prefixMain; + changeNameData.prefix = profileInfo?.prefix; changeNameData.firstName = profileInfo?.firstName; changeNameData.lastName = profileInfo?.lastName; + changeNameData.rank = profileInfo?.rank; prefixChange = changeNameData.prefix; firstNameChange = changeNameData.firstName; lastNameChange = changeNameData.lastName; + rankChange = changeNameData.rank; changeNameData.status = ''; dialogStatus = 'create'; submitDisable = true; @@ -563,12 +595,17 @@ onMounted(async () => {
-
+
+ { ) " />
+
+ +
Date: Thu, 11 Jun 2026 16:30:18 +0700 Subject: [PATCH 02/44] fix --- .forgejo/workflows/build.yaml | 50 -------------------- .forgejo/workflows/ci-cd.yaml | 86 ----------------------------------- .forgejo/workflows/deploy.yml | 29 ------------ 3 files changed, 165 deletions(-) delete mode 100644 .forgejo/workflows/build.yaml delete mode 100644 .forgejo/workflows/ci-cd.yaml delete mode 100644 .forgejo/workflows/deploy.yml diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml deleted file mode 100644 index ddb52c479..000000000 --- a/.forgejo/workflows/build.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# /.forgejo/workflows/build.yml -name: Build - -# on: - # push: - # tags: - # - "v[0-9]+.[0-9]+.[0-9]+" - # - "v[0-9]+.[0-9]+.[0-9]+*" - # workflow_dispatch: - -env: - REGISTRY: ${{ vars.CONTAINER_REGISTRY }} - REGISTRY_USERNAME: ${{ vars.CONTAINER_REGISTRY_USERNAME }} - REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }} - CONTAINER_IMAGE_NAME: ${{ vars.CONTAINER_REGISTRY }}/${{ vars.CONTAINER_IMAGE_OWNER }}/${{ vars.CONTAINER_IMAGE_NAME }} - IMAGE_VERSION: build - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - config-inline: | - [registry."${{ env.REGISTRY }}"] - ca=["/etc/ssl/certs/ca-certificates.crt"] - - name: Tag Version - run: | - if [[ "${{ github.event_name }}" == "push" ]]; then - echo "IMAGE_VERSION=${{ github.ref_name }}" | sed 's/v//g' >> $GITHUB_ENV - else - echo "IMAGE_VERSION=${{ env.IMAGE_VERSION }}-${{ github.run_number }}" >> $GITHUB_ENV - fi - - name: Login in to registry - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ env.REGISTRY_USERNAME }} - password: ${{ env.REGISTRY_PASSWORD }} - - name: Build and push docker image - uses: docker/build-push-action@v3 - with: - platforms: linux/amd64 - context: . - file: ./docker/Dockerfile - tags: ${{ env.CONTAINER_IMAGE_NAME }}:latest,${{ env.CONTAINER_IMAGE_NAME }}:${{ env.IMAGE_VERSION }} - push: true diff --git a/.forgejo/workflows/ci-cd.yaml b/.forgejo/workflows/ci-cd.yaml deleted file mode 100644 index 2bf102922..000000000 --- a/.forgejo/workflows/ci-cd.yaml +++ /dev/null @@ -1,86 +0,0 @@ -# /.forgejo/workflows/ci-cd.yml -name: Build & Deploy on Dev - -on: - push: - # branches: - # - dev - tags: - - "v[0-9]+.[0-9]+.[0-9]+" - - "v[0-9]+.[0-9]+.[0-9]+*" - workflow_dispatch: - -env: - REGISTRY: ${{ vars.CONTAINER_REGISTRY }} - REGISTRY_USERNAME: ${{ vars.CONTAINER_REGISTRY_USERNAME }} - REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }} - CONTAINER_IMAGE_NAME: ${{ vars.CONTAINER_REGISTRY }}/${{ vars.CONTAINER_IMAGE_OWNER }}/${{ vars.CONTAINER_IMAGE_NAME }} - IMAGE_VERSION: latest - DISCORD_WEBHOOK: ${{ vars.DISCORD_WEBHOOK }} - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - config-inline: | - [registry."${{ env.REGISTRY }}"] - ca=["/etc/ssl/certs/ca-certificates.crt"] - - name: Tag Version - run: | - if [ "${{ github.ref_type }}" == "tag" ]; then - echo "IMAGE_VERSION=${{ github.ref_name }}" >> $GITHUB_ENV - else - echo "IMAGE_VERSION=latest" >> $GITHUB_ENV - fi - - name: Login in to registry - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ env.REGISTRY_USERNAME }} - password: ${{ env.REGISTRY_PASSWORD }} - - name: Build and push docker image - uses: docker/build-push-action@v3 - with: - platforms: linux/amd64 - context: . - file: ./docker/Dockerfile - tags: ${{ env.CONTAINER_IMAGE_NAME }}:latest,${{ env.CONTAINER_IMAGE_NAME }}:${{ env.IMAGE_VERSION }} - push: true - - name: Remote Deploy - uses: appleboy/ssh-action@v1.2.1 - with: - host: ${{ vars.SSH_DEPLOY_HOST }} - port: ${{ vars.SSH_DEPLOY_PORT }} - username: ${{ secrets.SSH_DEPLOY_USER }} - password: ${{ secrets.SSH_DEPLOY_PASSWORD }} - script: | - cd ~/repo - ./replace-env.sh APP_MGT "${{ env.IMAGE_VERSION }}" - ./deploy.sh hrms-mgt - - - name: Discord Notification - if: always() - run: | - STATUS="${{ job.status == 'success' && '✅ Success' || '❌ Failed' }}" - COLOR="${{ job.status == 'success' && '3066993' || '15158332' }}" - TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ) - curl -H "Content-Type: application/json" \ - -X POST \ - -d "{ - \"embeds\": [{ - \"title\": \"$STATUS\", - \"description\": \"**Build & Deploy**\\n- Image: \`${{ env.CONTAINER_IMAGE_NAME }}\`\\n- Version: \`${{ env.IMAGE_VERSION }}\`\\n- By: \`${{ github.actor }}\`\", - \"color\": $COLOR, - \"footer\": { - \"text\": \"Release Notification\", - \"icon_url\": \"https://example.com/success-icon.png\" - }, - \"timestamp\": \"$TIMESTAMP\" - }] - }" \ - ${{ env.DISCORD_WEBHOOK }} diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml deleted file mode 100644 index 2e395ae1f..000000000 --- a/.forgejo/workflows/deploy.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Build - -on: - workflow_dispatch: - inputs: - version: - description: "Version to deploy" - type: string - required: false - default: "latest" - -env: - IMAGE_VERSION: build - -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - name: Remote Deploy - uses: appleboy/ssh-action@v1.2.1 - with: - host: ${{ vars.SSH_DEPLOY_HOST }} - port: ${{ vars.SSH_DEPLOY_PORT }} - username: ${{ secrets.SSH_DEPLOY_USER }} - password: ${{ secrets.SSH_DEPLOY_PASSWORD }} - script: | - cd ~/repo - ./replace-env.sh APP_MGT "${{ inputs.version }}" - ./deploy.sh hrms-mgt From 5aed5699b994ceeada72d32ffb2302d3502710e5 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Thu, 11 Jun 2026 18:17:21 +0700 Subject: [PATCH 03/44] fix --- .../02_NameChangeHistory.vue | 68 ++++++++++++++++++- .../interface/request/Main.ts | 1 + 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue b/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue index cbe7f361e..a4c9efd6b 100644 --- a/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue +++ b/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue @@ -59,6 +59,7 @@ const changeNameData = reactive({ profileId: profileId.value, prefixId: "", // id คำนำหน้า prefix: "", // คำนำหน้า + rank: "", // ยศ firstName: "", // ชื่อ lastName: "", // นามสกุล status: "", // สถานะ @@ -69,11 +70,13 @@ const selection = ref([]); // ตัวเลือก const prefixChange = ref(""); // เปลี่ยนคำนำหน้า const firstNameChange = ref(""); // เปลียนชื่อ const lastNameChange = ref(""); // เปลี่ยนนามสกุล +const rankChange = ref(""); // เปลี่ยนยศ const profileInfo = ref(); // ข้อมูล Profile const statusOption = ref([ "เปลี่ยนคำนำหน้าชื่อ", + "เปลี่ยนยศ", "เปลี่ยนชื่อ", "เปลี่ยนนามสกุล", "เปลี่ยนชื่อ-นามสกุล", @@ -84,6 +87,7 @@ const statusOption = ref([ const statusOptionFilter = ref([ "เปลี่ยนคำนำหน้าชื่อ", "เปลี่ยนชื่อ", + "เปลี่ยนยศ", "เปลี่ยนนามสกุล", "เปลี่ยนชื่อ-นามสกุล", "เปลี่ยนคำนำหน้าชื่อ และชื่อ", @@ -107,6 +111,17 @@ const columns = ref([ sort: (a: string, b: string) => a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), }, + { + name: "rank", + align: "left", + label: "ยศ", + sortable: true, + field: "rank", + headerStyle: "font-size: 14px", + style: "font-size: 14px", + sort: (a: string, b: string) => + a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), + }, { name: "firstName", align: "left", @@ -156,6 +171,7 @@ const columns = ref([ ]); const visibleColumns = ref([ "prefix", + "rank", "firstName", "lastName", "lastUpdateFullName", @@ -215,6 +231,7 @@ function onSubmit() { firstName: changeNameData.firstName, lastName: changeNameData.lastName, status: changeNameData.status, + rank: changeNameData.rank, documentId: changeNameData.documentId, }) .then(async (res) => { @@ -346,6 +363,14 @@ function filterSelector(val: string, update: Function, refData: string) { ); }); break; + + case "rankOps": + update(() => { + store.Ops.rankOps = store.OpsFilter.rankOps.filter( + (v: DataOption) => v.name.indexOf(val) > -1 + ); + }); + break; default: break; } @@ -390,12 +415,14 @@ watch( changeNameData.prefix, changeNameData.firstName, changeNameData.lastName, + changeNameData.rank, ], () => { submitDisable.value = changeNameData.prefix === prefixChange.value && changeNameData.firstName === firstNameChange.value && - changeNameData.lastName === lastNameChange.value; + changeNameData.lastName === lastNameChange.value && + changeNameData.rank === rankChange.value; } ); @@ -411,6 +438,9 @@ watch( if (!selection.value.includes("lastname")) { changeNameData.lastName = lastNameChange.value; } + if (!selection.value.includes("rank")) { + changeNameData.rank = rankChange.value; + } } ); /** ทำงานเมื่อ Components ถูกเรียกใช้งาน*/ @@ -445,12 +475,14 @@ onMounted(async () => { icon="add" @click=" () => { - changeNameData.prefix = profileInfo?.prefixMain; + changeNameData.prefix = profileInfo?.prefix; changeNameData.firstName = profileInfo?.firstName; changeNameData.lastName = profileInfo?.lastName; + changeNameData.rank = profileInfo?.rank; prefixChange = changeNameData.prefix; firstNameChange = changeNameData.firstName; lastNameChange = changeNameData.lastName; + rankChange = changeNameData.rank; changeNameData.status = ''; dialogStatus = 'create'; submitDisable = true; @@ -563,12 +595,17 @@ onMounted(async () => {
-
+
+ { ) " />
+
+ +
Date: Thu, 11 Jun 2026 18:20:51 +0700 Subject: [PATCH 04/44] fix --- .forgejo/workflows/build.yaml | 50 ++++++++++++++++++++ .forgejo/workflows/ci-cd.yaml | 86 ++++++++++++++++++++++++++++++++++ .forgejo/workflows/deploy.yaml | 29 ++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 .forgejo/workflows/build.yaml create mode 100644 .forgejo/workflows/ci-cd.yaml create mode 100644 .forgejo/workflows/deploy.yaml diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml new file mode 100644 index 000000000..ddb52c479 --- /dev/null +++ b/.forgejo/workflows/build.yaml @@ -0,0 +1,50 @@ +# /.forgejo/workflows/build.yml +name: Build + +# on: + # push: + # tags: + # - "v[0-9]+.[0-9]+.[0-9]+" + # - "v[0-9]+.[0-9]+.[0-9]+*" + # workflow_dispatch: + +env: + REGISTRY: ${{ vars.CONTAINER_REGISTRY }} + REGISTRY_USERNAME: ${{ vars.CONTAINER_REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }} + CONTAINER_IMAGE_NAME: ${{ vars.CONTAINER_REGISTRY }}/${{ vars.CONTAINER_IMAGE_OWNER }}/${{ vars.CONTAINER_IMAGE_NAME }} + IMAGE_VERSION: build + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + config-inline: | + [registry."${{ env.REGISTRY }}"] + ca=["/etc/ssl/certs/ca-certificates.crt"] + - name: Tag Version + run: | + if [[ "${{ github.event_name }}" == "push" ]]; then + echo "IMAGE_VERSION=${{ github.ref_name }}" | sed 's/v//g' >> $GITHUB_ENV + else + echo "IMAGE_VERSION=${{ env.IMAGE_VERSION }}-${{ github.run_number }}" >> $GITHUB_ENV + fi + - name: Login in to registry + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ env.REGISTRY_USERNAME }} + password: ${{ env.REGISTRY_PASSWORD }} + - name: Build and push docker image + uses: docker/build-push-action@v3 + with: + platforms: linux/amd64 + context: . + file: ./docker/Dockerfile + tags: ${{ env.CONTAINER_IMAGE_NAME }}:latest,${{ env.CONTAINER_IMAGE_NAME }}:${{ env.IMAGE_VERSION }} + push: true diff --git a/.forgejo/workflows/ci-cd.yaml b/.forgejo/workflows/ci-cd.yaml new file mode 100644 index 000000000..2bf102922 --- /dev/null +++ b/.forgejo/workflows/ci-cd.yaml @@ -0,0 +1,86 @@ +# /.forgejo/workflows/ci-cd.yml +name: Build & Deploy on Dev + +on: + push: + # branches: + # - dev + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]+*" + workflow_dispatch: + +env: + REGISTRY: ${{ vars.CONTAINER_REGISTRY }} + REGISTRY_USERNAME: ${{ vars.CONTAINER_REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }} + CONTAINER_IMAGE_NAME: ${{ vars.CONTAINER_REGISTRY }}/${{ vars.CONTAINER_IMAGE_OWNER }}/${{ vars.CONTAINER_IMAGE_NAME }} + IMAGE_VERSION: latest + DISCORD_WEBHOOK: ${{ vars.DISCORD_WEBHOOK }} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + config-inline: | + [registry."${{ env.REGISTRY }}"] + ca=["/etc/ssl/certs/ca-certificates.crt"] + - name: Tag Version + run: | + if [ "${{ github.ref_type }}" == "tag" ]; then + echo "IMAGE_VERSION=${{ github.ref_name }}" >> $GITHUB_ENV + else + echo "IMAGE_VERSION=latest" >> $GITHUB_ENV + fi + - name: Login in to registry + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ env.REGISTRY_USERNAME }} + password: ${{ env.REGISTRY_PASSWORD }} + - name: Build and push docker image + uses: docker/build-push-action@v3 + with: + platforms: linux/amd64 + context: . + file: ./docker/Dockerfile + tags: ${{ env.CONTAINER_IMAGE_NAME }}:latest,${{ env.CONTAINER_IMAGE_NAME }}:${{ env.IMAGE_VERSION }} + push: true + - name: Remote Deploy + uses: appleboy/ssh-action@v1.2.1 + with: + host: ${{ vars.SSH_DEPLOY_HOST }} + port: ${{ vars.SSH_DEPLOY_PORT }} + username: ${{ secrets.SSH_DEPLOY_USER }} + password: ${{ secrets.SSH_DEPLOY_PASSWORD }} + script: | + cd ~/repo + ./replace-env.sh APP_MGT "${{ env.IMAGE_VERSION }}" + ./deploy.sh hrms-mgt + + - name: Discord Notification + if: always() + run: | + STATUS="${{ job.status == 'success' && '✅ Success' || '❌ Failed' }}" + COLOR="${{ job.status == 'success' && '3066993' || '15158332' }}" + TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ) + curl -H "Content-Type: application/json" \ + -X POST \ + -d "{ + \"embeds\": [{ + \"title\": \"$STATUS\", + \"description\": \"**Build & Deploy**\\n- Image: \`${{ env.CONTAINER_IMAGE_NAME }}\`\\n- Version: \`${{ env.IMAGE_VERSION }}\`\\n- By: \`${{ github.actor }}\`\", + \"color\": $COLOR, + \"footer\": { + \"text\": \"Release Notification\", + \"icon_url\": \"https://example.com/success-icon.png\" + }, + \"timestamp\": \"$TIMESTAMP\" + }] + }" \ + ${{ env.DISCORD_WEBHOOK }} diff --git a/.forgejo/workflows/deploy.yaml b/.forgejo/workflows/deploy.yaml new file mode 100644 index 000000000..2e395ae1f --- /dev/null +++ b/.forgejo/workflows/deploy.yaml @@ -0,0 +1,29 @@ +name: Build + +on: + workflow_dispatch: + inputs: + version: + description: "Version to deploy" + type: string + required: false + default: "latest" + +env: + IMAGE_VERSION: build + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Remote Deploy + uses: appleboy/ssh-action@v1.2.1 + with: + host: ${{ vars.SSH_DEPLOY_HOST }} + port: ${{ vars.SSH_DEPLOY_PORT }} + username: ${{ secrets.SSH_DEPLOY_USER }} + password: ${{ secrets.SSH_DEPLOY_PASSWORD }} + script: | + cd ~/repo + ./replace-env.sh APP_MGT "${{ inputs.version }}" + ./deploy.sh hrms-mgt From bf4b03e64337724868e6b11df5453cc26697620f Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Fri, 12 Jun 2026 11:09:55 +0700 Subject: [PATCH 05/44] refactor(registry-officer): prefix --- .../components/detail/PersonalInformation/01_Profile.vue | 3 ++- .../detail/PersonalInformation/02_NameChangeHistory.vue | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue b/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue index 1d686dfe8..d37b57f06 100644 --- a/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue +++ b/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue @@ -304,7 +304,7 @@ function onClickOpenDialog() { id.value = informaData.value.id; age.value = calculateAge(informaData.value.birthDate); formData.citizenId = informaData.value.citizenId; - formData.prefix = informaData.value.prefixMain; + formData.prefix = informaData.value.prefix; formData.rank = informaData.value.rank; formData.firstName = informaData.value.firstName; formData.lastName = informaData.value.lastName; @@ -590,6 +590,7 @@ onMounted(() => {
{ :class="props.row.isEntry ? 'text-grey' : ''" >
- {{ col.value }} + {{ col.value ? col.value : "-" }}
From 72cbe6a8dc248a606b102e8a06f7ddcfc8a10dcd Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Fri, 12 Jun 2026 17:00:09 +0700 Subject: [PATCH 06/44] refactor(registry): itemsMenu RETIRE_MILITARY only SYS_PLACEMENT_OTHER --- src/modules/04_registryPerson/views/detailView.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/04_registryPerson/views/detailView.vue b/src/modules/04_registryPerson/views/detailView.vue index 8a779e0a9..1318ed468 100644 --- a/src/modules/04_registryPerson/views/detailView.vue +++ b/src/modules/04_registryPerson/views/detailView.vue @@ -121,7 +121,8 @@ const itemsMenu = computed(() => { if ( leaveType.value === "DISCIPLINE_TEMP_SUSPEND" || leaveType.value === "RETIRE_RESIGN" || - leaveType.value === "DISCIPLINE_SUSPEND" + leaveType.value === "DISCIPLINE_SUSPEND" || + leaveType.value === "RETIRE_MILITARY" ) { return ( baseItemsMenu.value?.filter( @@ -857,7 +858,7 @@ onMounted(async () => { ])) || leaveType === 'DISCIPLINE_TEMP_SUSPEND' || leaveType === 'RETIRE_RESIGN' || - leaveType === 'DISCIPLINE_SUSPEND' || + leaveType === 'DISCIPLINE_SUSPEND' || leaveType === 'RETIRE_MILITARY' " size="md" From 06ddc1c970450249212e37edee49492a7e45e90e Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Tue, 16 Jun 2026 10:43:31 +0700 Subject: [PATCH 07/44] refactor(org): add ROOT_CODE and CHILD_CODE fields for org hierarchy --- .../components/DialogFormAgency.vue | 107 ++++++++++++++++-- .../components/DialogStructureDetail.vue | 45 ++++++++ .../02_organization/interface/index/Main.ts | 5 + 3 files changed, 145 insertions(+), 12 deletions(-) diff --git a/src/modules/02_organization/components/DialogFormAgency.vue b/src/modules/02_organization/components/DialogFormAgency.vue index 32873fc17..72b3d228c 100644 --- a/src/modules/02_organization/components/DialogFormAgency.vue +++ b/src/modules/02_organization/components/DialogFormAgency.vue @@ -89,6 +89,11 @@ const formData = reactive({ DIVISION_CODE: "", SECTION_CODE: "", JOB_CODE: "", + ROOT_CODE: "", + CHILD1_CODE: "", + CHILD2_CODE: "", + CHILD3_CODE: "", + CHILD4_CODE: "", }); /** @@ -160,6 +165,11 @@ function onSubmit() { DIVISION_CODE: formData.DIVISION_CODE, SECTION_CODE: formData.SECTION_CODE, JOB_CODE: formData.JOB_CODE, + ROOT_CODE: formData.ROOT_CODE, + CHILD1_CODE: formData.CHILD1_CODE, + CHILD2_CODE: formData.CHILD2_CODE, + CHILD3_CODE: formData.CHILD3_CODE, + CHILD4_CODE: formData.CHILD4_CODE, }; // เพิ่มข้อมูล @@ -189,18 +199,20 @@ function onSubmit() { body ) .then(async () => { - await props.fetchDataTree(store.draftId); - await props.edit?.( - props.dataNode?.orgTreeId, - type, - body, - props.dataNode?.orgRootCode - ); - await props.fetchDataTable( - props?.dataNode?.orgTreeId, - props?.dataNode?.orgLevel, - false - ); + await Promise.all([ + await props.fetchDataTree(store.draftId), + await props.edit?.( + props.dataNode?.orgTreeId, + type, + body, + props.dataNode?.orgRootCode + ), + await props.fetchDataTable( + props?.dataNode?.orgTreeId, + props?.dataNode?.orgLevel, + false + ), + ]); await success($q, "บันทึกข้อมูลสำเร็จ"); closeClear(); }) @@ -231,6 +243,11 @@ function closeClear() { formData.isCommission = false; formData.isInformation = false; formData.misId = ""; + formData.ROOT_CODE = ""; + formData.CHILD1_CODE = ""; + formData.CHILD2_CODE = ""; + formData.CHILD3_CODE = ""; + formData.CHILD4_CODE = ""; formData.DEPARTMENT_CODE = ""; formData.DIVISION_CODE = ""; formData.SECTION_CODE = ""; @@ -456,6 +473,7 @@ watch( else { props.dataNode?.orgLevel === 1 && checkOfficer(); if (props.dataNode) { + console.log(props.dataNode); formData.orgName = props.dataNode.orgTreeName; formData.orgShortName = props.dataNode.orgTreeShortName; formData.orgCode = props.dataNode.orgTreeCode; @@ -474,6 +492,11 @@ watch( formData.DIVISION_CODE = props.dataNode.DIVISION_CODE; formData.SECTION_CODE = props.dataNode.SECTION_CODE; formData.JOB_CODE = props.dataNode.JOB_CODE; + formData.ROOT_CODE = props.dataNode.ROOT_CODE; + formData.CHILD1_CODE = props.dataNode.CHILD1_CODE; + formData.CHILD2_CODE = props.dataNode.CHILD2_CODE; + formData.CHILD3_CODE = props.dataNode.CHILD3_CODE; + formData.CHILD4_CODE = props.dataNode.CHILD4_CODE; orgLevelOption.value = props.dataNode.orgTreeRank === "DEPARTMENT" ? orgLevelOptionMain.value @@ -730,6 +753,66 @@ watch(
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
{ messageError($q, err); @@ -208,6 +218,41 @@ watch(
+
+
ROOT CODE
+
+

{{ formData.rootCode }}

+
+
+ +
+
CHILD1 CODE
+
+

{{ formData.child1Code }}

+
+
+ +
+
CHILD2 CODE
+
+

{{ formData.child2Code }}

+
+
+ +
+
CHILD3 CODE
+
+

{{ formData.child3Code }}

+
+
+ +
+
CHILD4 CODE
+
+

{{ formData.child4Code }}

+
+
+
หน้าที่ความรับผิดชอบ
diff --git a/src/modules/02_organization/interface/index/Main.ts b/src/modules/02_organization/interface/index/Main.ts index 8550b47e9..0103568c2 100644 --- a/src/modules/02_organization/interface/index/Main.ts +++ b/src/modules/02_organization/interface/index/Main.ts @@ -44,6 +44,11 @@ interface FormDataAgency { DIVISION_CODE: string; SECTION_CODE: string; JOB_CODE: string; + ROOT_CODE: string; + CHILD1_CODE: string; + CHILD2_CODE: string; + CHILD3_CODE: string; + CHILD4_CODE: string; } interface FormDataPosition { From df9a8408dd64fec048c9e04b4ba7a702b35614e9 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Tue, 16 Jun 2026 16:07:24 +0700 Subject: [PATCH 08/44] refactor(leave): add isAllDirector field to workflowCommanderOperate API --- .../05_Leave/Dialog/DialogAddCommander.vue | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/modules/09_leave/components/05_Leave/Dialog/DialogAddCommander.vue b/src/modules/09_leave/components/05_Leave/Dialog/DialogAddCommander.vue index e7697ce5b..fa61ca17f 100644 --- a/src/modules/09_leave/components/05_Leave/Dialog/DialogAddCommander.vue +++ b/src/modules/09_leave/components/05_Leave/Dialog/DialogAddCommander.vue @@ -35,6 +35,7 @@ const props = defineProps({ const pageId = ref(route.params.id as string); const keyword = ref(""); const isAct = ref(false); +const isAllDirector = ref(false); const total = ref(0); const totalList = ref(1); @@ -105,6 +106,7 @@ async function getData() { page: pagination.value.page, keyword: keyword.value, isAct: isAct.value, + isAllDirector: isAllDirector.value, keycloakId: props.keycloakUserId, type: props.profileType?.toLocaleLowerCase() === "officer" @@ -196,6 +198,7 @@ function closeDialog() { modal.value = false; rows.value = []; selected.value = []; + isAllDirector.value = false; } watch( @@ -231,19 +234,45 @@ watch(
-
+
+ + + + +
+ +
+ + หัวหน้าทั้งหน่วยงาน + - แสดงเฉพาะรักษาการแทน + แสดงเฉพาะรักษาการแทน - - -
+
{{ props.type == "APPROVER" From 004a0bcdb3c45f6c88abf4dc85941d9f17e81664 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Wed, 17 Jun 2026 15:26:47 +0700 Subject: [PATCH 09/44] refactor(registry): rules q-select rank --- .../detail/PersonalInformation/02_NameChangeHistory.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue b/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue index 05ee33629..0daa26c1f 100644 --- a/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue +++ b/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue @@ -661,7 +661,7 @@ onMounted(async () => { lazy-rules emit-value map-options - :rules="[(val:string) => !!val || `${'กรุณาเลือกยศ'}`]" + :rules="selection.includes('rank') ? [(val:string) => !!val || `${'กรุณาเลือกยศ'}`] : []" hide-bottom-space input-debounce="0" option-label="name" From 695c9ee271f1c5f9fd58f8b9ff0e67b232d2910d Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Wed, 17 Jun 2026 15:27:20 +0700 Subject: [PATCH 10/44] fix --- .../detail/PersonalInformation/02_NameChangeHistory.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue b/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue index 0daa26c1f..73bab2a70 100644 --- a/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue +++ b/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue @@ -661,7 +661,6 @@ onMounted(async () => { lazy-rules emit-value map-options - :rules="selection.includes('rank') ? [(val:string) => !!val || `${'กรุณาเลือกยศ'}`] : []" hide-bottom-space input-debounce="0" option-label="name" From 82411ce499269be556a0f74bb071ee6ffb6d9486 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Wed, 17 Jun 2026 16:50:59 +0700 Subject: [PATCH 11/44] fix --- .../components/detail/PersonalInformation/01_Profile.vue | 2 +- .../detail/PersonalInformation/02_NameChangeHistory.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue b/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue index d37b57f06..9df95660d 100644 --- a/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue +++ b/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue @@ -304,7 +304,7 @@ function onClickOpenDialog() { id.value = informaData.value.id; age.value = calculateAge(informaData.value.birthDate); formData.citizenId = informaData.value.citizenId; - formData.prefix = informaData.value.prefix; + formData.prefix = informaData.value.prefixMain; formData.rank = informaData.value.rank; formData.firstName = informaData.value.firstName; formData.lastName = informaData.value.lastName; diff --git a/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue b/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue index 73bab2a70..06b598ad8 100644 --- a/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue +++ b/src/modules/04_registryPerson/components/detail/PersonalInformation/02_NameChangeHistory.vue @@ -475,7 +475,7 @@ onMounted(async () => { icon="add" @click=" () => { - changeNameData.prefix = profileInfo?.prefix; + changeNameData.prefix = profileInfo?.prefixMain; changeNameData.firstName = profileInfo?.firstName; changeNameData.lastName = profileInfo?.lastName; changeNameData.rank = profileInfo?.rank; From c1d30de6d265f15f13168b71c6a270758432bb04 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Wed, 17 Jun 2026 17:30:23 +0700 Subject: [PATCH 12/44] fix --- .../components/detail/PersonalInformation/01_Profile.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue b/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue index 9df95660d..0b2bca785 100644 --- a/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue +++ b/src/modules/04_registryPerson/components/detail/PersonalInformation/01_Profile.vue @@ -96,11 +96,11 @@ const columnsHistory = ref([ a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), }, { - name: "prefix", + name: "prefixMain", align: "left", label: "คำนำหน้าชื่อ", sortable: true, - field: "prefix", + field: "prefixMain", headerStyle: "font-size: 14px", style: "font-size: 14px", sort: (a: string, b: string) => @@ -256,7 +256,7 @@ const columnsHistory = ref([ ]); const visibleColumnsHistory = ref([ "citizenId", - "prefix", + "prefixMain", "rank", "firstName", "lastName", From ee82e63e251aa94bf2f14ede3fbbaeaf97db5927 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Wed, 17 Jun 2026 18:11:30 +0700 Subject: [PATCH 13/44] refactor(position-temp): comment checkbox isSit --- src/modules/20_positionTemp/components/DialogSelectPerson.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/20_positionTemp/components/DialogSelectPerson.vue b/src/modules/20_positionTemp/components/DialogSelectPerson.vue index 6498094be..0c6ca2dac 100644 --- a/src/modules/20_positionTemp/components/DialogSelectPerson.vue +++ b/src/modules/20_positionTemp/components/DialogSelectPerson.vue @@ -706,7 +706,7 @@ watch(
-
+
From 20d80916cb59143c6458d04f2ad841ec8de32281 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Fri, 19 Jun 2026 15:45:19 +0700 Subject: [PATCH 14/44] refactor(command): validate commandCode === 'C-PM-47' --- src/modules/18_command/components/Step/1_Detail.vue | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/modules/18_command/components/Step/1_Detail.vue b/src/modules/18_command/components/Step/1_Detail.vue index 2a3f3b60f..fdbff84aa 100644 --- a/src/modules/18_command/components/Step/1_Detail.vue +++ b/src/modules/18_command/components/Step/1_Detail.vue @@ -113,8 +113,6 @@ const visibleColumns = ref>([ const modalAddOperator = ref(false); // แสดงเพิ่มรายชื่อลงนามในแนบท้ายคำสั่ง - - /** * ฟังก์ชันบันทึกข้อมูลรายละเอียดคำสั่ง * และกำหนด isChangeData เป็น false @@ -124,7 +122,8 @@ async function onSubmit() { if ( store.isIdofficer && formData.isBangkok !== "BANGKOK" && - formData.isBangkok !== "OFFICE" + formData.isBangkok !== "OFFICE" && + commandCode.value !== "C-PM-47" ) { dialogMessageNotify($q, "กรุณาเลือกคำสั่ง"); return; From 2dfe6172846436db0cbbd065617154f45e73490f Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Mon, 22 Jun 2026 09:28:50 +0700 Subject: [PATCH 15/44] refactor(command): readonly radio commandCode C-PM-47 --- .../18_command/components/Step/1_Detail.vue | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/modules/18_command/components/Step/1_Detail.vue b/src/modules/18_command/components/Step/1_Detail.vue index fdbff84aa..4ab0839a5 100644 --- a/src/modules/18_command/components/Step/1_Detail.vue +++ b/src/modules/18_command/components/Step/1_Detail.vue @@ -122,8 +122,7 @@ async function onSubmit() { if ( store.isIdofficer && formData.isBangkok !== "BANGKOK" && - formData.isBangkok !== "OFFICE" && - commandCode.value !== "C-PM-47" + formData.isBangkok !== "OFFICE" ) { dialogMessageNotify($q, "กรุณาเลือกคำสั่ง"); return; @@ -224,6 +223,8 @@ onMounted(async () => { formData.commandExcecuteDate = props.formCommandList.commandExcecuteDate; formData.isBangkok = !store.isIdofficer ? null + : props.formCommandList.commandCode === "C-PM-47" + ? "OFFICE" : props.formCommandList.isBangkok; commandCode.value = props.formCommandList.commandCode; const [volume, chapter] = props.formCommandList.commandNo.split("/"); @@ -485,12 +486,9 @@ onMounted(async () => { />
-
+
{ /> Date: Mon, 22 Jun 2026 10:45:45 +0700 Subject: [PATCH 16/44] refactor(command): default isBangkok to true when commandCode is 'C-PM-47' --- src/modules/18_command/components/Step/1_Detail.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/18_command/components/Step/1_Detail.vue b/src/modules/18_command/components/Step/1_Detail.vue index 4ab0839a5..0c3755cfb 100644 --- a/src/modules/18_command/components/Step/1_Detail.vue +++ b/src/modules/18_command/components/Step/1_Detail.vue @@ -224,7 +224,7 @@ onMounted(async () => { formData.isBangkok = !store.isIdofficer ? null : props.formCommandList.commandCode === "C-PM-47" - ? "OFFICE" + ? "BANGKOK" : props.formCommandList.isBangkok; commandCode.value = props.formCommandList.commandCode; const [volume, chapter] = props.formCommandList.commandNo.split("/"); From 76156d03e4f2c07433fe6eced18799499e7c1f67 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Mon, 22 Jun 2026 11:03:58 +0700 Subject: [PATCH 17/44] refactor(round-time): replace max-height DialogForm --- .../09_leave/components/01_RoundTime/DialogForm.vue | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/modules/09_leave/components/01_RoundTime/DialogForm.vue b/src/modules/09_leave/components/01_RoundTime/DialogForm.vue index c6883cb11..8eaf9c6b5 100644 --- a/src/modules/09_leave/components/01_RoundTime/DialogForm.vue +++ b/src/modules/09_leave/components/01_RoundTime/DialogForm.vue @@ -212,7 +212,7 @@ watch( :close="close" /> - +
@@ -362,6 +362,7 @@ watch(
+
@@ -513,6 +514,7 @@ watch(
+ + /> +
@@ -541,6 +544,7 @@ watch(
+
@@ -559,6 +563,7 @@ watch(
+
From 63f307c70d2c7bdd5199f1361b8b43aed686517b Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Tue, 23 Jun 2026 13:41:10 +0700 Subject: [PATCH 18/44] feat(timestamp-special): add MultipleApprove Special Lists --- src/api/09_leave/api.leave.ts | 1 + .../04_SpecialTime/DialogMultipleApprove.vue | 325 ++++++++++++++++++ src/modules/09_leave/interface/index/Main.ts | 2 + .../09_leave/views/04_SpecialTimeMain.vue | 26 +- 4 files changed, 353 insertions(+), 1 deletion(-) create mode 100644 src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue diff --git a/src/api/09_leave/api.leave.ts b/src/api/09_leave/api.leave.ts index d0229b204..3ea0ab8c3 100644 --- a/src/api/09_leave/api.leave.ts +++ b/src/api/09_leave/api.leave.ts @@ -25,6 +25,7 @@ export default { specialTime: () => `${leave}/admin/edit`, specialTimeApprove: (id: string) => `${leave}/admin/edit/approve/${id}`, specialTimeReject: (id: string) => `${leave}/admin/edit/reject/${id}`, + specialTimeApproveLists: `${leave}/admin/edit/approve-list`, /** รายการลา*/ leaveType: () => `${leave}/type`, diff --git a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue new file mode 100644 index 000000000..54484d7bd --- /dev/null +++ b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue @@ -0,0 +1,325 @@ + + + + + diff --git a/src/modules/09_leave/interface/index/Main.ts b/src/modules/09_leave/interface/index/Main.ts index 41766e80f..9381abe9c 100644 --- a/src/modules/09_leave/interface/index/Main.ts +++ b/src/modules/09_leave/interface/index/Main.ts @@ -68,6 +68,8 @@ interface DataSpecialTime { statusSort: number; timeAfternoon: string; timeMorning: string; + checkInStatusMain: string; + checkOutStatusMain: string; } export type { DataOption, diff --git a/src/modules/09_leave/views/04_SpecialTimeMain.vue b/src/modules/09_leave/views/04_SpecialTimeMain.vue index 1ea9ec44b..5c7890cdf 100644 --- a/src/modules/09_leave/views/04_SpecialTimeMain.vue +++ b/src/modules/09_leave/views/04_SpecialTimeMain.vue @@ -17,6 +17,7 @@ import type { import DialogReason from "@/components/Dialogs/PopupReason.vue"; import DialogApprove from "@/modules/09_leave/components/04_SpecialTime/DialogApprove.vue"; +import DialogMultipleApprove from "@/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue"; const $q = useQuasar(); // show dialog const mixin = useCounterMixin(); @@ -47,6 +48,7 @@ const name = ref(""); const id = ref(""); const dateDialog = ref(""); const dateFixDialog = ref(""); +const modalMultiple = ref(false); // ค้นหาในตาราง const filterKeyword = ref(""); @@ -54,7 +56,7 @@ const filterStatus = ref("PENDING"); const filterDate = ref<[Date, Date] | null>([new Date(), new Date()]); //วันที่ประกาศ const optionStatus = ref(store.optionStatusMain); const rows = ref([]); -const visibleColumns = ref([ +const visibleColumns = ref([ "no", "fullName", "createdAt", @@ -283,6 +285,20 @@ onMounted(async () => { From c49669021a3531e2ae5e82b9c02fcd0a90dd0074 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Tue, 23 Jun 2026 13:59:17 +0700 Subject: [PATCH 19/44] feat(notification): add delete notification feature --- .../04_SpecialTime/DialogMultipleApprove.vue | 1 + src/views/MainLayout.vue | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue index 54484d7bd..3c7051a75 100644 --- a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue +++ b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue @@ -105,6 +105,7 @@ function onSubmit() { dialogMessageNotify($q, "กรุณาเลือกอย่างน้อย 1 รายการ"); } else { dialogConfirm($q, async () => { + showLoader(); const payload = selected.value.map((e: DataSpecialTime) => ({ recId: e.id, checkInTime: e.checkInTime, diff --git a/src/views/MainLayout.vue b/src/views/MainLayout.vue index 33e733b0b..67af7375f 100644 --- a/src/views/MainLayout.vue +++ b/src/views/MainLayout.vue @@ -561,6 +561,26 @@ function getImg(id: string, pathName: string) { function onViewDetailNoti(url: string) { window.open(url, "_blank"); } + +function handleDeleteNotification() { + dialogRemove( + $q, + async () => { + try { + showLoader(); + await http.delete(config.API.msgNotificate); + await getDataNotification(1, "DEL"); + success($q, "ลบข้อมูลสำเร็จ"); + } catch (error) { + messageError($q, error); + } finally { + hideLoader(); + } + }, + "ยืนยันการลบข้อมูล", + "ต้องการยืนยันการลบรายการแจ้งเตือนทั้งหมดใช่หรือไม่?" + ); +} @@ -642,6 +662,17 @@ function onViewDetailNoti(url: string) {
ทั้งหมด {{ totalInbox }} ข้อความ
+ + ลบการแจ้งเตือนทั้งหมด +
Date: Tue, 23 Jun 2026 14:31:13 +0700 Subject: [PATCH 20/44] fix --- .../components/04_SpecialTime/DialogMultipleApprove.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue index 3c7051a75..b5f80c66e 100644 --- a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue +++ b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue @@ -164,8 +164,8 @@ watch(modal, async (val) => {
-
-
+
+
{
-
+
Date: Tue, 23 Jun 2026 14:33:12 +0700 Subject: [PATCH 21/44] Revert "fix" This reverts commit 1afe3936bd2fe07b738e1b269dfa03e65c94297c. --- .../components/04_SpecialTime/DialogMultipleApprove.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue index b5f80c66e..3c7051a75 100644 --- a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue +++ b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue @@ -164,8 +164,8 @@ watch(modal, async (val) => {
-
-
+
+
{
-
+
Date: Tue, 23 Jun 2026 14:40:50 +0700 Subject: [PATCH 22/44] fix --- .../components/04_SpecialTime/DialogMultipleApprove.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue index 3c7051a75..b5f80c66e 100644 --- a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue +++ b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue @@ -164,8 +164,8 @@ watch(modal, async (val) => {
-
-
+
+
{
-
+
Date: Tue, 23 Jun 2026 15:27:42 +0700 Subject: [PATCH 23/44] refactor(timestamp-special): update checkIn/checkOut payload and edit conditions --- .../04_SpecialTime/DialogApprove.vue | 4 +- .../04_SpecialTime/DialogMultipleApprove.vue | 42 +++++++++++++------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/modules/09_leave/components/04_SpecialTime/DialogApprove.vue b/src/modules/09_leave/components/04_SpecialTime/DialogApprove.vue index 2eb7b2cd0..af47e1dcf 100644 --- a/src/modules/09_leave/components/04_SpecialTime/DialogApprove.vue +++ b/src/modules/09_leave/components/04_SpecialTime/DialogApprove.vue @@ -96,8 +96,8 @@ watch( formData.checkOut = ""; formData.note = ""; } else if (props.editCheck === "PENDING") { - if (props.detailData) { - if (props.detailData.checkInEdit) { + if (props.detailData) { + if (props.detailData.checkInEdit && props.detailData.checkOutEdit) { formData.checkIn = props.detailData.startTimeMorning; formData.checkOut = props.detailData.endTimeAfternoon; } else if ( diff --git a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue index b5f80c66e..0caf9f339 100644 --- a/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue +++ b/src/modules/09_leave/components/04_SpecialTime/DialogMultipleApprove.vue @@ -106,14 +106,33 @@ function onSubmit() { } else { dialogConfirm($q, async () => { showLoader(); - const payload = selected.value.map((e: DataSpecialTime) => ({ - recId: e.id, - checkInTime: e.checkInTime, - checkOutTime: e.checkOutTime, - checkInStatus: e.checkInEdit ? "NORMAL" : e.checkInStatusMain, - checkOutStatus: e.checkOutEdit ? "NORMAL" : e.checkOutStatusMain, - reason: reason.value, - })); + const payload = selected.value.map((e: DataSpecialTime) => { + let checkInTime: string; + let checkOutTime: string; + + if (e.checkInEdit && e.checkOutEdit) { + checkInTime = e.startTimeMorning; + checkOutTime = e.endTimeAfternoon; + } else if (e.checkInEdit && !e.checkOutEdit) { + checkInTime = e.startTimeMorning; + checkOutTime = e.endTimeMorning; + } else if (!e.checkInEdit && e.checkOutEdit) { + checkInTime = e.startTimeAfternoon; + checkOutTime = e.endTimeAfternoon; + } else { + checkInTime = e.checkInTime; + checkOutTime = e.checkOutTime; + } + + return { + recId: e.id, + checkInTime, + checkOutTime, + checkInStatus: e.checkInEdit ? "NORMAL" : e.checkInStatusMain, + checkOutStatus: e.checkOutEdit ? "NORMAL" : e.checkOutStatusMain, + reason: reason.value, + }; + }); try { await http.put(config.API.specialTimeApproveLists, payload); @@ -236,7 +255,9 @@ watch(modal, async (val) => {
- + *หมายเหตุเลือกทั้งหมดเฉพาะรายการที่แสดงเท่านั้น
{ rows="3" />
- *หมายเหตุเลือกทั้งหมดเฉพาะรายการที่แสดงเท่านั้น From c0aa2856759f51ce7e89ba00e671ac9fcb500ee9 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Tue, 23 Jun 2026 15:54:08 +0700 Subject: [PATCH 24/44] refactor(notification): update icon and text display --- src/views/MainLayout.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/views/MainLayout.vue b/src/views/MainLayout.vue index 67af7375f..5c336f0f8 100644 --- a/src/views/MainLayout.vue +++ b/src/views/MainLayout.vue @@ -570,15 +570,15 @@ function handleDeleteNotification() { showLoader(); await http.delete(config.API.msgNotificate); await getDataNotification(1, "DEL"); - success($q, "ลบข้อมูลสำเร็จ"); + success($q, "รล้างการแจ้งสำเร็จ"); } catch (error) { messageError($q, error); } finally { hideLoader(); } }, - "ยืนยันการลบข้อมูล", - "ต้องการยืนยันการลบรายการแจ้งเตือนทั้งหมดใช่หรือไม่?" + "ยืนยันการล้างการแจ้งเตือนทั้งหมด", + "ต้องการยืนยันการล้างการแจ้งเตือนทั้งหมดทั้งหมดใช่หรือไม่?" ); } @@ -667,11 +667,11 @@ function handleDeleteNotification() { flat dense round - color="red" - icon="delete" + color="grey-7" + icon="mdi-trash-can-outline" @click.stop.prevent="handleDeleteNotification" > - ลบการแจ้งเตือนทั้งหมด + ล้างการแจ้งเตือนทั้งหมด
From 16c21467e49e48c820eefdd44701b7cafd16e397 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Tue, 23 Jun 2026 16:17:56 +0700 Subject: [PATCH 25/44] fix --- src/views/MainLayout.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/MainLayout.vue b/src/views/MainLayout.vue index 5c336f0f8..26b6cf9b1 100644 --- a/src/views/MainLayout.vue +++ b/src/views/MainLayout.vue @@ -578,7 +578,7 @@ function handleDeleteNotification() { } }, "ยืนยันการล้างการแจ้งเตือนทั้งหมด", - "ต้องการยืนยันการล้างการแจ้งเตือนทั้งหมดทั้งหมดใช่หรือไม่?" + "ต้องการยืนยันการล้างการแจ้งเตือนทั้งหมดใช่หรือไม่?" ); } From fd665b8b4d776e31ff8f4920139f583b562d2e09 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Thu, 25 Jun 2026 14:53:59 +0700 Subject: [PATCH 26/44] refactor(qualify): replace api CandidateExam --- src/api/recruiting/api.period-exam.ts | 5 +- .../components/TableCandidate.vue | 76 ++++++++++++------- src/views/MainLayout.vue | 2 +- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/src/api/recruiting/api.period-exam.ts b/src/api/recruiting/api.period-exam.ts index bf777e193..470303286 100644 --- a/src/api/recruiting/api.period-exam.ts +++ b/src/api/recruiting/api.period-exam.ts @@ -98,6 +98,9 @@ export default { `${env.API_URI}/placement/candidate/pdf/${candidateId}`, downloadCandidateExam: (id: string) => - `${periodExam}download/candidate-exam/${id}`, + `${exam_report}candidate/candidate-new/${id}`, downloadPassExam: (id: string) => `${periodExam}download/pass-exam/${id}`, + + downloadCandidatePassExam: (id: string) => + `${exam_report}candidate/pass-new/${id}`, }; diff --git a/src/modules/03_recruiting/components/TableCandidate.vue b/src/modules/03_recruiting/components/TableCandidate.vue index f5b1b2b21..5df6fa66c 100644 --- a/src/modules/03_recruiting/components/TableCandidate.vue +++ b/src/modules/03_recruiting/components/TableCandidate.vue @@ -363,37 +363,59 @@ async function downloadFileDashboard() { } async function clickPassExam() { - showLoader(); - await http - .get(config.API.downloadPassExam(examId.value)) - .then(async (res) => { - const data = res.data.result; - data.reportName = `Candidate_Dashboard_${dateToISO(new Date())}`; - await genReport(data, data.reportName, "pdf"); - }) - .catch((e) => { - messageError($q, e); - }) - .finally(() => { - hideLoader(); - }); + try { + showLoader(); + const res = await http.get( + config.API.downloadCandidatePassExam(examId.value), + { + headers: { + "Content-Type": "application/pdf", + Accept: "application/pdf", + }, + responseType: "blob", + } + ); + const url = window.URL.createObjectURL(new Blob([res.data])); + const link = document.createElement("a"); + link.href = url; + link.setAttribute( + "download", + `Candidate_Dashboard_${dateToISO(new Date())}` + ".pdf" + ); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); + } catch (error) { + messageError($q); + } finally { + hideLoader(); + } } async function clickCandidateList() { - showLoader(); - await http - .get(config.API.downloadCandidateExam(examId.value)) - .then(async (res) => { - const data = res.data.result; - data.reportName = `Candidate_Dashboard_${dateToISO(new Date())}`; - await genReport(data, data.reportName, "pdf"); - }) - .catch((e) => { - messageError($q, e); - }) - .finally(() => { - hideLoader(); + try { + showLoader(); + const res = await http.get(config.API.downloadCandidateExam(examId.value), { + headers: { + "Content-Type": "application/pdf", + Accept: "application/pdf", + }, + responseType: "blob", }); + const url = window.URL.createObjectURL(new Blob([res.data])); + const link = document.createElement("a"); + link.href = url; + link.setAttribute("download", "รายชื่อผู้มีสิทธิ์สอบ" + ".pdf"); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); + } catch (error) { + messageError($q); + } finally { + hideLoader(); + } } async function onCheckShowExaminfo() { diff --git a/src/views/MainLayout.vue b/src/views/MainLayout.vue index 26b6cf9b1..b37c2b183 100644 --- a/src/views/MainLayout.vue +++ b/src/views/MainLayout.vue @@ -570,7 +570,7 @@ function handleDeleteNotification() { showLoader(); await http.delete(config.API.msgNotificate); await getDataNotification(1, "DEL"); - success($q, "รล้างการแจ้งสำเร็จ"); + success($q, "ล้างการแจ้งสำเร็จ"); } catch (error) { messageError($q, error); } finally { From a9bef5bc42f418ebbcb2d8c47d2bc64638b84faf Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Thu, 25 Jun 2026 17:19:10 +0700 Subject: [PATCH 27/44] fix --- src/modules/03_recruiting/components/TableCandidate.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/03_recruiting/components/TableCandidate.vue b/src/modules/03_recruiting/components/TableCandidate.vue index 5df6fa66c..5ff53b467 100644 --- a/src/modules/03_recruiting/components/TableCandidate.vue +++ b/src/modules/03_recruiting/components/TableCandidate.vue @@ -387,7 +387,7 @@ async function clickPassExam() { document.body.removeChild(link); window.URL.revokeObjectURL(url); } catch (error) { - messageError($q); + messageError($q, error); } finally { hideLoader(); } @@ -412,7 +412,7 @@ async function clickCandidateList() { document.body.removeChild(link); window.URL.revokeObjectURL(url); } catch (error) { - messageError($q); + messageError($q, error); } finally { hideLoader(); } From 44e60d457fdfb920151d05b4f0afcceab1705165 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Thu, 25 Jun 2026 18:01:45 +0700 Subject: [PATCH 28/44] fix --- .../03_recruiting/components/TableCandidate.vue | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/modules/03_recruiting/components/TableCandidate.vue b/src/modules/03_recruiting/components/TableCandidate.vue index 5ff53b467..d725a3bc1 100644 --- a/src/modules/03_recruiting/components/TableCandidate.vue +++ b/src/modules/03_recruiting/components/TableCandidate.vue @@ -571,8 +571,20 @@ watch(
- - ดาวน์โหลดไฟล์ + + + {{ + attrs.rows.length !== 0 + ? "ดาวน์โหลดไฟล์" + : "ไม่มีข้อมูลผู้สอบคัดเลือก" + }}
diff --git a/src/modules/05_placement/components/PersonalList/DialogDetail.vue b/src/modules/05_placement/components/PersonalList/DialogDetail.vue index 13aa09aef..dff09ffdd 100644 --- a/src/modules/05_placement/components/PersonalList/DialogDetail.vue +++ b/src/modules/05_placement/components/PersonalList/DialogDetail.vue @@ -525,14 +525,14 @@ watch(props, () => {
ผลการสอบ
ลำดับที่สอบได้
-
จำนวนครั้งที่สมัครสอบ
+
{{ personalForm?.pass }}
{{ personalForm?.examNumber }}
-
{{ personalForm?.examRound }}
+
From 2355639f2552adec59ce4dae0909233791ce34be Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Mon, 29 Jun 2026 15:27:25 +0700 Subject: [PATCH 32/44] Revert "refactor: disable DonwloadCandidatePassExam" This reverts commit 6e8dbfc37556ff5c8c6bb2aa1e5728c1a7d90a9c. --- .../03_recruiting/components/TableCandidate.vue | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/modules/03_recruiting/components/TableCandidate.vue b/src/modules/03_recruiting/components/TableCandidate.vue index bd0dd72fe..d725a3bc1 100644 --- a/src/modules/03_recruiting/components/TableCandidate.vue +++ b/src/modules/03_recruiting/components/TableCandidate.vue @@ -1,5 +1,5 @@ + + + + diff --git a/src/modules/09_leave/interface/response/work.ts b/src/modules/09_leave/interface/response/work.ts index af055b794..d35a1a8d4 100644 --- a/src/modules/09_leave/interface/response/work.ts +++ b/src/modules/09_leave/interface/response/work.ts @@ -98,6 +98,26 @@ interface DataProcess { errorMessage: string | null; } +interface DataPendingJobs { + taskId: string; + keycloakUserId: string; + createdDate: string | Date; + processingDate: string | Date; + completedDate: string | Date; + status: string; + checkType: string; + checkInId: string; + errorMessage: string; + additionalData: string; + id: string; + createdAt: string | Date; + createdUserId: string; + lastUpdatedAt: string; + lastUpdateUserId: string; + createdFullName: string; + lastUpdateFullName: string; +} + export type { TableRows, DataResLog, @@ -105,4 +125,5 @@ export type { TableRowsTime, FormDetail, DataProcess, + DataPendingJobs, }; diff --git a/src/modules/09_leave/views/02_WorkingMain.vue b/src/modules/09_leave/views/02_WorkingMain.vue index fed615baf..87b81c060 100644 --- a/src/modules/09_leave/views/02_WorkingMain.vue +++ b/src/modules/09_leave/views/02_WorkingMain.vue @@ -9,6 +9,7 @@ import { useRoute } from "vue-router"; import Tab1 from "@/modules/09_leave/components/02_WorkList/Tab1.vue"; import Tab2 from "@/modules/09_leave/components/02_WorkList/Tab2.vue"; import Tab3 from "@/modules/09_leave/components/02_WorkList/Tab3_Processed_Late.vue"; +import Tab4_Pending from "@/modules/09_leave/components/02_WorkList/Tab4_Pending.vue"; const stores = useWorklistDataStore(); const route = useRoute(); @@ -21,6 +22,10 @@ const isPermissionTab3 = computed(() => { checkPermission(route)?.attrIsUpdate) ); }); + +const isPermissionTab4 = computed(() => { + return checkPermission(route)?.attrOwnership === "OWNER"; +});