S1 — Legal Consultation System (LCS) — Data Dictionary (Target Design)¶
TARGET DESIGN
พจนานุกรมข้อมูลของ schema LCS ตาม schema.sql — ยังไม่ลงฐานข้อมูลจริง · ดู er_diagram.md · index.md
Convention ร่วมทุกตาราง business (ละไว้ในตารางย่อยด้านล่างเพื่อความกระชับ):
CreatedAt datetime2 · CreatedBy int FK→AppUser · UpdatedAt datetime2 · UpdatedBy int FK→AppUser · ตารางที่ soft-delete ได้มี IsDeleted bit
Append-only logs (AuditLog/PermissionLog/ImportError/*History/ConsultantRevocation) ไม่มี Updated*/IsDeleted
PII (🔒): CitizenId (เลขบัตร 13 หลัก), ชื่อ-ที่อยู่-เบอร์ของประชาชน/ที่ปรึกษา, ไฟล์แนบ → เข้ารหัส at-rest AES-256 [NFR-S02]
1. Lookups¶
Province — จังหวัด (77) [REQ-LCS-010]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| ProvinceId 🔑 | int IDENTITY | PK |
| Code | varchar(10) UNIQUE | รหัสย่อ ('BKK') |
| NameTh / NameEn | nvarchar | ชื่อจังหวัด |
| Region | nvarchar(50) | ภูมิภาค |
| IsCentral | bit | ส่วนกลาง/กทม. (1–3 คน/วัน) vs ภูมิภาค (1 คน/วัน) |
| Sequence / IsActive | int / bit | ลำดับ / ใช้งาน |
CaseType — ประเภทคดี (7) · Channel — ช่องทาง (8) · Specialty — ความเชี่ยวชาญ (7)¶
โครงสร้างเหมือนกัน: …Id 🔑 int, Code varchar UNIQUE, NameTh nvarchar, Sequence int, IsActive bit
Channel = WALKIN/HOTLINE/LINE/MOBILE/WEBBOARD/FACEBOOK/MSC/SERVICECTR [REQ-LCS-006]
ConsultationTopic — หัวข้อเรื่อง (self-ref) [REQ-LCS-011]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| TopicId 🔑 | int | PK |
| Code | varchar(40) | รหัส (optional) |
| NameTh | nvarchar(300) | ชื่อหัวข้อ |
| ParentTopicId | int FK→ConsultationTopic | NULL=หัวข้อหลัก, มีค่า=เรื่องย่อย (Top 5 drill-down) |
Role — บทบาท S1 (6) [REQ-LCS-005]¶
RoleId 🔑, Code varchar(30) UNIQUE (ADMIN/DIRECTOR/OFFICER_LEGAL/CONSULTANT/PUBLIC/AUDITOR), NameTh, Description
2. Identity / Auth (thin SSO mirror)¶
AppUser — ผู้ใช้งาน (mirror SSO, ไม่มี password) [REQ-LCS-005]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| AppUserId 🔑 | int | PK |
| Sub | varchar(128) UNIQUE | subject claim จาก JWT |
| Username | varchar(150) | อ้างอิงจาก SSO (ไม่เก็บรหัสผ่าน) |
| CitizenId 🔒 | varchar(13) | เลขบัตร (ThaiD) |
| FullName / Email / Phone | nvarchar/varchar | ข้อมูลติดต่อ |
| ProvinceId | int FK→Province | จังหวัดสังกัด (NULL=ส่วนกลาง เห็นทุกจังหวัด) |
| AuthSource | varchar(20) CHECK | SSO/THAID/AD/LOCAL |
| LastLoginAt / IsActive | datetime2 / bit |
[OPEN-AUTH]
ไม่มี PasswordHash/lockout — fallback user/password ทำที่ Keycloak · ถ้าลูกค้ายืนยันให้เก็บใน LCS → เพิ่ม PasswordHash/FailedLoginCount/LockedUntil + ตาราง LoginAttempt
RoleAssignment — การมอบบทบาท (mirror) [REQ-LCS-005]¶
RoleAssignmentId 🔑, AppUserId FK, RoleId FK, ProvinceId FK (scope), GrantedBy FK→AppUser, GrantedAt, RevokedAt, IsActive · UNIQUE(AppUserId, RoleId, ProvinceId)
3. Consultant Registry¶
ImportBatch — รอบนำเข้าข้อมูล (persistent) [REQ-LCS-003]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| ImportBatchId 🔑 | int | PK |
| Purpose | varchar(20) CHECK | CONSULTANT / ROSTER |
| FileName / FileType | nvarchar / varchar CHECK | ไฟล์ + xls/xlsx/csv |
| TotalRows / ValidCount / ErrorCount | int | สรุปผล validation |
| Status | varchar(20) CHECK | VALIDATING/VALIDATED/COMMITTED/FAILED |
| CommittedAt | datetime2 | เวลายืนยันนำเข้า |
รอบนำเข้าใหม่ → เริ่มวาระ 3 ปีใหม่ (REQ-001) และที่ปรึกษาที่ไม่อยู่ในรอบใหม่ → เพิกถอน (REQ-004)
ImportError — error ราย row (append-only) [REQ-LCS-003]¶
ImportErrorId 🔑 bigint, ImportBatchId FK, RowNumber int, ColumnName, Message, RawValue, CreatedAt
ConsultantApplication — คำขอลงทะเบียน + คุณสมบัติ + อนุมัติ [REQ-LCS-001]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| ApplicationId 🔑 | int | PK |
| ApplicationNo | varchar(30) UNIQUE | เลขคำขอ (REQ-2569-00214) |
| FullName / CitizenId 🔒 / Phone / Email | ข้อมูลผู้สมัคร | |
| Education / LicenseNo / ExperienceYears | nvarchar/int | วุฒิ / เลขใบอนุญาต / ปีประสบการณ์ |
| SourceImportBatchId | int FK→ImportBatch | ถ้านำเข้าจากไฟล์ = ถือว่าผ่านสอบ/สัมภาษณ์ |
| QualificationPassed / QualificationNote | bit / nvarchar | ผลตรวจคุณสมบัติ |
| Status | varchar(20) CHECK | PENDING_REVIEW/PENDING_APPROVAL/APPROVED/REJECTED |
| ReviewedBy / ReviewedAt | int FK / datetime2 | จนท.ทะเบียน |
| ApprovedBy / ApprovedAt | int FK / datetime2 | DIRECTOR |
| RejectReason | nvarchar(1000) | |
| ConsultantId | int FK→Consultant | ผูกเมื่ออนุมัติ |
Consultant — ที่ปรึกษากฎหมาย (registry) [REQ-LCS-001/002/004]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| ConsultantId 🔑 | int | PK |
| ConsultantCode | varchar(30) UNIQUE | LAW-2569-0001 |
| AppUserId | int FK→AppUser | self-service login (ThaiD) |
| FullName / CitizenId 🔒 / Phone / Email | ||
| Education / LicenseNo / ExperienceYears | ||
| Status | varchar(20) CHECK | PENDING/ACTIVE/SUSPENDED/EXPIRED/REVOKED/INACTIVE |
| BirthDate | date | ใช้ตรวจอายุครบ 75 → auto revoke |
| Rating / ClosedCaseCount | decimal(3,2) / int | denormalized (mockup rating/cases) |
| IsDeleted | bit | soft delete |
ConsultantSpecialty — junction (ConsultantId+SpecialtyId 🔑) · ConsultantProvince — junction (ConsultantId+ProvinceId 🔑)¶
normalize spec[] และ "1 คนหลายจังหวัด" [REQ-LCS-001]
ConsultantTerm — วาระ 3 ปี [REQ-LCS-001]¶
TermId 🔑, ConsultantId FK, TermNo int, StartDate, EndDate (=Start+3y), SourceImportBatchId FK, IsCurrent bit
ConsultantRevocation — การเพิกถอน (append-only) [REQ-LCS-004]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| RevocationId 🔑 | int | PK |
| ConsultantId | int FK | |
| Reason | varchar(20) CHECK | EXPIRED/AGE75/RESIGN/COMPLAINT/NOT_IN_IMPORT |
| ReasonNote | nvarchar(1000) | บังคับถ้าไม่มี auto-reason (REQ-005) |
| IsAuto | bit | TRUE=ระบบเพิกถอนอัตโนมัติ (อายุ 75) |
| RevokedBy / RevokedAt | int FK (NULL=ระบบ) / datetime2 |
4. Duty Roster & Attendance¶
DutyRoster — ตารางเวรรายเดือน (แผน) [REQ-LCS-009]¶
DutyRosterId 🔑, ProvinceId FK, YearBE int, Month tinyint CHECK 1..12, SourceImportBatchId FK, Status CHECK DRAFT/PUBLISHED · UNIQUE(ProvinceId, YearBE, Month)
DutySlot — ช่องเวรรายวัน (แผน) [REQ-LCS-009]¶
DutySlotId 🔑, DutyRosterId FK, DutyDate date, GenderReq CHECK M/F/ANY (กลางต้องมี ญ1+ช1), PlannedConsultantId FK→Consultant
ConsultantAvailability — แจ้งวันว่าง [REQ-LCS-009]¶
AvailabilityId 🔑, ConsultantId FK, AvailableDate date, Note · UNIQUE(ConsultantId, AvailableDate)
DutySession — ปฏิบัติงานจริง (ACTUAL — แหล่งค่าตอบแทน) [REQ-LCS-009/010]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| DutySessionId 🔑 | int | PK |
| DutySlotId | int FK→DutySlot | NULL=เพิ่มเฉพาะกิจ |
| ProvinceId / ConsultantId | int FK | ผู้ปฏิบัติจริง |
| DutyDate | date | |
| HoursServed | decimal(5,2) | ชั่วโมงจริง (≥8 → eligible) |
| IsReplacement | bit | มาแทนผู้อื่น |
| ReplacedConsultantId | int FK→Consultant | ผู้ที่ถูกแทน |
| CountsForStats | bit | ผู้มาแทนนับ ; ผู้ยกเลิกไม่นับ |
DutyCancellation — การยกเลิกเวร [REQ-LCS-009]¶
CancellationId 🔑, DutySlotId FK, ConsultantId FK (ผู้ยกเลิก), DutyDate, Reason nvarchar NOT NULL, IsUrgent bit, ReplacementConsultantId FK, CancelledAt
5. Consultation Requests¶
ConsultationRequest — คำขอรับคำปรึกษา [REQ-LCS-006/012]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| RequestId 🔑 | int | PK |
| ReferenceNo | varchar(30) UNIQUE | S1-2569-00432 — ใช้ public tracking |
| ChannelId | int FK→Channel | 1 ใน 8 ช่องทาง |
| RequesterName 🔒 / RequesterCitizenId 🔒 / RequesterPhone 🔒 | ข้อมูลประชาชน | |
| ProvinceId / CaseTypeId / TopicId | int FK | |
| Summary | nvarchar(2000) | เรื่อง/สรุป |
| ReceivedAt | datetime2 | เวลารับเรื่อง (SLA) |
| Status | varchar(30) CHECK | PENDING_ASSIGN→…→CLOSED (8 ค่า) |
| PublicStatus | varchar(30) | สถานะที่ประชาชนเห็น [TBD-012] |
| IsDeleted | bit |
RequestAssignment — มอบหมายงาน [REQ-LCS-006]¶
AssignmentId 🔑, RequestId FK, ConsultantId FK (หรือ) AssigneeUserId FK→AppUser, AssignedBy FK→AppUser, AssignedAt, IsCurrent bit, Note
ConsultationResult — บันทึกผล (versioned) [REQ-LCS-007]¶
ResultId 🔑, RequestId FK, ConsultantId FK, Version int, Facts/Detail/ClientNeed nvarchar(max), ConsultedAt (อาจย้อนหลัง), IsCurrent bit
QAReview — ตรวจคุณภาพ (ผลรวม) [REQ-LCS-007]¶
QAReviewId 🔑, RequestId FK, ResultId FK, ReviewerId FK→AppUser, Result CHECK PASS/FAIL, Score int CHECK 0..100, Note, ReviewedAt
QAReviewItem — ผล QA รายเกณฑ์ (5 เกณฑ์) [REQ-LCS-007]¶
QAReviewItemId 🔑, QAReviewId FK→QAReview, CriterionKey varchar(30) (c1..c5), CriterionLabel nvarchar(300) (denorm ณ เวลาตรวจ), Verdict CHECK PASS/FAIL/NA · UNIQUE(QAReviewId, CriterionKey)
รองรับ checklist Pass/Fail/N/A ในจอ
qa-pending; เกณฑ์เก็บเป็น data ปรับชุดได้ (SRS = ดุลพินิจ)
Escalation — ส่งต่อ Web Service [REQ-LCS-008]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| EscalationId 🔑 | int | PK |
| RequestId | int FK | |
| TargetSystem | varchar(30) | เริ่ม OCIPA [TBD-008] |
| TargetOrgName | nvarchar(300) | หน่วยงานปลายทาง |
| Reason / Priority | nvarchar / varchar CHECK NORMAL/URGENT | |
| Status | varchar(15) CHECK | PENDING/ACCEPTED/REJECTED/FAILED |
| ExternalRefId | varchar(100) | Reference ID ปลายทาง |
| RequestPayload / ResponsePayload | nvarchar(max) | audit ข้อมูลรับ-ส่ง |
| SentBy / SentAt / RespondedAt |
RequestStatusHistory — ประวัติสถานะ (append-only) [REQ-LCS-012/013]¶
StatusHistoryId 🔑 bigint, RequestId FK, FromStatus, ToStatus, Note, ChangedBy FK→AppUser, ChangedAt
6. Compensation¶
CompensationCalculation — รอบคำนวณค่าตอบแทน [REQ-LCS-010]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| CompensationId 🔑 | int | PK |
| ProvinceId / ConsultantId | int FK | แยกจอตามจังหวัด |
| PeriodStart / PeriodEnd | date | ช่วงคำนวณ |
| EligibleDays | int | วันที่ครบ 8 ชม. (จ่ายได้) |
| TotalHours | decimal(7,2) | รวมจาก DutySession |
| RatePerDay | decimal(10,2) | DEFAULT 1000.00 |
| Amount | decimal(12,2) | = EligibleDays × RatePerDay |
| Status | varchar(15) CHECK | DRAFT/CONFIRMED/EXPORTED/SENT_S5/PAID |
| S5Reference | varchar(100) | เลขอ้างอิงเมื่อส่ง S5 [OPEN-S5] |
| CalculatedBy | int FK |
UNIQUE(ConsultantId, ProvinceId, PeriodStart, PeriodEnd)
CompensationItem — รายการประกอบ [REQ-LCS-010]¶
CompensationItemId 🔑, CompensationId FK, DutySessionId FK, DutyDate, Hours decimal(5,2), IsEligible bit, Amount decimal(10,2)
7. Cross-cutting¶
Attachment — ไฟล์แนบ polymorphic [REQ-LCS-001/006/013]¶
AttachmentId 🔑, OwnerEntityType varchar(40), OwnerEntityId int, FileName 🔒, MimeType, SizeBytes bigint, StoragePath (เข้ารหัส at-rest), UploadedBy FK, UploadedAt, IsDeleted
Notification — แจ้งเตือน [REQ-LCS-004/007/009]¶
NotificationId 🔑 bigint, RecipientUserId FK→AppUser, Type varchar(40), Title, Message, RelatedEntityType/Id, IsRead bit, SentAt
ApprovalStep — สายอนุมัติ (config) [REQ-LCS-001]¶
ApprovalStepId 🔑, Process varchar(40), StepNo int, StepName nvarchar, RoleCode, SlaDays int, IsActive · UNIQUE(Process, StepNo)
SystemConfig — ค่าตั้งระบบ (key/value) [REQ-LCS-012]¶
ConfigKey 🔑 varchar(100), ConfigValue nvarchar(max), Description, UpdatedAt, UpdatedBy · ใช้เก็บ SLA, Template, map สถานะสาธารณะ
PermissionLog — log จัดการสิทธิ (append-only) [REQ-LCS-005]¶
PermissionLogId 🔑 bigint, ActorUserId FK, TargetUserId FK→AppUser, RoleCode, Action CHECK GRANT/CHANGE/REVOKE, Reason nvarchar NOT NULL (บังคับ), CreatedAt
AuditLog — audit trail ทั่วระบบ (append-only) [REQ-LCS-013]¶
| คอลัมน์ | ชนิด | คำอธิบาย |
|---|---|---|
| AuditLogId 🔑 | bigint | PK |
| ActorUserId | int FK | |
| ActorName / ActorRole | nvarchar / varchar | denormalized (คงไว้แม้ user เปลี่ยน) |
| Action | varchar(40) | CREATE/UPDATE/DELETE/UPLOAD/QA/ESCALATE/EXPORT/LOGIN |
| EntityType / EntityId | varchar | |
| BeforeData / AfterData | nvarchar(max) | JSON ก่อน/หลัง |
| Reason | nvarchar(1000) | เหตุผล (คอลัมน์ "เหตุผล" ในจอ admin-audit ; บังคับสำหรับ role.update/lawyer.revoke/qa.reject) |
| IpAddress | varchar(45) | |
| CreatedAt | datetime2 |
Retention
AuditLog/PermissionLog/Notification/ImportError เป็น log ปริมาณสูง — วางแผน archive/purge ตามนโยบาย retention ของกรมฯ (align เหมือน S3 = 1 ปี, รอยืนยัน)