Project

General

Profile

Feature #26938 » spec.md

Parujee Pangsriuthai, 05/08/2026 11:14 AM

 
1
# ระบบกะงานหมุนเวียน (Work Shift Rotation System)
2

    
3
**วันที่จัดทำ:** 8 พฤษภาคม 2026  
4
**สถานะ:** Spec ฉบับรวม (ระบบเดิม + Database Design + Logic + Export Excel)  
5
**Scope:** Master Setup + Pattern + Export Excel เท่านั้น (ไม่รวม Calendar View / Override / วันหยุด)
6

    
7
---
8

    
9
## 1. ภาพรวมระบบเดิม (As-Is)
10

    
11
### 1.1 ระบบกะงานเดิม
12

    
13
ระบบเดิมมีแค่ **กะงานแบบตายตัว** (Fixed Shift) โดย:
14
- มีตาราง `ms_work_shift` เก็บข้อมูลกะ (ชื่อกะ + เวลาเริ่ม/สิ้นสุด)
15
- พนักงานแต่ละคนถูก map กับ `work_shift_id` ตัวเดียว
16
- ระบบแสดงกะของพนักงานจาก `work_shift_id` ตรงๆ ไม่มีการหมุน
17

    
18
### 1.2 ข้อจำกัดของระบบเดิม
19

    
20
- ไม่รองรับกะหมุนเวียน (Rotating Shift)
21
- ไม่สามารถแสดงได้ว่า "วันนี้พนักงานคนนี้ทำกะอะไรจริงๆ"
22
- ไม่รองรับการแบ่งกลุ่มพนักงานตามความสามารถในการทำกะ
23
- ไม่มีการ Export ตารางกะเป็น Excel
24

    
25
---
26

    
27
## 2. Requirement ใหม่: ระบบกะหมุนเวียน
28

    
29
### 2.1 การแบ่งกลุ่มพนักงาน (Work Group)
30

    
31
พนักงาน (ช่าง) ถูกแบ่งเป็น **6 กลุ่ม** ตามความสามารถ:
32

    
33
| กลุ่ม | ความสามารถ | ลักษณะการทำงาน |
34
|---|---|---|
35
| **C** | ทำได้แค่กะปกติ (จันทร์-ศุกร์) | กะปกติตลอด **ไม่หมุน** |
36
| **A** | ทำได้กะเช้า+บ่าย | หมุนสลับกับ B ทุกสัปดาห์ |
37
| **B** | ทำได้กะเช้า+บ่าย | หมุนสลับกับ A ทุกสัปดาห์ |
38
| **X** | ทำได้ทุกกะ (เช้า/บ่าย/ดึก) | หมุนสลับกับ Y, Z ทุกสัปดาห์ |
39
| **Y** | ทำได้ทุกกะ (เช้า/บ่าย/ดึก) | หมุนสลับกับ X, Z ทุกสัปดาห์ |
40
| **Z** | ทำได้ทุกกะ (เช้า/บ่าย/ดึก) | หมุนสลับกับ X, Y ทุกสัปดาห์ |
41

    
42
### 2.2 กะเวลา (Shift)
43

    
44
| shift_code | shift_name | start_time | end_time | หมายเหตุ |
45
|---|---|---|---|---|
46
| NORMAL | ปกติ | 08:00 | 17:00 | กลุ่ม C ทำงานปกติ จันทร์-ศุกร์ |
47
| MORNING | เช้า | 06:00 | 14:30 | 8.5 ชม. |
48
| AFTERNOON | บ่าย | 14:30 | 23:00 | 8.5 ชม. |
49
| NIGHT | ดึก | 23:00 | 06:00 | 7 ชม. ข้ามวัน |
50

    
51
### 2.3 ตารางการหมุน (Rotation Pattern) — รอบ 6 สัปดาห์
52

    
53
| สัปดาห์ | กะปกติ | กะเช้า | กะบ่าย | กะดึก |
54
|---|---|---|---|---|
55
| 1 | C | A + X | B + Y | Z |
56
| 2 | C | B + Y | A + Z | X |
57
| 3 | C | A + Z | B + X | Y |
58
| 4 | C | B + X | A + Y | Z |
59
| 5 | C | A + Y | B + Z | X |
60
| 6 | C | B + Z | A + X | Y |
61

    
62
**วิธีอ่าน:** สัปดาห์ที่ 1 → กลุ่ม A และกลุ่ม X ทำกะเช้า, กลุ่ม B และกลุ่ม Y ทำกะบ่าย, กลุ่ม Z ทำกะดึก  
63
หลังจบสัปดาห์ที่ 6 จะวนกลับไปเริ่มสัปดาห์ที่ 1 ใหม่
64

    
65
**หลักการสำคัญ:** ในฐานข้อมูล **ไม่เก็บ AX, BY, AZ เป็น string รวม** แต่แยกเป็นราย group (A และ X เป็น 2 rows) แล้ว aggregate ตอนแสดงผล
66

    
67
---
68

    
69
## 3. Database Design
70

    
71
### 3.1 ตาราง ms_shift — Master กะเวลา
72

    
73
```sql
74
CREATE TABLE public.ms_shift (
75
    id uuid DEFAULT gen_random_uuid() NOT NULL,
76
    shift_code varchar(20) NOT NULL,
77
    shift_name varchar(100) NOT NULL,
78
    start_ts time NULL,
79
    end_ts time NULL,
80
    seq int4 DEFAULT 0,
81
    is_active bool DEFAULT true NOT NULL,
82
    is_deleted bool DEFAULT false NOT NULL,
83
    created_date timestamptz DEFAULT now() NOT NULL,
84
    updated_date timestamptz DEFAULT now() NOT NULL,
85
    CONSTRAINT ms_shift_pk PRIMARY KEY (id)
86
);
87
```
88

    
89
### 3.2 ตาราง ms_work_group — Master กลุ่มพนักงาน
90

    
91
```sql
92
CREATE TABLE public.ms_work_group (
93
    id uuid DEFAULT gen_random_uuid() NOT NULL,
94
    group_code varchar(10) NOT NULL,
95
    group_name varchar(100) NOT NULL,
96
    is_active bool DEFAULT true NOT NULL,
97
    is_deleted bool DEFAULT false NOT NULL,
98
    created_date timestamptz DEFAULT now() NOT NULL,
99
    updated_date timestamptz DEFAULT now() NOT NULL,
100
    CONSTRAINT ms_work_group_pk PRIMARY KEY (id)
101
);
102
```
103

    
104
### 3.3 ตาราง ms_employee — เพิ่ม work_group_id
105

    
106
```sql
107
ALTER TABLE public.ms_employee ADD COLUMN work_group_id uuid;
108
ALTER TABLE public.ms_employee ADD CONSTRAINT fk_employee_group 
109
    FOREIGN KEY (work_group_id) REFERENCES public.ms_work_group(id);
110
```
111

    
112
### 3.4 ตาราง ms_shift_pattern — Pattern หลัก
113

    
114
```sql
115
CREATE TABLE public.ms_shift_pattern (
116
    id uuid DEFAULT gen_random_uuid() NOT NULL,
117
    pattern_code varchar(50) NOT NULL,
118
    pattern_name varchar(200) NOT NULL,
119
    cycle_days int4 NOT NULL,              -- จำนวนวันของ pattern ทั้งหมด (42)
120
    anchor_date date NOT NULL,             -- วันเริ่มรอบจริง
121
    is_active bool DEFAULT true NOT NULL,
122
    is_deleted bool DEFAULT false NOT NULL,
123
    created_date timestamptz DEFAULT now() NOT NULL,
124
    updated_date timestamptz DEFAULT now() NOT NULL,
125
    CONSTRAINT ms_shift_pattern_pk PRIMARY KEY (id)
126
);
127
```
128

    
129
### 3.5 ตาราง ms_shift_pattern_week_detail — รายละเอียด Pattern รายสัปดาห์
130

    
131
```sql
132
CREATE TABLE public.ms_shift_pattern_week_detail (
133
    id uuid DEFAULT gen_random_uuid() NOT NULL,
134
    pattern_id uuid NOT NULL,
135
    week_no int4 NOT NULL,
136
    shift_id uuid NOT NULL,
137
    work_group_id uuid NOT NULL,
138
    is_active bool DEFAULT true NOT NULL,
139
    is_deleted bool DEFAULT false NOT NULL,
140
    created_date timestamptz DEFAULT now() NOT NULL,
141
    updated_date timestamptz DEFAULT now() NOT NULL,
142
    CONSTRAINT ms_shift_pattern_week_detail_pk PRIMARY KEY (id),
143
    CONSTRAINT fk_week_detail_pattern FOREIGN KEY (pattern_id) REFERENCES public.ms_shift_pattern(id),
144
    CONSTRAINT fk_week_detail_shift FOREIGN KEY (shift_id) REFERENCES public.ms_shift(id),
145
    CONSTRAINT fk_week_detail_group FOREIGN KEY (work_group_id) REFERENCES public.ms_work_group(id)
146
);
147
```
148

    
149
**ตัวอย่างข้อมูล Week 1:**
150

    
151
| week_no | shift | group |
152
|---|---|---|
153
| 1 | NORMAL | C |
154
| 1 | MORNING | A |
155
| 1 | MORNING | X |
156
| 1 | AFTERNOON | B |
157
| 1 | AFTERNOON | Y |
158
| 1 | NIGHT | Z |
159

    
160
---
161

    
162
## 4. Logic การคำนวณรอบหมุน
163

    
164
### 4.1 คำนวณ week_no จากวันที่
165

    
166
```
167
week_no = floor(((work_date - anchor_date) % cycle_days) / 7) + 1
168
```
169

    
170
เมื่อ `cycle_days = 42` จะได้ week_no วิ่ง 1-6
171

    
172
### 4.2 ดึง pattern ของวันที่ที่ต้องการ
173

    
174
```sql
175
SELECT 
176
    d.week_no,
177
    s.shift_code,
178
    s.shift_name,
179
    s.seq,
180
    STRING_AGG(g.group_code, '' ORDER BY g.group_code) AS display_text
181
FROM ms_shift_pattern_week_detail d
182
JOIN ms_shift s ON s.id = d.shift_id
183
JOIN ms_work_group g ON g.id = d.work_group_id
184
WHERE d.pattern_id = :pattern_id
185
  AND d.week_no = :calculated_week_no
186
  AND d.is_active = true
187
  AND d.is_deleted = false
188
GROUP BY d.week_no, s.shift_code, s.shift_name, s.seq
189
ORDER BY s.seq;
190
```
191

    
192
---
193

    
194
## 5. Relationship Diagram
195

    
196
```
197
ms_shift 1 ──── * ms_shift_pattern_week_detail
198
ms_work_group 1 ──── * ms_shift_pattern_week_detail
199
ms_shift_pattern 1 ──── * ms_shift_pattern_week_detail
200

    
201
ms_work_group 1 ──── * ms_employee
202
```
203

    
204
---
205

    
206
## 6. Export Excel (ตารางกะเป็นสีๆ เหมือน EGM ของลูกค้า)
207

    
208
### 6.1 ภาพรวม
209

    
210
ฟีเจอร์ Export ตารางกะจากระบบเป็นไฟล์ Excel (.xlsx) โดยรูปแบบอ้างอิงจากไฟล์ `EGM_ตารางกะ ธ.ค.2025-มี.ค.2027.xlsx` ของลูกค้า
211

    
212
### 6.2 แหล่งข้อมูลสำหรับ Export
213

    
214
ข้อมูลที่ใช้ generate Excel มาจาก:
215

    
216
| ตาราง | ข้อมูลที่ดึง |
217
|---|---|
218
| `ms_shift_pattern` | anchor_date, cycle_days → คำนวณ week_no |
219
| `ms_shift_pattern_week_detail` | week_no, shift_id, work_group_id → pattern แต่ละสัปดาห์ |
220
| `ms_shift` | shift_code, shift_name, seq → ชื่อกะ + ลำดับ |
221
| `ms_work_group` | group_code → ชื่อกลุ่ม |
222

    
223
### 6.3 รูปแบบ Excel (อ้างอิงจากไฟล์ EGM — Sheet 103ki)
224

    
225
**Layout:** แต่ละเดือนใช้ 5 คอลัมน์ เรียงแนวนอน
226

    
227
```
228
│ Col 1-5 = เดือนที่ 1 │ Col 6-10 = เดือนที่ 2 │ Col 11-15 = เดือนที่ 3 │ ...
229
```
230

    
231
**โครงสร้างแต่ละกลุ่ม 5 คอลัมน์:**
232

    
233
| คอลัมน์ | เนื้อหา |
234
|---|---|
235
| 1 (วันที่) | เลขวันที่ (1, 2, 3, ..., 31) |
236
| 2 (ปกติ) | กลุ่มที่ทำกะปกติ (C) |
237
| 3 (เช้า) | กลุ่มที่ทำกะเช้า (เช่น BX, AY) |
238
| 4 (บ่าย) | กลุ่มที่ทำกะบ่าย (เช่น AY, BZ) |
239
| 5 (ดึก) | กลุ่มที่ทำกะดึก (เช่น Z, X, Y) |
240

    
241
**Header (Row 1):**
242

    
243
| Row | เนื้อหา |
244
|---|---|
245
| 1 | "ตารางกะการทำงานของพนักงาน บริษัท ไทยฮอนด้า จำกัด" (merge cells ทั้งแถว, พื้นน้ำเงินเข้ม, ตัวอักษรขาว Bold) |
246

    
247
**Data (Row 2+):** ตารางปฏิทินเลย — แต่ละเดือนใช้ 5 คอลัมน์เรียงแนวนอน
248

    
249
### 6.4 ตัวอย่างข้อมูลใน Cell
250

    
251
| วันที่ | ปกติ | เช้า | บ่าย | ดึก |
252
|---|---|---|---|---|
253
| 1 | C | BX | AY | Z |
254
| 2 | C | BX | AY | Z |
255
| 3 | C | BX | AY | Z |
256
| 4 | C | BX | AY | Z |
257
| 5 | C | AY | BZ | X |
258
| 6 | C | AY | BZ | X |
259
| 7 | C | AY | BZ | X |
260

    
261
### 6.5 สีพื้นหลัง — แยกตามสัปดาห์ในรอบหมุน (W1-W6)
262

    
263
สีใช้แยกตาม **สัปดาห์ในรอบหมุน** เพื่อให้เห็นชัดว่าวันไหนอยู่ในรอบเดียวกัน ทุก cell ในสัปดาห์เดียวกันจะใช้สีเดียวกันทั้งแถว
264

    
265
| สัปดาห์ | สีพื้นหลัง | Hex (ประมาณ) | ลักษณะ |
266
|---|---|---|---|
267
| W1 | ฟ้าอ่อน | #BDD7EE | ฟ้าพาสเทล |
268
| W2 | เขียวอ่อน | #C6EFCE | เขียวมิ้นท์ |
269
| W3 | เหลืองอ่อน | #FFFF99 | เหลืองพาสเทล |
270
| W4 | ม่วงอ่อน | #E2BFEE | ม่วงลาเวนเดอร์ |
271
| W5 | ชมพูอ่อน | #FFC7CE | ชมพูพาสเทล |
272
| W6 | ส้มอ่อน | #FFD966 | ส้มพาสเทล |
273

    
274
**หลักการ:** สีสลับทุก 7 วัน ทำให้แยกรอบหมุนได้ง่ายด้วยตา
275

    
276
> หมายเหตุ: สี Hex เป็นค่าประมาณ — ให้ Dev ดูจากไฟล์ EGM ต้นฉบับเป็นหลัก
277

    
278
### 6.6 Logic การ Generate Excel
279

    
280
```
281
1. ดึง ms_shift_pattern (anchor_date, cycle_days)
282
2. ดึง ms_shift_pattern_week_detail ทั้งหมดของ pattern นั้น
283
3. Aggregate group_code ตาม week_no + shift
284
4. สำหรับแต่ละวันใน date range ที่ต้องการ:
285
   a. คำนวณ week_no = floor(((วันนั้น - anchor_date) % cycle_days) / 7) + 1
286
   b. ดึง display_text ของ week_no นั้น (NORMAL, MORNING, AFTERNOON, NIGHT)
287
   c. เขียนลง cell พร้อมสีพื้นหลังตาม week_no
288
5. Save เป็นไฟล์ .xlsx
289
```
290

    
291
### 6.7 Date Range ของ Export
292

    
293
**Default:** export ตั้งแต่ anchor_date ไปจนจบปี (ของ anchor_date) แล้วบวกเพิ่มอีก 3 เดือน
294

    
295
```
296
start_date = anchor_date
297
end_date = สิ้นเดือนที่ 3 ของปีถัดไป (จากปีของ anchor_date)
298
```
299

    
300
**สูตร:**
301
```
302
anchor_year = ปีของ anchor_date
303
end_date = 31 มีนาคม ของ (anchor_year + 1)
304
```
305

    
306
**ตัวอย่าง:**
307
- anchor_date = 1 ธ.ค. 2025 → ปีของ anchor = 2025 → จบปี 2025 = 31 ธ.ค. 2025 → บวก 3 เดือน → **export ถึง 31 มี.ค. 2026**
308
- anchor_date = 1 มิ.ย. 2026 → ปีของ anchor = 2026 → จบปี 2026 = 31 ธ.ค. 2026 → บวก 3 เดือน → **export ถึง 31 มี.ค. 2027**
309

    
310
**เหตุผล:** แสดงกะงานที่เหลือของปีที่เป็น anchor date + ล่วงหน้าอีก 3 เดือนของปีถัดไป เพื่อวางแผนได้สะดวก
311

    
312
### 6.8 Export Options (UI)
313

    
314
| Option | Type | ค่าเริ่มต้น |
315
|---|---|---|
316
| Pattern | Dropdown | pattern ที่ active |
317
| วันเริ่มต้น | Date picker | anchor_date |
318
| วันสิ้นสุด | Date picker | 31 มี.ค. ของปีถัดจาก anchor_year |
319
| Production Line | Text | (ว่าง) |
320

    
321
### 6.9 API สำหรับ Export
322

    
323
```
324
POST /api/shift-pattern/export
325
Content-Type: application/json
326

    
327
{
328
  "pattern_id": "uuid",
329
  "start_date": "2025-12-01",
330
  "end_date": "2027-03-31",
331
  "production_line": "102KI"
332
}
333

    
334
Response:
335
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
336
Content-Disposition: attachment; filename="ตารางกะ_102KI_ธค2568-มีค2570.xlsx"
337
```
338

    
339
### 6.10 การจัดรูปแบบ Excel
340

    
341
- **Font:** ขนาด 10-11, Tahoma หรือ TH Sarabun New
342
- **Header:** Bold, พื้นเทาอ่อน
343
- **Alignment:** Center ทุก cell
344
- **Border:** เส้นบางรอบทุก cell
345
- **Column width:** auto-fit (~5-8 ต่อคอลัมน์)
346

    
347
---
348

    
349
## 7. สรุป Table ทั้งหมดที่ใช้
350

    
351
| Table | ประเภท | หน้าที่ |
352
|---|---|---|
353
| `ms_shift` | Master | เก็บ master กะเวลา (NORMAL, MORNING, AFTERNOON, NIGHT) |
354
| `ms_work_group` | Master | เก็บ master กลุ่ม A/B/C/X/Y/Z |
355
| `ms_employee` | Master | เก็บพนักงาน + ผูกกับ work_group_id |
356
| `ms_shift_pattern` | Master | เก็บหัว pattern (cycle_days, anchor_date) |
357
| `ms_shift_pattern_week_detail` | Master | เก็บรายละเอียด pattern รายสัปดาห์ แยก group เป็นราย row |
358

    
359
---
360

    
361
## 8. สรุปสิ่งที่ Dev ต้องทำ
362

    
363
### 8.1 Database
364

    
365
| # | งาน | รายละเอียด |
366
|---|---|---|
367
| 1 | สร้างตาราง ms_shift | Master กะเวลา (NORMAL, MORNING, AFTERNOON, NIGHT) |
368
| 2 | สร้างตาราง ms_work_group | Master กลุ่ม (A, B, C, X, Y, Z) |
369
| 3 | แก้ตาราง ms_employee | เพิ่ม work_group_id |
370
| 4 | สร้างตาราง ms_shift_pattern | Pattern หลัก (cycle_days, anchor_date) |
371
| 5 | สร้างตาราง ms_shift_pattern_week_detail | รายละเอียด pattern รายสัปดาห์ |
372
| 6 | Insert master data | กะเวลา + กลุ่ม + pattern 6 สัปดาห์ |
373

    
374
### 8.2 Backend / API
375

    
376
| # | งาน | รายละเอียด |
377
|---|---|---|
378
| 7 | Logic คำนวณ week_no | จาก anchor_date + cycle_days |
379
| 8 | API POST /shift-pattern/export | Export Excel |
380
| 9 | CRUD API สำหรับ ms_shift | จัดการ master กะเวลา |
381
| 10 | CRUD API สำหรับ ms_work_group | จัดการ master กลุ่ม |
382
| 11 | CRUD API สำหรับ ms_shift_pattern + detail | จัดการ pattern |
383

    
384
### 8.3 Frontend / UI
385

    
386
| # | งาน | รายละเอียด |
387
|---|---|---|
388
| 12 | หน้า Work Shift Setup | CRUD กะเวลา |
389
| 13 | หน้า Work Group Setup | CRUD กลุ่มพนักงาน |
390
| 14 | หน้า Shift Pattern Setup | Header + Detail grid (week_no × shift × group) |
391
| 15 | แก้หน้า Employee | เพิ่ม dropdown เลือก Work Group |
392
| 16 | Export Excel | ปุ่ม export + dialog เลือก options + generate .xlsx |
393

    
394
---
395

    
396
## 9. Key Decisions
397

    
398
| หัวข้อ | Decision |
399
|---|---|
400
| Pattern storage | เก็บรายสัปดาห์ (ไม่ใช่รายวัน) เพราะ 1 สัปดาห์ pattern เหมือนกันทุกวัน |
401
| Group storage | แยกเป็นราย row (ไม่เก็บ AX, BY เป็น string รวม) |
402
| Export สี | แยกสีตามสัปดาห์ในรอบหมุน (W1-W6 คนละสี) |
403
| Export format | อ้างอิง layout จากไฟล์ EGM ลูกค้า (เดือนเรียงแนวนอน) |
404
| Display aggregation | aggregate group เป็น AX/BY/AZ ตอนแสดงผลและ export |
405
| rotation_cycle_days | ตัดออก ใช้แค่ cycle_days ตัวเดียว |
406

    
407
---
408

    
409
## 10. แหล่งอ้างอิง
410

    
411
- ไฟล์ Excel ลูกค้า: `EGM_ตารางกะ ธ.ค.2025-มี.ค.2027.xlsx`
412
- ไฟล์รูป: `shift rotation.png`
413
- ไฟล์ Logic: `shift_rotation_logic_summary.md`
(2-2/4)