Service Report #008 In Review
Date: 2026-01-21
This report covers improvements to the Training Settings and Training Enrollment workflows based on MoM 2026-01-16.
- This MoM covers 2 tightly-coupled features: Training Settings (schedule/session management) and Training Enrollment (contractor→SO workflow). Changes in one often affect the other.
- The requirements from MoM were draft/verbal discussions, so implementation is a best-effort interpretation of what was discussed.
- This is a starting point — it uses real data (no mockup) and needs feedback from testers to refine behavior.
- Many conditions and edge cases are involved: form validation, partial approval, duplicate blocking, training status verification, worker eligibility rules.
- Testers should focus on the "What to Test" sections in each item below for structured verification.
Feature Overview
Features originate from MoM 2026-01-16 (Parent: #278)
1. Training Enrollment Form Validation
Source: Phase 0 Foundation Fix Thai Name: เพิ่มการตรวจสอบฟอร์มก่อนส่งรายชื่อผู้อบรม
Description: Added form validation to the Training Enrollment workflow. The "Submit Training List" command now requires:
- A training session to be selected
- At least one worker to be selected
The submit button is disabled when validation fails, with clear error messages showing what's missing.
Location: Training Enrollment Task > Document Form
Implementation
| Layer | File | Change |
|---|---|---|
| Backend | TrainingEnrollmentWorkflow.cs | Added ValidationRequired = true to SubmitTrainingList command |
| Frontend | training-enrollment-form.component.ts | Added formValid and validationErrors computed signals |
| Frontend | training-enrollment-form.component.ts | Added ReviewTaskService injection and validity sync effect |
| i18n | messages.json, messages.en.json | Added validation message keys |
Validation Rules
| Field | Rule | Error Message |
|---|---|---|
| Training Session | Must be selected | "รอบอบรม" / "Training Session" |
| Workers | At least 1 selected | "ผู้อบรม (อย่างน้อย 1 คน)" / "Workers (at least 1)" |
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Open Training Enrollment task with no session selected → Submit button disabled | ⌛ Pending |
| 2 | Select session but no workers → Submit button still disabled | ⌛ Pending |
| 3 | Select session AND at least 1 worker → Submit button enabled | ⌛ Pending |
| 4 | Verify validation error messages display correctly | ⌛ Pending |
2. Training Enrollment Auto-Navigation
Source: Phase 0 Foundation Fix Thai Name: เปิดเอกสารอัตโนมัติตาม Role
Description: When users open a Training Enrollment task, the system now automatically opens the correct document form based on their role instead of showing the document list.
Location: Training Enrollment Task > Document Container
Implementation
| Layer | File | Change |
|---|---|---|
| Backend | TrainingEnrollmentWorkflow.cs | Added DefaultForRoleIds to form permissions |
Auto-Navigation Configuration
| State | Default Form | Role |
|---|---|---|
| FillInTrainingList | TrainingEnrollmentForm | Contractor |
| ReviewBySafetyOfficer | TrainingEnrollmentForm | SafetyOfficer |
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Login as Contractor → Open Training Enrollment task → Form opens automatically | ⌛ Pending |
| 2 | Login as Safety Officer → Open task in Review state → Form opens automatically | ⌛ Pending |
| 3 | Verify document list is NOT shown first (form opens directly) | ⌛ Pending |
3. Form Data Persists After Saving
Issue: #289 Thai Name: หลังบันทึกแผนการอบรมใหม่ ข้อมูลในฟอร์มหายไป
จป แผนการอบรม: ทดสอบบันทึกแผนการอบรม เมื่อบันทึก แล้วจะข้อมูล clear ก่อนสร้างรอบ ต้องออกไปแล้วเข้าใหม่
Description: Fixed a bug where form data would clear after saving a new training schedule or session. The data now persists on screen, allowing users to immediately generate sessions from a newly created schedule.
Location: Tools > กำหนดค่า > Training Settings
Root Cause
When saving a new record, the service was incorrectly using its internal default values instead of the user's entered data when updating the form state after save.
Fix Applied
| Layer | File | Change |
|---|---|---|
| Frontend | training-setting.service.ts | Changed saveSchedule to preserve user's entered data after save |
| Frontend | training-setting.service.ts | Changed saveSession to preserve user's entered data after save |
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Create new training schedule → Fill all fields → Save → Data persists on screen | ⌛ Pending |
| 2 | After save, "สร้างรอบอบรม" button should be available (schedule has valid ID) | ⌛ Pending |
| 3 | Edit existing schedule → Save → Data still visible (unchanged behavior) | ⌛ Pending |
| 4 | Same behavior for training sessions (data persists after save) | ⌛ Pending |
4. Session Generation for "No Repeat" Schedules
Issue: #290 Thai Name: ปรับปรุงการสร้างรอบอบรมสำหรับแผน "ไม่ซ้ำ"
จป: การสร้างแผนการอบรมแบบไม่ซ้ำ ให้มีวันที่วันเดียว แต่สามารถกดสร้างรอบ ได้หลายครั้ง
Description: Two improvements to session generation for "No repeat" (ไม่ซ้ำ) training schedules.
Location: Tools > กำหนดค่า > Training Settings > Sessions
Part 1: Single Date Picker
Previously, the session generation dialog always showed a date range (From - To), even for "No repeat" schedules. This was confusing because:
- "No repeat" means ONE session on ONE specific date
- Showing a date range implied generating multiple sessions
Fix: Dialog now shows a single date picker when the schedule type is "No repeat".
| Recurrence Type | UI |
|---|---|
| ไม่ซ้ำ (No repeat) | Single date picker |
| รายสัปดาห์ (Weekly) | Date range (From - To) |
| รายเดือน (Monthly) | Date range (From - To) |
Part 2: Duplicate Warning Toast
When trying to generate a session that already exists (same date, time, and schedule), the system was showing a green success toast saying "สร้างรอบอบรมจำนวน 0 รายการ". This was misleading.
Fix: Now shows an orange warning toast explaining that no sessions were created because a duplicate exists.
| Sessions Created | Toast Type | Message |
|---|---|---|
| 1+ | Green (success) | สร้างรอบอบรมจำนวน X รายการ |
| 0 | Orange (warning) | ไม่มีรอบอบรมที่สร้างใหม่ (มีรอบอบรมในวันและเวลานี้อยู่แล้ว) |
Files Modified
| Layer | File | Change |
|---|---|---|
| Frontend | dialog-generate-sessions.component.ts | Conditional single date vs date range picker |
| Frontend | training-setting.component.ts | Show warning toast when 0 sessions created |
| Frontend | toast.service.ts | Added warning toast type |
| Frontend | toast.component.ts | Added amber styling for warning type |
| Frontend | ui.helper.ts | Added openWarningSnackBar() method |
| i18n | messages.json, messages.en.json | Added warning message key |
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Create "ไม่ซ้ำ" schedule → Click "สร้างรอบอบรม" → Single date picker shown | ⌛ Pending |
| 2 | Create "รายสัปดาห์" schedule → Click "สร้างรอบอบรม" → Date range shown | ⌛ Pending |
| 3 | Generate session for new date → Green success toast with count | ⌛ Pending |
| 4 | Generate session for existing date/time → Orange warning toast | ⌛ Pending |
5. Remove Quarterly Training Plan
Issue: #291 Thai Name: ลบตัวเลือกแผนการอบรมรายไตรมาส
จป: แผนการอบรม รายไตรมาส ให้ตัดออก จะไม่มีการใช้งาน
Description: Removed the "Quarterly" (รายไตรมาส) recurrence type from training schedules. This option was deemed unnecessary as users can achieve the same result using Monthly recurrence with specific dates.
Location: Tools > กำหนดค่า > Training Settings > Schedules > Recurrence Type
Before/After
| Before | After |
|---|---|
| 4 options: ไม่ซ้ำ, รายสัปดาห์, รายเดือน, รายไตรมาส | 3 options: ไม่ซ้ำ, รายสัปดาห์, รายเดือน |
| Quarterly-specific fields visible | Quarterly fields removed |
Files Modified
| Layer | File | Change |
|---|---|---|
| Backend | TrainingRecurrenceTypes.cs | Removed Quarterly = 3 enum value |
| Backend | TrainingRecurrencePattern.cs | Removed QuarterlyMonths and QuarterlyDayOfMonth properties |
| Backend | TrainingRecurrencePatternDto.cs | Removed quarterly properties |
| Backend | TrainingScheduleService.cs | Removed quarterly mapping |
| Backend | TrainingScheduleSeed.cs | Removed quarterly from seed data |
| Frontend | training-setting.contract.ts | Removed 'Quarterly' from type and helper |
| Frontend | training-schedule-form.component.ts | Removed Quarterly option from dropdown |
Migration Note
Before deployment, verify no existing data uses recurrence_type = 3:
SELECT COUNT(*) FROM training_schedules WHERE recurrence_type = 3;
If count > 0, migrate those records to Monthly recurrence before deployment.
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Open Training Schedule form → Verify only 3 recurrence options | ⌛ Pending |
| 2 | "รายไตรมาส" option is NOT visible in dropdown | ⌛ Pending |
| 3 | Create schedule with "รายสัปดาห์" → Save → Success | ⌛ Pending |
| 4 | Create schedule with "รายเดือน" → Save → Success | ⌛ Pending |
| 5 | Existing schedules (Weekly/Monthly/None) load correctly | ⌛ Pending |
6. Document View Gating for Commands
Issue: #281 Thai Name: ปิดปุ่มคำสั่งจนกว่าจะเปิดดูเอกสาร
จป: เมื่อเข้า task ที่ผู้รับเหมาส่งรายชื่อมา หากยังไม่กดเข้าไปดูรายชื่อ ไม่ควรเลือก flow action ใดได้ จนกว่าจะเข้าไป review รายชื่อ
Description: When a user opens a task, the workflow command buttons (อนุมัติ, ยกเลิก, etc.) are now hidden when viewing the document list. Commands only appear after the user clicks to open and view a specific document form. This ensures reviewers actually look at the submitted data before taking action.
Location: All workflow tasks > Toolbar > Command buttons
Behavior
| View State | Command Buttons |
|---|---|
| Document List | Hidden - User must open a document first |
| Document Form | Visible - User can now execute commands |
This feature was implemented as part of PR #303 (2026-01-20) for all workflow types. Training Enrollment automatically inherits this behavior.
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Login as Safety Officer → Open Training Enrollment task in "Review" state → See document list → Command buttons are HIDDEN | ✅ Passed |
| 2 | From document list → Click on "Training Enrollment Form" to open it → Command buttons APPEAR | ✅ Passed |
| 3 | Click "Back" to return to document list → Command buttons HIDE again | ✅ Passed |
| 4 | Same behavior applies to other workflows (Project Registration, JSA, Tool List, Work Permit) | ✅ Passed |
7. Block Second Training Enrollment
Issue: #280 Thai Name: ป้องกันการส่งรายชื่อผู้อบรมซ้ำขณะรออนุมัติ
ผู้รับเหมา: ส่งรายชื่ออบรมไปแล้วครั้ง หนึ่งแล้ว จป. ยังไม่อนุมัติ การจะส่งใหม่ ควรทำไม่ได้ ในรูป ชัยยุทธฯ อยู่ระหว่างรออนุมัติ ไม่ให้ควารให้ส่งครั้งที่ 2
Description: Contractors can no longer create a second Training Enrollment task while they have one pending approval. The system checks for existing active Training Enrollment tasks before allowing creation.
Location: งานของฉัน > สร้างงาน > ส่งรายชื่อผู้อบรม
Behavior
| Scenario | Result |
|---|---|
| No pending enrollment | Task created normally |
| Has pending enrollment (รอ จป. อนุมัติ) | Error: "คุณมีรายการส่งรายชื่อผู้อบรมที่รอการอนุมัติอยู่แล้ว กรุณารอให้ จป. อนุมัติก่อนส่งรายชื่อใหม่" |
| Previous enrollment approved/rejected/cancelled | Task created normally |
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Login as Contractor with NO pending enrollment → Create Training Enrollment → Success | ⌛ Pending |
| 2 | Login as Contractor with PENDING enrollment → Create Training Enrollment → Error message shown | ⌛ Pending |
| 3 | After SO approves/rejects enrollment → Contractor can create new enrollment | ⌛ Pending |
8. Partial Approval of Worker List
Issue: #282 Thai Name: อนุมัติรายชื่อผู้อบรมบางส่วน
จป: จากข้อที่ผ่านมา ให้เปิดให้ จป. เลือกรายชื่อได้ทั้งหมด หรือ เลือกรายบุคคล (partial approve) เพื่อให้อนุมัติรายชื่อ ส่วนผู้ที่ไม่ถูกเลือก ก็จะถูก 'ส่งกลับแก้ไข'โดยอัตโนมัติ
Description: Safety Officers can now partially approve worker lists. When reviewing a Training Enrollment task, SO can deselect workers who fail validation (missing documents, blacklisted, duplicate bookings, etc.). Only selected workers will be enrolled; unselected workers are automatically excluded without needing a separate "send back" action.
Location: Training Enrollment Task (Review state) > Worker List
Behavior
| Role | View State | Worker Selection |
|---|---|---|
| Contractor | Edit mode | Can select/deselect all eligible workers |
| Safety Officer | Review mode | Can deselect workers with issues (partial approval) |
Validation Checks (Auto-Deselect Triggers)
Workers are automatically blocked from selection if they have any of these issues:
| Issue | Icon | Description |
|---|---|---|
| Blacklisted | 🚫 | Worker is on the blacklist |
| Already Enrolled | ✓ | Worker already enrolled in this session |
| Booking Conflict | 📅 | Worker has conflicting enrollment on same day |
| Missing ID Card | ⚠️ | Worker has no ID card document uploaded |
| Missing Profile Photo | ⚠️ | Worker has no profile photo uploaded |
SO Workflow
- Open Training Enrollment task in "Review" state
- View worker list with validation status for each worker
- Workers with issues are shown with red background and cannot be selected
- Deselect any additional workers if needed
- Click "อนุมัติ" (Approve) → Only selected workers are enrolled
Files Modified
| Layer | File | Change |
|---|---|---|
| Backend | FormEditPermission.cs | Added CanModifySelection property |
| Backend | FormPermissions.cs | Added CanModifySelection to response |
| Backend | FormPermissionService.cs | Set CanModifySelection = true for SO in ReviewBySafetyOfficer state |
| Backend | TrainingEnrollmentWorkflow.cs | Added CanModifySelection to form permissions |
| Backend | TrainingApprovalService.cs | Filter to only approve selected workers |
| Frontend | form-permissions.model.ts | Added canModifySelection property |
| Frontend | training-enrollment-form.component.ts | Added canModifyWorkerSelection() computed |
| Frontend | training-enrollment-form.component.ts | Show checkboxes in review state for SO |
| Frontend | training-enrollment-form.component.ts | Updated validation for partial approval mode |
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Login as SO → Open Training Enrollment in Review state → Checkboxes visible for worker selection | ✅ Passed |
| 2 | Workers with validation issues (blacklist, missing docs) → Cannot be selected (checkbox disabled) | ✅ Passed |
| 3 | SO deselects some workers → Clicks Approve → Only selected workers are enrolled | ✅ Passed |
| 4 | Approve button disabled if no workers are selected | ✅ Passed |
| 5 | Validation error shows "ต้องเลือกผู้อบรมอย่างน้อย 1 คนเพื่ออนุมัติ" when none selected | ✅ Passed |
9. Inbox Notification Feature
Issue: #283 Thai Name: แจ้งเตือนจำนวน Task ใหม่ในส่วนต่าง ๆ
ทุกส่วน: ปัญหาคือเมื่อมี task เดินทางผ่านไปยังส่วนต่าง ๆ แล้วโดยเฉพาะกรณี เมื่อ จป. อนุมัติอบรม Task จะวิ่งไป งานที่เสร็จสิ้น โดยที่ทางผู้รับเหมา ไม่เห็นทันสังเกตุ
Description: A new Inbox notification system that alerts users when tasks move between workflow states. This works alongside email notifications and stores notification data locally in our database.
Location: Top navigation bar (bell icon) + งานของฉัน > กล่องข้อความ
Features
| Feature | Description |
|---|---|
| Navbar Bell Icon | Shows unread count badge in navigation bar |
| Inbox Dropdown | Quick preview of recent notifications from navbar |
| Full Inbox Page | Complete notification list with bulk actions |
| Mark Read/Unread | Toggle read status for individual or multiple notifications |
| Archive | Remove notifications from inbox |
| Click to Navigate | Click notification to go directly to the related task |
Notification Triggers
Notifications are created when tasks move to states requiring user action:
| Workflow | Trigger | Recipient |
|---|---|---|
| Training Enrollment | Task submitted for review | Safety Officer |
| Training Enrollment | Task approved/rejected | Contractor |
| Project Registration | Task submitted | Work Owner |
| All Workflows | Task assigned to user | Assignee |
Components
| Component | Location | Purpose |
|---|---|---|
NavbarInboxComponent | Navbar | Bell icon with dropdown |
InboxComponent | /inbox route | Full inbox page |
InboxService | Shared service | State management |
RelativeTimePipe | Shared pipe | "5 minutes ago" format |
Backend
| Endpoint | Method | Description |
|---|---|---|
/api/inbox/notifications | GET | List notifications with pagination |
/api/inbox/mark-read | POST | Mark notifications as read |
/api/inbox/mark-unread | POST | Mark notifications as unread |
/api/inbox/archive | POST | Archive notifications |
/api/inbox/unread-count | GET | Get unread count for badge |
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Login → See bell icon in navbar with unread count (if any) | ⌛ Pending |
| 2 | Click bell icon → Dropdown shows recent notifications | ⌛ Pending |
| 3 | Click "ดูทั้งหมด" → Navigate to full inbox page | ⌛ Pending |
| 4 | Click notification → Navigate to related task | ⌛ Pending |
| 5 | Select multiple → Mark as read → Badge count decreases | ⌛ Pending |
| 6 | Select multiple → Archive → Notifications removed from list | ⌛ Pending |
| 7 | As SO: Approve training enrollment → Contractor receives notification | ⌛ Pending |
| 8 | As Contractor: Submit training list → SO receives notification | ⌛ Pending |
10. Training Attendance Verification
Issue: #285 Thai Name: ตรวจสอบสถานะการอบรมของผู้ปฏิบัติงาน
ผู้รับเหมา: กรณีที่อนุมัติอบรมแล้ว ไม่ควรแจ้งว่าเป็นปัญหา หรือเมื่อผ่านการอบรมดังรูป (มีการตรวจสอบตามวันที่อบรมหรือไม่)
Description: Workers who have already passed training (TrainingStatus = Passed) are now shown with a green background instead of being marked as having validation issues. Previously, passed workers were shown with red background because the validation didn't consider their training status.
Location: Training Enrollment Task > Worker List
Behavior Change
| Training Status | Before | After |
|---|---|---|
| Passed | Red background, blocked from selection | Green background, selectable for refresher training |
| None/Expired | Requires document validation | Same - requires document validation |
Validation Rules by Training Status
| Training Status | ID Card Required | Profile Photo Required | Can Enroll |
|---|---|---|---|
| Passed | ❌ Not checked | ❌ Not checked | ✅ Yes (refresher training) |
| None | ✅ Required | ✅ Required | ✅ If documents valid |
| Expired | ✅ Required | ✅ Required | ✅ If documents valid |
| Pending | ✅ Required | ✅ Required | ✅ If documents valid |
Blocking Rules (Apply to ALL statuses)
| Condition | Result |
|---|---|
| Blacklisted | ❌ Always blocked (red background) |
| Already enrolled in THIS session | ❌ Always blocked (red background) |
Visual Changes
| Element | Passed Workers |
|---|---|
| Row background | Green (bg-green-50) |
| Validation icon | Shield with checkmark (verified_user) |
| Tooltip | "ผ่านการอบรมแล้ว - สามารถลงทะเบียนอบรมทบทวนได้" |
Files Modified
| Layer | File | Change |
|---|---|---|
| Backend | EnrollmentValidationDto.cs | Added TrainingStatus property to WorkerValidationDto |
| Backend | EnrollmentValidationService.cs | Populated TrainingStatus from worker entity |
| Frontend | training-enrollment-form.model.ts | Added trainingStatus to WorkerValidation interface |
| Frontend | training-enrollment-form.component.ts | Updated hasValidationIssues() to handle Passed status |
| Frontend | training-enrollment-form.component.ts | Added hasPassedTraining() for green styling |
| Frontend | training-enrollment-form.component.ts | Updated validation icon for passed workers |
| i18n | messages.json, messages.en.json | Added passedTraining translation key |
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Worker with Passed status, not enrolled → Green background, selectable | ✅ Passed |
| 2 | Worker with Passed status, already enrolled in THIS session → Red background, blocked | ✅ Passed |
| 3 | Worker with Passed status but blacklisted → Red background, blocked | ✅ Passed |
| 4 | Worker with Expired status, missing documents → Red background, blocked | ✅ Passed |
| 5 | Worker with None status, all documents present → No background, selectable | ✅ Passed |
| 6 | Hover over passed worker → Tooltip shows "ผ่านการอบรมแล้ว..." | ✅ Passed |
11. Worker Selection Dialog Improvements
Issue: #286 Thai Name: ปรับปรุง Dialog เลือกรายชื่อผู้อบรม ให้ค้นหา/กรองได้
ผู้ร้บเหมา: ตอนส่งรายชื่อ เนื่องจากในบางกรณีอาจมีพนักงานมากถึง 80 คน ควรมีการดำเนินการดังนี้
- เปลี่ยนเป็น เพิ่มรายชื่อ แทน checkbox เพื่อที่จะได้ตรวจสอบหรือคัดกรองได้
- ใน dialog ที่ popup ให้ search ได้ เรียงได้ ตามรายชื่อ หรือ อื่น ๆ
- Multi selection ได้
- Filter ได้ (default คือผู้ที่ยังไม่ได้ผ่านการอบรม / ยังไม่ด้ส่งรายชื่อ)
Description: The worker selection for Training Enrollment now uses a dedicated dialog with search, filter by training status, and multi-select capabilities. Workers who have already passed training or are pending approval are automatically disabled (grayed out, cannot be selected).
Location: Training Enrollment Task > Document Form > "จัดการรายชื่อ" button
Features
| Feature | Description |
|---|---|
| Search | Search by worker name or ID card number |
| Filter Chips | Filter by training status: ผ่าน, รอการอบรม, ยังไม่ได้อบรม, หมดอายุ, ไม่ผ่าน |
| Multi-Select | Select multiple workers with checkboxes |
| Select All | Select all eligible workers in current view |
| Auto-Disable | Workers with "ผ่าน" or "รอการอบรม" status are disabled |
Selection Eligibility
| Training Status | Can Select | Visual |
|---|---|---|
| ยังไม่ได้อบรม (Not trained) | ✅ Yes | Normal row |
| หมดอายุ (Expired) | ✅ Yes | Normal row |
| ไม่ผ่าน (Failed) | ✅ Yes | Normal row |
| ผ่าน (Passed) | ❌ No | Grayed out (opacity-50) |
| รอการอบรม (Pending) | ❌ No | Grayed out (opacity-50) |
| Blacklisted | ❌ No | Red badge, grayed out |
| Pending Approval | ❌ No | Orange badge, grayed out |
Default Behavior
- Dialog opens with "ยังไม่ได้อบรม" chip selected (most relevant workers shown first)
- Clicking the active chip again deselects it → shows all workers from all statuses
- "Select All" only selects eligible workers (skips disabled ones)
- Confirm button shows selected count: "ยืนยันรายชื่อ (N)"
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Click "จัดการรายชื่อ" → Dialog opens with "ยังไม่ได้อบรม" chip selected | ⌛ Pending |
| 2 | Type in search box → List filters by name or ID card | ⌛ Pending |
| 3 | Click "ผ่าน" chip → Shows passed workers, all checkboxes disabled | ⌛ Pending |
| 4 | Click "รอการอบรม" chip → Shows pending workers, all checkboxes disabled | ⌛ Pending |
| 5 | Click active chip again (deselect) → Shows all workers from all statuses | ⌛ Pending |
| 6 | "เลือกทั้งหมด" checkbox → Only selects eligible workers, skips disabled | ⌛ Pending |
| 7 | Blacklisted worker → Shows red badge, cannot select | ⌛ Pending |
| 8 | Click disabled worker row → Nothing happens | ⌛ Pending |
| 9 | Select workers → Click "ยืนยันรายชื่อ" → Workers added to form | ⌛ Pending |
12. Task Card Last Action Time
Issue: #284 Thai Name: แสดงเวลาตั้งแต่ last task action บน Task Card
ทุกส่วน: ตัวเลข 23 นาทีที่แล้ว เป็น ตั้งแต่ last action หรือ since create ควรเป็น since last task action
Description: The time displayed on task cards now shows the elapsed time since the last workflow action (state transition), rather than the task creation time. This gives users a clearer indication of how long a task has been sitting at its current state.
Location: งานของฉัน > Task Cards (all workflow types)
Behavior
| Before | After |
|---|---|
| Shows time since task creation | Shows time since last workflow action (state change) |
| Could show "5 days ago" for active tasks | Shows "23 minutes ago" when just acted upon |
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Open task list → Time shown is relative to last action, not creation | ⌛ Pending |
| 2 | Execute a workflow command → Time resets to "just now" | ⌛ Pending |
| 3 | Task sitting in current state for hours → Shows correct elapsed time | ⌛ Pending |
13. Worker Registry Improvements
Issue: #287 Thai Name: ปรับปรุงหน้าทะเบียนผู้ปฏิบัติงาน เพิ่มสถานะอบรมและการกรอง
จป และ ผู้รับเหมา: หน้าทะเบียนผู้ปฏิบัติงาน สถานะยังไม่สื่อ
- ผู้รับเหมา หากมีการส่งไปอบรมแล้ว หรือ รออบรม ควรมีสถานะเพิ่ม เนื่องจาก ผู้รับเหมาสามารถเข้ามาตรวจสอบภาพรวมที่ส่วนนี้ได้ด้วยความรวดเร็ว และรีบส่งอบรมด่วน
- จป: ไม่สนใจรายละเอียด สนใจเพียง ผ่านแล้ว หรือ ยังไม่อบรม หมดอายุ
- ผู้ปฏิบัติงานใหม่ ที่ ผู้รับเหมาพึ่งจะเพิ่มเข้าในระบบ จะต้องยังอยู่ที่บริษัท ส่วนอื่น ๆ (จป/sys admin) จะต้องยังไม่เห็นรายชื่อนั้น จนกว่าผู้รับเหมาจะมีการส่งไปอบรมครั้งแรก หลังจากนั้นจะอยู่ในระบบตลอด จนกว่าผู้รับเหมาจะลบออกจากระบบ
Description: Three improvements to the Worker Registry page:
- Clickable filter chips - Filter worker list by training status (ผ่าน, รอการอบรม, ยังไม่ได้อบรม, หมดอายุ, ไม่ผ่าน) with counts shown on each chip
- HasBeenEnrolled visibility - New workers are only visible to SO/Admin after their first training enrollment; contractors always see all their own workers
- Role-based chip visibility - SO/Admin don't see the "ยังไม่ได้อบรม" chip since those workers are hidden from them
Location: Tools > กำหนดค่า > ทะเบียนผู้ปฏิบัติงาน
Sub-Feature 1: Training Status Filter Chips
Clickable chips above the worker list for quick filtering by training status.
| Chip | Thai Label | Filters To |
|---|---|---|
| Passed | ผ่าน | Workers with trainingStatus = passed |
| Pending | รอการอบรม | Workers with trainingStatus = pending |
| None | ยังไม่ได้อบรม | Workers with trainingStatus = none |
| Expired | หมดอายุ | Workers with trainingStatus = expired |
| Failed | ไม่ผ่าน | Workers with trainingStatus = failed |
| Behavior | Description |
|---|---|
| Click chip | Filter list to show only workers with that status |
| Click active chip | Deselect filter, show all workers |
| Chip label | Shows count of workers in that status |
Sub-Feature 2: HasBeenEnrolled Visibility
| Role | Workers Visible |
|---|---|
| Contractor | All own workers (regardless of enrollment history) |
| Safety Officer | Only workers who have been enrolled at least once (HasBeenEnrolled = true) |
| Admin | Only workers who have been enrolled at least once (HasBeenEnrolled = true) |
The HasBeenEnrolled flag is set to true when a worker is first enrolled in a training session via the Training Enrollment workflow.
Sub-Feature 3: Role-Based Chip Visibility
| Role | Visible Chips |
|---|---|
| Contractor | All 5 chips (ผ่าน, รอการอบรม, ยังไม่ได้อบรม, หมดอายุ, ไม่ผ่าน) |
| Safety Officer | 4 chips (ผ่าน, รอการอบรม, หมดอายุ, ไม่ผ่าน) — "ยังไม่ได้อบรม" hidden |
| Admin | 4 chips (ผ่าน, รอการอบรม, หมดอายุ, ไม่ผ่าน) — "ยังไม่ได้อบรม" hidden |
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Login as Contractor → Open Worker Registry → See all 5 filter chips with counts | ⌛ Pending |
| 2 | Click "ผ่าน" chip → Only passed workers shown | ⌛ Pending |
| 3 | Click active chip again → All workers shown (deselect filter) | ⌛ Pending |
| 4 | Login as Safety Officer → Open Worker Registry → See only 4 chips (no "ยังไม่ได้อบรม") | ⌛ Pending |
| 5 | Login as Contractor → Add new worker → Worker visible in Contractor's list | ⌛ Pending |
| 6 | Login as SO → New worker NOT visible until first enrollment | ⌛ Pending |
| 7 | After training enrollment approved → Worker becomes visible to SO/Admin | ⌛ Pending |
14. Training Info Enrollment Shortcut
Issue: #288 Thai Name: กดลงทะเบียนอบรมจากหน้าข้อมูลการอบรมได้โดยตรง
ผู้รับเหมา: หน้าข้อมูลการอบรม หากพบการอบรมที่สนใจ ที่ยังว่างอยู่ ให้สามารถกดจากส่วนนั้น เพื่อไปสร้าง task ตามวันเวลาสนใจจะเข้าไปอบรมได้เลย
Description: Contractors can now create a Training Enrollment task directly from the Training Info page by clicking the "ลงทะเบียน" button next to any open session. After the task is created, the user is redirected to the Task Review page for the newly created task.
Location: เครื่องมือ > ข้อมูลการอบรม > ปุ่ม "ลงทะเบียน"
Behavior
| Condition | Register Button |
|---|---|
| Session status = Open, not expired | ✅ Visible (green "ลงทะเบียน" button) |
| Session status = Closed/Full | ❌ Not shown |
| Session expired | ❌ Not shown |
| Non-Contractor role | ❌ Column hidden |
| Has pending enrollment task | Button disabled during creation |
Flow
- Contractor opens Training Info page
- Finds an open session with available seats
- Clicks "ลงทะเบียน" button
- Progress bar appears (fixed below navbar)
- On success: green toast "สร้างงานส่งรายชื่อผู้อบรมสำเร็จ" + redirect to Task Review page
- On error: warning toast with error message
What to Test
| # | Test Case | Status |
|---|---|---|
| 1 | Login as Contractor → Open Training Info → See "ลงทะเบียน" button on Open sessions | ⌛ Pending |
| 2 | Click "ลงทะเบียน" → Progress bar appears below navbar | ⌛ Pending |
| 3 | After success → Green toast shows "สร้างงานส่งรายชื่อผู้อบรมสำเร็จ" | ⌛ Pending |
| 4 | After success → Redirected to Task Review page for the new task | ⌛ Pending |
| 5 | Login as Safety Officer → Open Training Info → "ลงทะเบียน" column NOT visible | ⌛ Pending |
| 6 | Expired session → "ลงทะเบียน" button NOT shown | ⌛ Pending |
Summary
| Phase | Description | Issues | Status |
|---|---|---|---|
| Phase 0 | Foundation Fixes (Validation + Auto-Navigation) | Internal | ✅ Complete |
| Phase 1 | Training Settings Bug Fixes | #289, #290, #291 | ✅ Complete |
| Phase 2 | Training Enrollment Workflow Improvements | #280-#288 | 🔍 #280, #281, #282, #285, #286, #287, #288 In Review |
| Phase 3 | Task Dashboard Improvements | #283, #284 | 🔍 #283, #284 In Review |