Skip to main content

ตั้งค่า Attribute (Attribute Setup)

ภาพรวม

Attribute Setup (ฝั่ง backend ใช้ชื่อ attribute-master) คือหน้าจัดการ schema กลางของ custom attribute ที่ผูกกับผู้ใช้ LINE ในแต่ละ LINE OA พูดง่าย ๆ คือเป็นการ "ประกาศโครงสร้างข้อมูล" ไว้ล่วงหน้าว่า ระบบจะเก็บฟิลด์อะไรบ้าง แต่ละฟิลด์เป็นข้อมูลชนิดใด และฟิลด์ไหนบ้างที่นำไปใช้กรอง audience หรือแสดงในรายงานได้

หน้าจอนี้เหมาะกับผู้ดูแลระบบที่ต้องออกแบบโครงสร้างข้อมูลลูกค้าก่อนเริ่มเก็บข้อมูลจริง เพราะฟีเจอร์ปลายทางอย่าง Audience, Report, Workflow และ Friend Track จะดึงนิยามจากที่นี่ไปใช้ทั้งหมด เมนูอยู่ใต้กลุ่ม Settings → User Attribute Setup

ข้อมูล 1 รายการ (attribute master) ประกอบด้วย

ข้อมูลคำอธิบาย
ชื่อ (name)ชื่อชุด attribute ที่ใช้อ้างอิงในตาราง บังคับกรอก ไม่เกิน 255 ตัวอักษร
คำอธิบาย (description)รายละเอียดเพิ่มเติมของชุด attribute นี้
สถานะ (status)เปิดใช้งาน (active) หรือปิดใช้งาน (inactive)
Schemaโครงสร้างฟิลด์ทั้งหมดในรูปแบบ tree รองรับฟิลด์ซ้อน (nested) และ array

แต่ละฟิลด์ภายใน schema มีคุณสมบัติดังนี้

คุณสมบัติคำอธิบาย
labelชื่อที่ผู้ใช้เห็นและเป็น identity จริงที่ระบบตรวจสอบ ห้ามว่างและห้ามซ้ำกันทั้ง tree
dataTypeชนิดข้อมูล เลือกได้ 6 แบบ: string, number, date, boolean, array, object
filterableอนุญาตให้นำฟิลด์นี้ไปใช้เป็นเงื่อนไขกรองใน Audience หรือไม่
displayInReportอนุญาตให้แสดงเป็นคอลัมน์ในรายงาน All Friends หรือไม่
pathตำแหน่งเต็มของฟิลด์ใน JSON ใช้ระบุตำแหน่งเวลาแก้ไข/ลบ
keyรหัสภายในที่ระบบสร้างให้อัตโนมัติ ไม่แสดงและแก้ไขไม่ได้จากหน้าจอ

จุดสำคัญที่ต้องทราบ

  • ฟิลด์ที่มี dataType เป็น object หรือ array จะไม่สามารถเปิด filterable หรือ displayInReport ได้ เพราะเป็นฟิลด์เชิงโครงสร้าง ไม่ใช่ค่าที่นำไปเปรียบเทียบตรง ๆ
  • การเลือก dataType มีผลต่อ operator ที่เลือกได้ในหน้า Audience จึงควรกำหนดให้ถูกต้องตั้งแต่ต้น
  • สร้าง schema ได้ 2 ทาง คือ กรอกทีละฟิลด์ด้วยมือ หรือ Import from JSON โดยวาง JSON ตัวอย่างแล้วให้ระบบแปลงเป็นโครงสร้างให้

Business Flow

หน้ารายการ (/attribute-setup)

  1. เปิดหน้า ระบบตั้ง breadcrumb เป็น Settings → User Attribute Setup แล้วโหลดตารางรายการ
  2. ระบบอ่านเงื่อนไขการกรองล่าสุดจาก sessionStorage หากไม่มีจะใช้ค่าเริ่มต้น (หน้าแรก 10 รายการต่อหน้า ไม่มีคำค้น ไม่กรองสถานะ)
  3. ตารางแสดงลำดับ ชื่อ คำอธิบาย จำนวนฟิลด์ใน schema สถานะ และวันที่สร้าง คลิกที่ชื่อเพื่อเปิดดูรายละเอียดในโหมดอ่านอย่างเดียว
  4. ค้นหาด้วยชื่อ และกรองตามสถานะ (ทั้งหมด / เปิดใช้งาน / ปิดใช้งาน) ได้จากแถบเครื่องมือด้านบน มุมขวาแสดงจำนวนรายการทั้งหมด
  5. ทุกครั้งที่เปลี่ยนเงื่อนไขการกรองหรือหน้า ระบบจะจดจำค่าล่าสุดไว้ในเซสชัน ทำให้กลับเข้าหน้านี้แล้วยังเห็นผลเดิม
  6. ปุ่มมุมขวาบนมี 2 ปุ่ม คือ Import from JSON สำหรับเข้าโหมดนำเข้า และ Create สำหรับสร้างด้วยมือ
  7. การลบต้องยืนยันผ่านกล่องข้อความก่อน เมื่อสำเร็จระบบจะแจ้งผลและรีเฟรชตารางให้อัตโนมัติ

การสร้าง / แก้ไข / ดูรายละเอียด (/attribute-setup/form)

  1. หน้าฟอร์มทำงาน 3 โหมด ได้แก่ สร้างใหม่ แก้ไข และดูอย่างเดียว โดยดูจากพารามิเตอร์ใน URL (id สำหรับระบุรายการที่แก้ไข และ view=true สำหรับโหมดอ่านอย่างเดียว)
  2. กรณีแก้ไขหรือดู ระบบจะโหลดข้อมูลเดิมมาเติมลงฟอร์มทั้งชื่อ คำอธิบาย สถานะ และ schema
  3. โหมดดูอย่างเดียวจะปิดการแก้ไขทุกช่อง ตัวแก้ไข schema เป็นแบบอ่านอย่างเดียว และซ่อนปุ่มบันทึก
  4. เมื่อกดบันทึก ระบบจะไล่ตรวจ label ทุกฟิลด์แบบ recursive ทั้ง tree ก่อนเสมอ โดย label ต้องไม่ว่างและต้องไม่ซ้ำกัน (เทียบแบบไม่สนตัวพิมพ์เล็กใหญ่) ถ้าไม่ผ่านจะแจ้งเตือนและไม่ส่งข้อมูลไปยัง API
  5. ผ่านการตรวจแล้ว ระบบจะสร้างรายการใหม่หรืออัปเดตรายการเดิม แล้วพากลับสู่หน้ารายการ

โหมด Import from JSON

  1. ขั้นที่ 1 — กรอกข้อมูลและวาง JSON ผู้ใช้กรอกชื่อ (บังคับ) คำอธิบาย และ root path (ไม่บังคับ ใช้เมื่อต้องการชี้เข้าไปที่ object ย่อยแทนที่จะใช้ทั้งก้อน) จากนั้นวาง JSON ตัวอย่างลงในช่องข้อความ
  2. กด "Parse & Continue" ระบบจะตรวจรูปแบบ JSON ที่ฝั่งหน้าจอก่อน หากรูปแบบไม่ถูกต้องจะแจ้งเตือนทันทีโดยไม่เรียก API
  3. รูปแบบถูกต้องแล้ว ระบบส่ง JSON ไปให้ backend แปลงเป็น schema แล้วนำผลลัพธ์กลับมาแสดงในขั้นถัดไป หากแปลงไม่สำเร็จจะแจ้งเตือนพร้อมให้แก้ไขข้อมูลต้นทาง
  4. ขั้นที่ 2 — ตรวจสอบและปรับแต่ง ผู้ใช้แก้ชื่อและคำอธิบายได้อีกครั้ง พร้อมปรับ schema ที่แปลงมาได้ทั้ง label, ชนิดข้อมูล, สวิตช์ filterable/displayInReport และลบฟิลด์ที่ไม่ต้องการ
  5. ปุ่ม Back ย้อนกลับไปขั้นแรกได้โดยข้อมูล JSON เดิมยังอยู่ กด Save เพื่อบันทึกเป็น attribute master ใหม่ในสถานะเปิดใช้งาน

การแก้ไข schema ในตัวแก้ไข

  1. ตัวแก้ไขแปลงโครงสร้าง tree เป็นตารางแบบเยื้องระดับ ฟิลด์ที่มีฟิลด์ลูกจะมีปุ่มลูกศรสำหรับย่อ/ขยาย และมีปุ่ม Expand all / Collapse all สำหรับทั้งตาราง
  2. แต่ละแถวปรับได้ 4 ส่วน คือ Label, Data type, สวิตช์ Filterable และสวิตช์ Show in report พร้อมปุ่มลบท้ายแถว โดยสวิตช์ทั้งสองจะถูกปิดอัตโนมัติเมื่อชนิดข้อมูลเป็น object หรือ array
  3. ปุ่ม "Add attribute" เพิ่มฟิลด์ใหม่ที่ระดับบนสุด โดยตั้งค่าเริ่มต้นเป็นชนิด string และเปิดทั้ง filterable และ displayInReport ไว้ให้ ผู้ใช้ต้องกรอก label เอง
  4. การลบฟิลด์ของรายการที่ยังไม่เคยบันทึก จะลบออกทันที
  5. การลบฟิลด์ของรายการที่บันทึกไว้แล้ว ระบบจะเปิดกล่องเตือนผลกระทบและสอบถาม backend ก่อนว่ามีใครใช้ฟิลด์นั้นอยู่ ผลลัพธ์ครอบคลุม 4 ด้าน คือ จำนวนผู้ใช้ที่มีค่าในฟิลด์นั้น, trigger rule, audience และ rich message ที่อ้างถึง
  6. ผลการตรวจสอบเป็นเพียงข้อมูลประกอบการตัดสินใจ ไม่ได้บล็อกการลบ หากตรวจสอบไม่สำเร็จระบบก็ยังให้ลบได้
  7. การยืนยันลบในกล่องนี้เป็นการลบออกจาก schema ในหน้าจอเท่านั้น ต้องกดบันทึกที่ฟอร์มอีกครั้งเพื่อให้มีผลจริง

หน้าจอและองค์ประกอบหลัก

หน้ารายการ (/attribute-setup)

  • แถบเครื่องมือ — ช่องค้นหาตามชื่อ (ค้นทันทีขณะพิมพ์) ตัวเลือกสถานะ และตัวเลขสรุปจำนวนรายการทั้งหมด
  • ตารางรายการ — ลำดับ ชื่อ (คลิกเพื่อดูรายละเอียด) คำอธิบาย จำนวนฟิลด์ สถานะ วันที่สร้าง และปุ่มดำเนินการ พร้อมการแบ่งหน้า
  • ปุ่มสร้าง — Import from JSON และ Create แยกกันชัดเจนที่มุมขวาบน

ไฟล์อ้างอิงหลัก: src/app/attribute-setup/page.tsx, src/components/attribute-setup/list/attribute-setup.container.tsx

หน้าฟอร์ม (/attribute-setup/form)

  • การ์ดข้อมูลพื้นฐาน — ชื่อ (บังคับ) คำอธิบาย และสถานะ
  • การ์ด Schema — ตัวแก้ไข schema แบบตาราง โดยค่าที่แก้ไขจะถูกเก็บกลับเข้าฟอร์มโดยอัตโนมัติ
  • ตัวแก้ไข schema — ตารางแบบ tree รองรับการเยื้องระดับ ย่อ/ขยาย เพิ่ม แก้ และลบฟิลด์
  • กล่องเตือนก่อนลบฟิลด์ — แสดงจำนวนผู้ใช้และรายการ trigger rule / audience / rich message ที่อ้างถึงฟิลด์นั้น

ไฟล์อ้างอิงหลัก: src/app/attribute-setup/form/page.tsx, src/components/attribute-setup/form/attribute-setup-form.container.tsx, src/components/attribute-setup/form/components/attribute-editor.tsx, src/components/attribute-setup/form/components/attribute-delete-warning-modal.tsx

บริการฝั่ง API

รวมอยู่ที่ src/services/attribute-master.service.ts ภายใต้ path หลัก attribute-master

ความสามารถEndpoint
ดึงรายการ attribute masterGET /attribute-master
ดึงข้อมูลรายตัวGET /attribute-master/{id}
สร้างรายการใหม่POST /attribute-master
แก้ไขรายการPUT /attribute-master/{id}
ลบรายการDELETE /attribute-master/{id}
แปลง JSON เป็น schema (พรีวิว)POST /attribute-master/parse-json
ดึงเฉพาะ attribute ที่กรองได้GET /attribute-master/filterable
ดึงเฉพาะ attribute ที่แสดงในรายงานได้GET /attribute-master/reportable
ตรวจสอบการใช้งานของ attribute ก่อนลบGET /attribute-master/{id}/check-attribute-usage

จุดเชื่อมต่อกับฟีเจอร์อื่น

  • สิทธิ์การใช้งาน — เมนูและหน้าจอถูกควบคุมด้วยสิทธิ์ของโมดูล attribute-master ซึ่งแมปกับเมนู attribute-setup ใต้กลุ่ม Settings การกันสิทธิ์ทำที่เมนูด้านข้างและระบบ ability กลาง
  • Audience Multi-Source Filter — เมื่อเลือกแหล่งข้อมูลชนิด custom attribute ระบบจะดึงเฉพาะ attribute ที่เปิด filterable มาเป็นตัวเลือก และแยกกลุ่มระหว่างฟิลด์โปรไฟล์มาตรฐาน (path ขึ้นต้นด้วย __fixed.) กับ custom attribute จาก schema นี้ ส่วน operator ที่เลือกได้ผันตามชนิดข้อมูลของ attribute
  • Report All Friends — ดึงเฉพาะ attribute ที่เปิด displayInReport มาสร้างคอลัมน์แบบไดนามิก สวิตช์ในหน้านี้จึงเป็นตัวควบคุมคอลัมน์ในรายงานโดยตรง
  • Workflow — แผงตั้งค่า node เรียกดูรายการ attribute master ทั้งหมด และสร้าง/แก้ไข attribute master ได้จากในแผงนั้นเลยโดยไม่ต้องกลับมาหน้านี้
  • Friend Track และ All Friends detail — ดึงรายการ attribute master เพื่อจับคู่ค่าที่เก็บไว้กับ label ที่ผู้ใช้เข้าใจ
  • Import Mapping — ฟิลด์ปลายทางที่ขึ้นต้นด้วย custom. ในหน้านำเข้าข้อมูล คือ custom attribute ที่ประกาศไว้จากหน้านี้
  • System Attribute เป็นคนละฟีเจอร์ — ค่าแบบ key/value ระดับระบบที่ใช้ในหน้า LINE OA Management และ Workflow ไม่ได้เกี่ยวข้องกับ schema ของหน้านี้
  • โครงสร้างพื้นฐานร่วม — ใช้ระบบยืนยันตัวตนและ HTTP client กลางของ CMS (ออกจากระบบอัตโนมัติเมื่อ token หมดอายุ) ระบบ breadcrumb และเมนูด้านข้าง รวมถึงการจดจำเงื่อนไขการกรองใน sessionStorage เช่นเดียวกับหน้ารายการอื่นในระบบ

รายละเอียดฝั่ง Backend (CMS API)

โค้ดฝั่ง backend อยู่ที่ internal/modules/attributemaster/ โดยมีส่วนที่แยกไฟล์ออกมาเฉพาะทางสองส่วน คือ ตัวแปลง JSON เป็น schema และ ตัวรักษาลำดับของคีย์ เพื่อให้ผลลัพธ์ที่ส่งกลับเรียงฟิลด์ตรงตามลำดับที่ผู้ใช้วางเข้ามา ไม่สลับไปมาตามการจัดเก็บภายใน

สิทธิ์ที่ต้องมี

  • ทุก route ถูกครอบด้วย module gate ของโมดูล attribute-master
  • policy แยกตามการกระทำ: readAll สำหรับดึงรายการ, read สำหรับดูรายตัว ดึงรายการที่กรองได้/แสดงในรายงานได้ ตรวจการใช้งาน และการแปลง JSON เป็นพรีวิว, create สำหรับสร้างและนำเข้าเป็นชุด, update และ delete ตามการกระทำ
  • การแปลง JSON เพื่อดูพรีวิวใช้สิทธิ์ระดับอ่านเท่านั้น เพราะยังไม่มีการบันทึกใด ๆ เกิดขึ้น

Validation และ Business Rule ที่ backend ตรวจ

  • ตรวจโควตาจำนวน attribute ก่อนสร้างเสมอ (ค่า maxAttributes ของแพ็กเกจ) การสร้างจึงถูกปฏิเสธได้แม้ schema จะถูกต้องทุกอย่าง
  • การนำเข้าจาก JSON แยกเป็นสองจังหวะชัดเจน: POST /api/attribute-master/parse-json แปลงและคืนพรีวิวเท่านั้น ยังไม่บันทึก โดยรับ root path มาด้วยได้เพื่อชี้เข้าไปที่ object ย่อย ส่วนการบันทึกจริงเป็นอีกคำขอต่างหาก
  • backend ยังเปิด POST /api/attribute-master/import-json ไว้สำหรับสร้าง attribute จาก schema ทั้งชุดในคำขอเดียว ซึ่งเป็นเส้นทางที่มีอยู่ฝั่ง API แม้หน้าจอปัจจุบันจะบันทึกผ่านเส้นทางสร้างปกติ
  • GET /api/attribute-master/:id/check-attribute-usage รับคีย์ของ attribute ที่ต้องการตรวจมาทาง query string เป็นตัวระบุ ไม่ใช่ตรวจทั้งรายการรวดเดียว

สิ่งที่บันทึกและผลข้างเคียง (Side Effect)

  • นิยาม schema เก็บอยู่ในตาราง attribute_master ส่วนค่าจริงของแต่ละคนเก็บเป็น custom attribute ที่ผูกกับตาราง line_user
  • การตรวจการใช้งานก่อนลบต้องมองข้ามไปหลายตาราง ทั้ง audience, form_builder, import_mapping_job และ template_message เพื่อรวบรวมว่ามีใครอ้างถึงฟิลด์นั้นอยู่บ้าง
  • โมดูลนี้ไม่ได้เขียน cache และไม่ได้ส่งงานเข้าคิว การเปลี่ยน schema จึงมีผลทันทีกับฟีเจอร์ที่อ่านนิยามไปใช้
  • ผลกระทบเป็นวงกว้าง — เพราะ Audience filter, รายงาน All Friends, merge tag ของข้อความ และฟิลด์ปลายทางของการนำเข้าข้อมูล ล้วนอ่านนิยามจากตารางนี้ การแก้ชนิดข้อมูลหรือลบฟิลด์จึงกระทบหลายฟีเจอร์พร้อมกัน

Attribute ระดับระบบ เป็นคนละโมดูลที่ backend

นอกจาก attribute ที่ตั้งเองต่อ LINE OA ระบบยังมี attribute ระดับระบบ ที่นิยามไว้กลางในโมดูลแยกต่างหาก (internal/modules/systemattribute/) เป็นชุด attribute พื้นฐานที่ทุก OA มีเหมือนกัน

  • เป็นโมดูล CRUD เรียบง่ายเพียง 4 endpoint ภายใต้ /api/system-attribute
  • ผลลัพธ์ถูกนำไปรวมกับ custom attribute ในรายการ merge tag ของข้อความ (เมื่อร้องขอให้รวม attribute ระบบเข้าไปด้วย) และใช้ประกอบตอนสร้างฟอร์มและรายงาน
  • ตารางนี้ใช้กลไก soft delete อัตโนมัติของ ORM จริง ๆ (ต่างจากหลายโมดูลในระบบที่ต้องเขียนเงื่อนไขเอง) การดึงรายการจึงกรองรายการที่ถูกลบออกให้เองอยู่แล้ว
  • ข้อสังเกตด้านความปลอดภัย — โมดูลนี้ ไม่มี module gate และไม่มีการบังคับสิทธิ์ระดับ Super Admin ครอบไว้ ขอเพียงผ่านการยืนยันตัวตนกลางและมี LINE OA ที่เลือกไว้ก็เรียกได้ ทั้งที่ข้อมูลชุดนี้เป็นค่าที่ใช้ร่วมกันทั้งระบบ ไม่ใช่ข้อมูลเฉพาะของ OA ใด OA หนึ่ง
  • Edge case — คำสั่งแก้ไข attribute ระบบถูกเขียนให้ไม่กรองรายการที่ถูกลบไปแล้วออก (คงพฤติกรรมเดิมของระบบก่อนหน้าไว้) ผลคือการแก้ไขด้วย id ของรายการที่ถูกลบไปแล้วยังทำได้สำเร็จ ทั้งที่รายการนั้นจะไม่ปรากฏในผลการดึงรายการ

Edge Case และข้อสังเกตที่ควรรู้

  • ผลการตรวจการใช้งานก่อนลบเป็นเพียงข้อมูลประกอบการตัดสินใจ backend ไม่ได้บล็อกการลบ แม้จะพบว่ามีฟีเจอร์อื่นอ้างถึงอยู่ ความรับผิดชอบในการไม่ทำของพังจึงอยู่ที่ผู้ใช้
  • การจัดการข้อผิดพลาดของโมดูลนี้จะส่งต่อข้อผิดพลาดที่รู้จัก (เช่น ไม่มีสิทธิ์ ไม่พบข้อมูล ข้อมูลไม่ถูกต้อง ข้อมูลชนกัน) กลับไปตามเดิม แต่ข้อผิดพลาดที่ไม่รู้จักทั้งหมดจะถูกยุบเป็นข้อผิดพลาดทั่วไปรหัสเดียว ทำให้รายละเอียดต้นเหตุหายไปจากคำตอบ ต้องไปดูที่ log ของ backend แทน
  • ลำดับของฟิลด์ใน schema เป็นสิ่งที่โมดูลนี้ตั้งใจรักษาไว้ ไม่ใช่ผลพลอยได้ — การเรียงคอลัมน์ในรายงานและลำดับ merge tag จึงคาดเดาได้
  • การแก้ชนิดข้อมูลของฟิลด์ที่มีข้อมูลอยู่แล้วไม่ได้ทำให้ค่าที่เก็บไว้เปลี่ยนตามไปด้วย มีเพียงชุดตัวดำเนินการที่เลือกได้ในหน้า Audience เท่านั้นที่เปลี่ยน ค่าที่เก็บไว้ก่อนหน้าจึงอาจเทียบเงื่อนไขไม่ได้ตามที่คาด