263 lines
16 KiB
Markdown
263 lines
16 KiB
Markdown
# Plan + สรุปตาราง + Drop Script — Cleanup & Mock Seed `hrms_organization`
|
||
|
||
> **ไฟล์เดียวจบ:** Part A สรุปตาราง DB · Part B plan checklist (CP0-CP7) · Part C drop script SQL
|
||
> **Status:** ✅ CP0-CP6 done (drop 54 tables + seed mock org/pos/profile) · ⏳ CP7 (Keycloak) defer
|
||
> **Seed mock:** แยกที่ `src/seed/` → `npm run seed:run` (ไม่กระทบ `migration:run` หลัก)
|
||
> **วิธีใช้:** เช็ค `- [x]` ทีละขั้น, ทุก CP destructive ต้องแจ้ง user ก่อน + รอยืนยัน (DB test `192.168.1.68` เท่านั้น)
|
||
|
||
---
|
||
|
||
# Part A — สรุปตาราง DB
|
||
|
||
| รายการ | ค่า |
|
||
|---|---|
|
||
| Database | `hrms_organization` (MySQL 8.4.6) |
|
||
| Host | test `192.168.1.68` / prod `192.168.1.63` (ห้ามแตะ prod) |
|
||
| รวมตาราง | **211 → 157** (drop 54 แล้ว @ test) |
|
||
|
||
สถานะการใช้งาน:
|
||
|
||
| สถานะ | จำนวน | รายละเอียด |
|
||
|---|---:|---|
|
||
| ✅ ใช้งานจริง (เก็บไว้) | **147** | ข้อมูลธุรกิจหลัก + Master Data + ตารางเสริมที่มี controller |
|
||
| 🗑️ เตรียมลบ/ลบแล้ว | **54** | ดู §5 |
|
||
| ⚙️ ระบบ/ตัวเชื่อม | **10** | junction + system tables |
|
||
| **รวม** | **211** | |
|
||
|
||
## A.1 ข้อมูลหลัก
|
||
| กลุ่ม | ตัวอย่างตาราง |
|
||
|---|---|
|
||
| โครงสร้างองค์กร | `orgRoot`, `orgChild1`–`orgChild4`, `orgRevision` |
|
||
| ประวัติพนักงาน | `profile`, `profileEmployee`, `profileSalary`, `profile*` + `*History` |
|
||
| ตำแหน่ง/อัตรากำลัง | `position`, `posMaster`, `posMasterHistory`, `employeePosition` |
|
||
| คำสั่ง | `command`, `commandSend`, `commandRecive`, `commandOperator` |
|
||
| สิทธิ์/การเข้าถึง | `authRole`, `permissionOrg`, `permissionProfile`, `roleKeycloak` |
|
||
| อายุงาน/วิทยฐานะ | `tenure*` (5 ตาราง) |
|
||
|
||
## A.2 Master Data (ข้อมูลอ้างอิง — lookup, เปลี่ยนน้อย)
|
||
| กลุ่ม | ตาราง (จำนวนแถว exact) |
|
||
|---|---|
|
||
| ที่อยู่ | `province` (77), `district` (1,051), `subDistrict` (8,585), `province_master`, `district_master`, `subdistrict_master` |
|
||
| ประวัติบุคคล | `gender` (3), `bloodGroup` (4), `religion` (5), `relationship` (4), `prefixe` (5), `rank` (9), `educationLevel` (14) |
|
||
| ตำแหน่ง | `posType` (4), `posLevel` (15), `posDict` (910), `posExecutive` (40), `employeePosType`, `employeePosLevel`, `employeePosDict` |
|
||
| เครื่องราช | `insignia` (14), `insigniaType` (3) |
|
||
| คำสั่ง/การลา | `commandType` (47), `commandCode` (21), `commandSys` (12), `leaveType` (11) |
|
||
|
||
> 💡 ที่อยู่มี 2 ชุดซ้ำซ้อน: `province`/`district`/`subDistrict` (ใช้จริง) vs `*_master` (ชุดสำรอง) — ตรวจสอบว่าจำเป็นไหม
|
||
|
||
## A.3 ตารางคำนวณอัตโนมัติ (cron เขียนทุกคืน — ห้ามแก้ด้วยมือ)
|
||
| เวลา | ตาราง | สิ่งที่ทำ |
|
||
|---|---|---|
|
||
| 00:30 ทุกคืน | `profile`, `profileEmployee` | ประมวลผลคำสั่ง |
|
||
| 04:00 ทุกคืน | `registry`, `registryEmployee`, `tenure*` | **ล้างและสร้างใหม่** (full refresh) |
|
||
| 02:00 วันที่ 1 ต.ค. | `profile`, `profileEmployee`, `profileSalary`, `posMaster` | อัปเดตสถานะเกษียณ |
|
||
|
||
## A.4 ข้อมูลต้นทางจากระบบเดิม (MIS)
|
||
ชื่อตารางตัวใหญ่ (`HR_*`, `EMPLOYEE`, `Profile*`):
|
||
| สถานะ | จำนวน | รายละเอียด |
|
||
|---|---:|---|
|
||
| ใช้อยู่ (สำหรับนำเข้าข้อมูล) | 22 | `EMPLOYEE`, `OFFICER`, `Profile*` (ตัวใหญ่), `*Import` |
|
||
| ไม่ได้ใช้แล้ว (dead entity) | 25 | `HR_*` (24) + `IMPORT_ORG` — เคยมีข้อมูลจริง >1.4M แถว |
|
||
|
||
> ⚠️ ทั้ง 47 ตารางอยู่ในกลุ่มเตรียมลบ (§5) — **drop แล้ว @ test**
|
||
|
||
## A.5 กลุ่มที่เตรียมลบ/ลบแล้ว (54 ตาราง)
|
||
| กลุ่ม | จำนวน | ตัวอย่าง / เหตุผล |
|
||
|---|---:|---|
|
||
| ข้อมูลระบบเดิม (MIS) | 47 | `HR_*`, `EMPLOYEE`, `OFFICER`, `Profile*`, `*Import`, `IMPORT_ORG` |
|
||
| ตารางพักนำเข้า (ว่าง) | 2 | `HR_CHILDEN_EMPTEMP`, `HR_INSIGNIA_EMPTEMP` (0 แถว) |
|
||
| ตารางซ้ำ/ทดสอบ/เก่า | 5 | `Profiles`, `new_table`, `new_table_emp`, `entity_base`, `MET_PREFIX` |
|
||
|
||
หลังลบครบเหลือ **157 ตาราง**. Script อยู่ Part C.
|
||
|
||
> ⚠️ `profile*Employee*` (profileDisciplineEmployee, profileInformation, profileSalaryEmployee + *History) **ยังใช้** (มี controller: ProfileDisciplineEmployeeController, ProfileSalaryEmployeeController, ProfileEmployeeController) — อย่า drop
|
||
|
||
## A.6 ข้อควรระวัง
|
||
- ตารางเก็บ **ชื่อ + เลขบัตรประชาชน**: ~23 ตาราง (หลัก `profile`, `profileEmployee`, `registry`) — ข้อมูลส่วนบุคคล
|
||
- `migrations`, `typeorm_metadata` เป็นตารางระบบ **ห้ามลบเด็ดขาด**
|
||
- จำนวนแถวใน §A.1/A.4 เป็นค่าประมาณ (ยกเว้น §A.2 Master Data = exact)
|
||
|
||
## A.7 Seed / Mock data (สำหรับ dev/test)
|
||
mock data แยกที่ `src/seed/` (Node/TS) → `npm run seed:show` / `seed:run` / `seed:revert`
|
||
seed **แยกจาก migration หลัก** → `migration:run` ไม่เจอ seed → ไม่ทำลายข้อมูล prod. อ่าน `src/seed/README.md`
|
||
|
||
---
|
||
|
||
# Part B — Plan checklist (CP0-CP7)
|
||
|
||
## Context
|
||
DB `hrms_organization` (test) มีข้อมูลจริง + ตารางระบบเดิมไม่ได้ใช้ → ทำ environment สะอาด: ลดตารางเหลือใช้จริง + แทนข้อมูลจริงด้วย mock 30 คน + โครงสร้าง mock (revision 2569) + (defer) Keycloak
|
||
|
||
## Decisions
|
||
| | |
|
||
|---|---|
|
||
| Target DB | `192.168.1.68` (test) — **แจ้ง user ทุกครั้งก่อนจัดการ data** |
|
||
| Mock | 30 คน = 20 ข้าราชการ (Profile) + 10 ลูกจ้าง (ProfileEmployee) |
|
||
| citizenId | สุ่ม 13 หลักผ่าน checksum จริง + ห้ามตรงของเดิม (block list) |
|
||
| HR_* (24) | drop เลย (ไม่รอ .NET) |
|
||
| Keycloak | clear `keycloak` column ก่อนลบ profile → CP6 clear orphan → CP7 ผูก KC ใหม่ |
|
||
| CP7 password | `ddMMyyyy` พ.ศ. จาก birthDate mock |
|
||
|
||
## Checklist
|
||
|
||
### CP0 — Pre-flight ✅
|
||
- [x] หยุด service (กัน cron 00:30/03:00/04:00 ทับ) + ยืนยันต่อ DB `192.168.1.68` (clone: 211 tables, profile 20,501)
|
||
- [x] verify junction/child table names + NOT NULL columns ของ target tables
|
||
|
||
### เตรียมไฟล์ ✅
|
||
- [x] `src/seed/mockData.ts` (ชื่อไทย + genValidCitizenId checksum + deterministic UUID + genBirthDate)
|
||
- [x] 5 seed migrations (CP3-CP5c) + birthDate ใน CP5b; typecheck + test ผ่าน
|
||
|
||
### CP1 — Full Backup ✅ SKIP (user มี backup อยู่แล้ว)
|
||
|
||
### CP2 — Drop 54 unused tables (211 → 157) ✅ done
|
||
- [x] comment `ImportDataController.ts` @Route/@Security → `npm run build` → verify `/api/v1/org/upload/*` หาย
|
||
- [x] execute DROP 54 tables ใต้ `SET FOREIGN_KEY_CHECKS=0/1` (ดู Part C)
|
||
- [x] **verify**: tables = **157**; `migrations`/`typeorm_metadata` ยังอยู่
|
||
|
||
### CP3 — Seed orgRevision 2569 ✅ done
|
||
- [x] run `1782100000001-seed_org_revision_2569.ts` (ล้าง org/pos เดิม + INSERT "โครงสร้าง 2569")
|
||
- [x] **verify**: `orgRevision`=1, `orgRevisionIsCurrent`=1
|
||
|
||
### CP4 — Seed mock org structure ✅ done
|
||
- [x] run `1782100000002-seed_mock_org_structure.ts`
|
||
- [x] **verify**: สำนักA/หน่วยงานA/ฝ่ายA/กลุ่มงานA; FK chain ครบ
|
||
|
||
### CP5a — Seed mock positions ✅ done (seed ตรง — TypeORM INSERT quirk)
|
||
- [x] run `1782100000003-seed_mock_positions.ts` (20 posMaster + 10 employeePosMaster)
|
||
- [x] **verify**: posMaster=20, employeePosMaster=10; current_holderId NULL
|
||
|
||
### CP5b — Seed mock profiles + clear keycloak ✅ done
|
||
- [x] run `1782100000004-seed_mock_profiles.ts` (snapshot citizenId block list, clear keycloak, DELETE child + profile, INSERT 30 mock + birthDate)
|
||
- [x] **verify**: profile=20, profileEmployee=10; citizenId checksum + ไม่ตรง blocklist; birthDate ครบ
|
||
|
||
### CP5c — Link holders ✅ done
|
||
- [x] run `1782100000005-seed_link_holders.ts`
|
||
- [x] **verify**: posMaster holder=20 join profile ครบ; employeePosMaster holder=10
|
||
|
||
### CP6 — Clear Keycloak orphans ✅ SKIP (จัด KC ท้ายสุดพร้อม CP7)
|
||
|
||
### CP7 — ผูก Keycloak ให้ mock ⏳ defer
|
||
- [ ] เปลี่ยน `.env` `KC_SERVICE_ACCOUNT_*` ชี้ Keycloak **test**
|
||
- [ ] seed migration (`1782100000006-seed_keycloak_users.ts`) เรียก helper `src/keycloak/index.ts` (createUser/addUserRoles/getRoles/getUserByUsername)
|
||
- [ ] role `WHERE name='USER'` (แทน hardcode UUID `8a1a0dc9-...`)
|
||
- [ ] loop mock 30 คน: createUser(citizenId, password `ddMMyyyy` พ.ศ. จาก birthDate) + addUserRoles(USER) + เซ็ต `profile.keycloak` + junction
|
||
- [ ] **verify**: KC user = mock count; login mock ได้; super_admin ยังอยู่
|
||
|
||
## ไฟล์ที่สร้างแล้ว
|
||
**Seed (แยกจาก migration หลัก):** `src/seed/README.md`, `src/seed/data-source.ts`, `src/seed/mockData.ts`, `src/seed/migrations/178210000000{1..5}-seed_*.ts`
|
||
**npm scripts:** `npm run seed:show` / `seed:run` / `seed:revert` (ใช้ `src/seed/data-source.ts`)
|
||
**Code:** `src/controllers/ImportDataController.ts` (@Route/@Security comment — CP2)
|
||
|
||
## End-to-end verify (หลัง CP6)
|
||
1. `npm run migration:run` ผ่านไม่ error (migration หลัก) + `npm run seed:show` เห็น seed 5
|
||
2. tables = 157
|
||
3. profile=20, profileEmployee=10, orgRevision=1
|
||
4. citizenId ผ่าน checksum + ไม่ตรง blocklist
|
||
5. posMaster holder=20 join profile ครบ
|
||
6. cron 04:00 รอบแรก → registry/tenure rebuild จาก mock 30 คน
|
||
7. login admin ได้ (super_admin ยังอยู่)
|
||
|
||
## Risks
|
||
- migration + `SET FOREIGN_KEY_CHECKS` session-level ไม่ rollback → **backup เป็นหลัก ไม่พึ่ง down()**
|
||
- cron ทับ → หยุด service หรือทำ CP3-5c ในกรอบเวลาแคบ
|
||
- CP7 env ต้องชี้ KC test ก่อน
|
||
- TypeORM quirk: CP5a INSERT SELECT WHERE NOT EXISTS อาจไม่ execute ใน transaction → seed ตรงถ้า posMaster ว่าง
|
||
|
||
---
|
||
|
||
# Part C — Drop script SQL (CP2)
|
||
|
||
> ⚠️⚠️⚠️ DROP TABLE ลบถาวร ย้อนกลับไม่ได้. ทุก DROP comment (`--`) ไว้ — uncomment เฉพาะที่ตรวจสอบแล้ว.
|
||
> ก่อนรัน: (1) backup DB (2) comment `ImportDataController` + `npm run build` (3) รันบน test เท่านั้น (4) ปรึกษาทีม .NET เรื่อง HR_*
|
||
> 🚫 ห้าม DROP: `migrations`, `typeorm_metadata`
|
||
|
||
```sql
|
||
USE hrms_organization;
|
||
|
||
-- นับตารางก่อนรัน (ควรได้ 211)
|
||
SELECT COUNT(*) AS tables_before
|
||
FROM information_schema.tables
|
||
WHERE table_schema = 'hrms_organization' AND table_type = 'BASE TABLE';
|
||
|
||
SET FOREIGN_KEY_CHECKS = 0;
|
||
|
||
-- ============================================================
|
||
-- กลุ่ม 1 — MIS tables (47) — ⚠️ ImportDataController พังหลัง drop → comment controller ก่อน
|
||
-- ============================================================
|
||
-- -- บุคลากรต้นทาง (4)
|
||
-- DROP TABLE IF EXISTS EMPLOYEE;
|
||
-- DROP TABLE IF EXISTS EMPLOYEETEMP;
|
||
-- DROP TABLE IF EXISTS OFFICER;
|
||
-- DROP TABLE IF EXISTS positionOfficer;
|
||
-- -- Profile* staging ตัว P ใหญ่ (14)
|
||
-- DROP TABLE IF EXISTS ProfileAbilitys;
|
||
-- DROP TABLE IF EXISTS ProfileCertificates;
|
||
-- DROP TABLE IF EXISTS ProfileChangeNames;
|
||
-- DROP TABLE IF EXISTS ProfileChildrens;
|
||
-- DROP TABLE IF EXISTS ProfileDisciplines;
|
||
-- DROP TABLE IF EXISTS ProfileDutys;
|
||
-- DROP TABLE IF EXISTS ProfileEducations;
|
||
-- DROP TABLE IF EXISTS ProfileHonors;
|
||
-- DROP TABLE IF EXISTS ProfileInsignias;
|
||
-- DROP TABLE IF EXISTS ProfileLeaveSummary;
|
||
-- DROP TABLE IF EXISTS ProfileNopaids;
|
||
-- DROP TABLE IF EXISTS ProfileOthers;
|
||
-- DROP TABLE IF EXISTS ProfileSalaries;
|
||
-- DROP TABLE IF EXISTS ProfileTrainings;
|
||
-- -- Import master (4)
|
||
-- DROP TABLE IF EXISTS amphurImport;
|
||
-- DROP TABLE IF EXISTS educationMis;
|
||
-- DROP TABLE IF EXISTS provinceImport;
|
||
-- DROP TABLE IF EXISTS subDistrictImport;
|
||
-- -- HR_* dead entity (24) — ⛔ มีข้อมูลจริง >1.4M แถว ปรึกษาทีม .NET ก่อน!
|
||
-- DROP TABLE IF EXISTS HR_CHANGENAME;
|
||
-- DROP TABLE IF EXISTS HR_CHANGENAME_EMP;
|
||
-- DROP TABLE IF EXISTS HR_CHANGENAME_EMPTEMP;
|
||
-- DROP TABLE IF EXISTS HR_CHILDEN;
|
||
-- DROP TABLE IF EXISTS HR_CHILDEN_EMP;
|
||
-- DROP TABLE IF EXISTS HR_DISCIPLINE;
|
||
-- DROP TABLE IF EXISTS HR_DISCIPLINE_EMP;
|
||
-- DROP TABLE IF EXISTS HR_DISCIPLINE_EMPTEMP;
|
||
-- DROP TABLE IF EXISTS HR_EDUCATION;
|
||
-- DROP TABLE IF EXISTS HR_EDUCATION_EMP;
|
||
-- DROP TABLE IF EXISTS HR_EDUCATION_EMPTEMP;
|
||
-- DROP TABLE IF EXISTS HR_FUND_COURSE_CODE;
|
||
-- DROP TABLE IF EXISTS HR_INSIGNIA;
|
||
-- DROP TABLE IF EXISTS HR_INSIGNIA_EMP;
|
||
-- DROP TABLE IF EXISTS HR_MAJOR_CODE;
|
||
-- DROP TABLE IF EXISTS HR_PERSONAL_EMPTEMP_ADDRESS;
|
||
-- DROP TABLE IF EXISTS HR_PERSONAL_EMPTEMP_FAMILY;
|
||
-- DROP TABLE IF EXISTS HR_PERSONAL_EMP_ADDRESS;
|
||
-- DROP TABLE IF EXISTS HR_PERSONAL_EMP_FAMILY;
|
||
-- DROP TABLE IF EXISTS HR_PERSONAL_OFFICER_ADDRESS;
|
||
-- DROP TABLE IF EXISTS HR_PERSONAL_OFFICER_FAMILY;
|
||
-- DROP TABLE IF EXISTS HR_POSITION_EMPLOYEE;
|
||
-- DROP TABLE IF EXISTS HR_POSITION_EMPLOYEETEMP;
|
||
-- DROP TABLE IF EXISTS HR_POSITION_OFFICER;
|
||
-- -- IMPORT_ORG (0 แถว)
|
||
-- DROP TABLE IF EXISTS IMPORT_ORG;
|
||
|
||
-- ============================================================
|
||
-- กลุ่ม 2 — Import staging ไม่มี entity (2, 0 แถว)
|
||
-- ============================================================
|
||
-- DROP TABLE IF EXISTS HR_CHILDEN_EMPTEMP;
|
||
-- DROP TABLE IF EXISTS HR_INSIGNIA_EMPTEMP;
|
||
|
||
-- ============================================================
|
||
-- กลุ่ม 3 — ซ้ำ/ทดสอบ/เก่า (5)
|
||
-- ⚠️ profile*Employee* ยังใช้ (มี controller) — อย่า drop
|
||
-- ============================================================
|
||
-- DROP TABLE IF EXISTS Profiles;
|
||
-- DROP TABLE IF EXISTS new_table;
|
||
-- DROP TABLE IF EXISTS new_table_emp;
|
||
-- DROP TABLE IF EXISTS entity_base;
|
||
-- DROP TABLE IF EXISTS MET_PREFIX;
|
||
|
||
SET FOREIGN_KEY_CHECKS = 1;
|
||
|
||
-- นับตารางหลังรัน (drop ครบ 54 → เหลือ 157)
|
||
SELECT COUNT(*) AS tables_after
|
||
FROM information_schema.tables
|
||
WHERE table_schema = 'hrms_organization' AND table_type = 'BASE TABLE';
|
||
```
|