Skip to main content

Auto-response message

ภาพรวม​

Auto-response message คือกฎแบบ "keyword → Rich message" เมื่อผู้ใช้พิมพ์ข้อความในห้องแชทตรงกับ keyword ที่ตั้งไว้ ระบบจะส่ง Rich message ที่ผูกไว้กลับไปให้อัตโนมัติโดยไม่ต้องมีแอดมินคอยตอบ เหมาะกับคำถามซ้ำ ๆ เช่น เวลาทำการ ที่ตั้งสาขา หรือวิธีสั่งซื้อ

จุดสำคัญที่ต้องเข้าใจก่อนเริ่มคือ เมนูนี้ไม่ได้เป็นผู้ตอบข้อความเอง — สิ่งที่การกดบันทึกทำจริงคือการเขียน ตาราง keyword ลง Redis ให้ครบทั้ง OA ใหม่ทั้งชุด แล้วบริการเบื้องหลังเป็นผู้อ่านตารางนั้นตอนมีข้อความเข้ามาและเป็นผู้ส่งจริง ผลที่ตามมาคือกฎที่ "ดูปกติ" ในหน้าจอนี้อาจไม่มีอยู่ในตารางที่ใช้ตอบจริงเลยก็ได้ ถ้าเงื่อนไขบางอย่างไม่ครบ (ดูหัวข้อ รายละเอียดสำคัญ)

บทบาทที่ใช้งาน — ทีมที่ดูแลแชทของ LINE OA (โมดูลนี้มี ModuleGate บังคับจริงที่ backend — ดูหัวข้อ สิทธิ์การเข้าถึง)

เส้นทางผู้ใช้งาน​

1. ดูรายการกฎ​

เปิดเมนู ข้อความตอบกลับอัตโนมัติ สิ่งแรกที่ระบบทำคืออ่านการตั้งค่าของ LINE OA แล้ว ขึ้นแถบเตือนสีเหลืองไว้เหนือตาราง ถ้าลำดับจัดการข้อความถูกตั้งเป็น ai_classifier_only — ข้อความเตือนบอกตรง ๆ ว่า "Auto-response ถูกปิดใช้งานอยู่ในขณะนี้" เพราะโหมดนั้นให้เวิร์กโฟลว์แชตบอทรับข้อความทั้งหมดไป กฎในเมนูนี้จะไม่ถูกกระตุ้นเลย พร้อมบอกที่แก้ให้ด้วย (ตั้งค่า LINE OA → Message Handling)

ตารางมีคอลัมน์ ลำดับ / ชื่อ / Rich message / การดำเนินการ พร้อมสวิตช์สถานะที่กดสลับได้จากหน้ารายการโดยตรง คอลัมน์ Rich message แสดงชื่อของ Rich message ที่ผูกไว้ พร้อม ป้ายกำกับสถานะ — ป้ายสีเขียวเมื่อยังใช้งานได้ และป้าย "ถูกลบแล้ว" เมื่อ Rich message นั้นไม่อยู่ในสถานะใช้งานอีกต่อไป

ตัวกรองมี 2 ช่อง — ค้นหา (ค้นได้ทั้งจาก ชื่อกฎและตัว keyword ตาม placeholder ที่บอกว่า "ชื่อหรือ keyword") และเลือกสถานะ

2. สร้างกฎใหม่​

  1. กดปุ่ม สร้างการตอบกลับ เข้าสู่ฟอร์มสองฝั่ง
  2. กรอกชื่อกฎ — ไม่เกิน 100 ตัวอักษร ต้องไม่ซ้ำกับกฎอื่น ใต้ช่องชื่อมีกล่อง เงื่อนไขการกรอกข้อมูล อธิบายอักขระ/สัญลักษณ์ที่รองรับ และข้อจำกัดว่าห้ามขึ้นต้นด้วยสัญลักษณ์
  3. กรอก keyword แบบแท็ก — พิมพ์แล้วกด Enter หรือคั่นด้วยจุลภาคเพื่อเพิ่มหลายคำต่อกฎ กล่องคำแนะนำข้างช่องระบุกฎกติกาไว้ 3 ข้อ: ตอบเฉพาะ keyword ที่ตั้งไว้ (ถ้าตั้งหลายคำจะตอบเมื่อตรงคำใดคำหนึ่ง), แต่ละ keyword ยาวได้ไม่เกิน 30 ตัวอักษร, และ keyword ที่ถูกใช้แล้วจะใช้กับกฎอื่นไม่ได้
  4. ระบบตรวจ keyword ซ้ำทันทีที่เพิ่มแท็ก (หน่วงไว้ 0.5 วินาที) ถ้าซ้ำ ระบบจะ ลบแท็กนั้นออกให้ ขึ้นข้อผิดพลาดใต้ช่อง และเด้งการแจ้งเตือนมุมขวาบนพร้อมปุ่มเปิดกฎที่ใช้ keyword นั้นอยู่ในแท็บใหม่
  5. เลือก Rich message ที่ต้องการให้ตอบกลับ จากรายการที่มีอยู่ในเมนู Rich message
  6. ดูตัวอย่างข้อความ ที่คอลัมน์ขวาในรูปแบบหน้าจอแชทจริง
  7. เปิดสวิตช์สถานะ (ค่าเริ่มต้นเมื่อสร้างใหม่คือเปิดใช้งาน) แล้วกดบันทึก

3. แก้ไขกฎที่มีอยู่​

เปิดฟอร์มแก้ไข ระบบเทียบ Rich message ที่บันทึกไว้กับรายการที่เลือกได้ในปัจจุบัน — ถ้า Rich message นั้น ไม่อยู่ในรายการอีกแล้ว (ถูกลบไป) ระบบจะ ล้างค่าในช่องให้เป็นว่าง และขึ้นข้อผิดพลาดกำกับไว้ บังคับให้เลือกใหม่ก่อนจะบันทึกได้ (ต่างจากหน้ารายการที่แค่ขึ้นป้าย "ถูกลบแล้ว" ให้เห็น)

การกดสวิตช์สถานะในหน้ารายการเรียกเส้นทางแยก (PUT /auto-response/:id/status) ไม่ต้องส่งข้อมูลทั้งฟอร์ม และทุกครั้งที่บันทึกหรือสลับสถานะ ระบบจะเขียนตาราง keyword ใน Redis ใหม่ทั้งชุด

รายละเอียดสำคัญที่ตรวจสอบจากซอร์สโค้ดจริง​

ยืนยันจาก internal/modules/autoresponse/{controller,service,dto}.go ของ line-management-cms-api-go, internal/autoresponse/service.go และ internal/cronscheduler/auto_response_sync.go ของ line-management-worker-go:

  • ทุกครั้งที่บันทึก ระบบเขียนตาราง keyword ของทั้ง OA ใหม่หมด ไม่ได้แก้เฉพาะกฎที่เพิ่งแตะ — กลไกคือลบคีย์ Redis AUTO_RESPONSE:LINE_OA_ID:<id> ทิ้งทั้งอัน แล้วสร้างใหม่จากการอ่านกฎ ทุกกฎที่สถานะ active ในองค์กร+OA นั้น ได้ผลเป็น Redis hash ที่แมป keyword → {autoResponseId, richMessageId} ทำงานเหมือนกันทั้งตอนสร้าง แก้ไข สลับสถานะ ลบ และลบถาวร — และถ้าคำนวณแล้วได้ตารางว่าง ระบบจะ ลบคีย์ทิ้งโดยไม่เขียนอะไรกลับเลย
  • กฎที่ผูกกับ Rich message ที่ใช้งานไม่ได้จะถูก "ตัดออกเงียบ ๆ" จากตารางที่ใช้ตอบจริง — ตอนสร้างตาราง ระบบดึงรายชื่อ Rich message ที่ status = active ของ OA นั้นมาก่อน แล้ว ข้าม keyword ทุกคำของกฎที่ชี้ไป Rich message ที่ไม่อยู่ในรายชื่อนั้น ผลคือกฎยังอยู่ในฐานข้อมูล ยังโชว์ในตาราง สวิตช์ยังเปิดอยู่ แต่ ไม่มีอยู่ในตารางที่ใช้ตอบจริง — ตรงกับป้าย "ถูกลบแล้ว" ที่หน้ารายการขึ้นให้เห็น
  • keyword ที่ซ้ำกันข้ามกฎ ตัวที่ถูกอ่านทีหลังจะทับตัวก่อน — ตารางถูกประกอบเป็น map ตรง ๆ ตามลำดับที่อ่านกฎมา จึงเหลือกฎเดียวที่ตอบ keyword นั้นได้ กลไกกัน keyword ซ้ำตอนกรอกฟอร์มจึงเป็นการป้องกันชั้นเดียวที่มี — ไม่มีข้อจำกัดที่ระดับฐานข้อมูลหรือ API ที่กันไว้อีกชั้น
  • การจับคู่ keyword ตอนรันจริงเป็นการเทียบแบบตรงตัวทั้งคำ (exact match) — บริการเบื้องหลังใช้ HGET อ่านฟิลด์ตามชื่อ keyword ตรง ๆ ไม่ใช่การค้นแบบมีคำนั้นอยู่ในข้อความ (substring) หรือแบบใกล้เคียง ข้อความที่พิมพ์เกินมาแม้ตัวเดียวจะไม่ตรง
  • POST /check-keyword-exists ตอบ 500 เมื่อ keyword "ว่างอยู่" (ใช้ได้) — นี่คือบั๊กจากระบบต้นฉบับที่ถูกคงไว้โดยเจตนา คอมเมนต์ระบุไว้ตรง ๆ ว่า TS อ้าง res[0].id บนอาเรย์ว่าง ทำให้เกิด TypeError ระบบจึงตอบ 500 พร้อมข้อความ JavaScript ตามตัวอักษร Cannot read properties of undefined (reading 'id') แทนที่จะตอบ {exists: false} และ ฝั่งหน้าเว็บก็รับมือด้วยการถือว่า "คำขอล้มเหลว = keyword ใช้ได้" (เส้นทาง keyword ว่างคือ block catch ที่แค่เขียน console log) นอกจากนี้ฟิลด์ที่ชื่อ richMessageId ในคำตอบ แท้จริงบรรจุ id ของ auto-response ไม่ใช่ของ Rich message (คอมเมนต์ระบุว่าตั้งชื่อผิดมาตั้งแต่ต้นฉบับ) — แต่นั่นคือค่าที่หน้าเว็บต้องใช้พอดีเพื่อทำลิงก์ "ดูกฎที่ใช้ keyword นี้" พฤติกรรมจึงถูกต้องแม้ชื่อฟิลด์จะผิด
  • เส้นทางสลับสถานะไม่มีการตรวจสอบข้อมูลใด ๆ เลย — PUT /auto-response/:id/status รับค่า status จาก body แล้วเขียนลงคอลัมน์ตรง ๆ โดยไม่ตรวจ เพราะในระบบต้นฉบับชนิดของ body เป็น type alias ซึ่งทำให้ ValidationPipe ไม่ทำงาน (คอมเมนต์อธิบายไว้ครบ) เรียก API ตรงด้วยค่าอะไรก็ถูกบันทึกลงไปได้ — และค่าที่ไม่ใช่ active จะทำให้กฎหลุดออกจากตารางที่ใช้ตอบจริงโดยปริยาย
  • ข้อความแจ้งข้อผิดพลาดของสถานะไม่ตรงกับค่าที่ระบบรับจริง — ข้อความบอกว่า "status must be one of the auto-response status values: active, inactive" แต่รายการค่าที่ผ่านการตรวจจริงคือ CommonStatus ทั้ง 9 ค่า (active, inactive, delete, process, processing, completed, expired, draft, failed) การส่ง draft หรือ failed มาที่เส้นทางสร้าง/แก้ไขจึงผ่านการตรวจไปได้ ทั้งที่ข้อความบอกว่ารับแค่สองค่า
  • ค่า status ที่ไม่ใช่สตริงทำให้เกิด 500 ก่อนที่ฟิลด์อื่นจะถูกตรวจ — ระบบคงพฤติกรรมของ class-transformer ไว้: การแปลงค่าทุกตัวเกิดขึ้น ก่อน การตรวจสอบทั้งหมด ดังนั้นการส่ง status เป็นตัวเลขหรืออ็อบเจ็กต์จะได้ 500 พร้อมข้อความ JavaScript ตามตัวอักษร text.toLowerCase is not a function และ กลบข้อผิดพลาดของฟิลด์อื่นที่กรอกผิดไว้หมด
  • การตรวจ keywords และ richMessageId หลวมกว่าที่หน้าจอบังคับไว้มาก — keywords มีแค่กฎ "ต้องไม่ว่าง" ไม่มีกฎ "ต้องเป็นอาเรย์" จึงส่ง อาเรย์ว่าง [] ผ่านได้ (รวมถึงตัวเลขหรืออ็อบเจ็กต์) ส่วน richMessageId แปลงค่าตามกฎของ JavaScript ทำให้สตริงว่างกลายเป็นเลข 0 ซึ่งผ่านทั้งกฎ "ไม่ว่าง" และ "ต้องเป็นตัวเลข" — และ ไม่มีการตรวจเลยว่า Rich message นั้นมีอยู่จริงหรือเป็นของ OA ผู้เรียก (ต่างจากเมนู Rich message ที่ตรวจความเป็นเจ้าของของ quick reply อย่างเข้มงวด) กฎที่ชี้ไป id ที่ไม่มีอยู่จะถูกตัดออกจากตาราง Redis เงียบ ๆ อีกที
  • มีผู้เขียนตาราง keyword ถึงสามทาง และทางที่สามถูกเพิ่มเพื่อแก้อาการ "ตอบแค่ครั้งที่สอง" — นอกจากการบันทึกที่หน้าเว็บ ยังมี cron ทุก 5 นาที ที่ไล่ sync ทุก OA และ การอุ่นแคชแบบ cache-aside ตอนที่คีย์เย็น คอมเมนต์อธิบายอาการเดิมไว้ตรง ๆ ว่าตารางถูกเขียนจาก 2 ทางแรกเท่านั้น พอรีสตาร์ตหรือแคชถูกไล่ออก ข้อความ แรก จะไม่ตรงแม้ตั้งค่าถูก จึงเพิ่มกลไกอุ่นแคชที่ แยกแยะระหว่าง "คีย์ยังไม่มีเลย" (อุ่นจากฐานข้อมูลแล้วลองใหม่) กับ "มีคีย์แต่ไม่มี keyword นี้" (ปล่อยไป) เพื่อไม่ให้ข้อความคุยเล่นทั่ว ๆ ไปกระตุ้นการอุ่นแคชทุกครั้ง
  • cron เดิมเคยหยุดกลางทางเมื่อ OA หนึ่งพัง — คอมเมนต์ระบุว่าโค้ดเดิมใช้ return แทน continue OA เดียวที่ตั้งค่าเสียหรือใหญ่เกินจึงทำให้ OA ที่เหลือในรอบนั้นไม่ได้ sync เลย ("สาเหตุหลักอย่างหนึ่งของอาการ auto-response ทำงานแค่ครั้งที่สอง") ปัจจุบันแก้ให้ข้ามตัวที่พังแล้วไปต่อ
  • ถ้าไม่มี keyword ตรงและเปิดโหมดส่งต่อให้ AI ไว้ ข้อความจะถูกส่งต่อเข้าคิวของ AI — บริการเบื้องหลังจะ publish ข้อความนั้นเข้าคิว trigger ต่อให้ ไม่ได้ทิ้งไปเปล่า ๆ (ถ้าไม่ได้เปิดโหมดนี้ จะเพียงเขียน log ว่าไม่มีกฎรองรับ keyword นั้น)
  • merge tag ในเนื้อหาถูกแทนค่าตอนส่ง ไม่ใช่ตอนบันทึก — ตอนจะส่งจริง ระบบตรวจว่าเนื้อหาของ Rich message มี merge tag หรือไม่ ถ้ามีจึงไปอ่านข้อมูลผู้ใช้ LINE คนนั้นมาแทนค่า และถ้า LINE OA ไม่อยู่ในสถานะ active ตอนนั้น งานจะถูกทำเครื่องหมายว่าล้มเหลวแบบถาวร ไม่ลองส่งซ้ำ
  • การลบ Rich message ไปล้างตาราง keyword ให้ด้วย — โมดูล Rich message ไล่ลบทุกฟิลด์ใน Redis hash ของเมนูนี้ที่ชี้ไปที่ Rich message ที่ถูกลบ กฎที่ผูกไว้จึงเลิกตอบทันทีโดยไม่ต้องรอ cron รอบถัดไป
  • การลบกฎเป็นการลบสองจังหวะ และการลบถาวรไม่ผูกกับ OA — การลบปกติเปลี่ยนสถานะเป็น delete ก่อน แล้วประทับ deleted_date อีกครั้งเป็นคำสั่งที่สอง ส่วน DELETE /:id/hard ลบด้วยเงื่อนไข id เพียงอย่างเดียว ไม่ได้กรอง line_oa_id จึงลบกฎของ OA ใดก็ได้ตาม id (จำกัดด้วยการต้องเป็น Super Admin เท่านั้น) และถ้าไม่ส่ง confirm=true จะถูกปฏิเสธด้วย 400 ที่มีข้อความเป็นสตริงดิบ ErrorResponse.AUS_10 ซึ่งคอมเมนต์เรียกตรง ๆ ว่าเป็นบั๊กของต้นฉบับที่คงไว้ตามตัวอักษร
  • ช่องค้นหาค้นทั้งชื่อและ keyword จริงตามที่ placeholder บอก — คำสั่ง SQL ค้นด้วย LIKE แบบไม่สนตัวพิมพ์เล็กใหญ่ทั้งที่คอลัมน์ชื่อ และไล่ดูทุกสมาชิกในอาเรย์ keyword (ผ่าน jsonb_array_elements_text) ส่วนโหมดพิเศษที่เมนู Segment audience เรียกใช้ จะกรองเฉพาะกฎที่สถานะ active หรือ inactive และ สร้างภายใน 3 เดือนล่าสุด เท่านั้น

เมนูที่เกี่ยวข้องกันในเส้นทางนี้​

  • Rich message — เนื้อหาที่กฎนี้ส่งออกไป ถ้า Rich message ที่ผูกไว้ถูกลบ กฎจะหลุดจากตารางที่ใช้ตอบจริงทันที หน้ารายการขึ้นป้าย "ถูกลบแล้ว" ให้เห็น และฟอร์มแก้ไขจะบังคับให้เลือกใหม่
  • Quick reply — keyword ของกฎที่เปิดใช้งานอยู่ในเมนูนี้จะโผล่เป็นคำแนะนำในช่องข้อความของปุ่มชนิด "ข้อความ" ที่เมนูนั้น เพราะข้อความที่ปุ่มส่งกลับเข้าแชทมากระตุ้นกฎที่นี่ได้จริง
  • Template message — เช่นเดียวกัน keyword ที่เปิดใช้งานจะโผล่เป็นคำแนะนำในช่องข้อความของปุ่มชนิด "ส่งข้อความ"
  • การตั้งค่า LINE OA — ค่าลำดับจัดการข้อความเป็นตัวตัดสินว่ากฎในเมนูนี้จะได้ทำงานหรือไม่ ถ้าตั้งเป็น ai_classifier_only กฎทั้งหมดจะไม่ถูกกระตุ้น (หน้ารายการขึ้นแถบเตือนไว้ให้)
  • Segment audience — ใช้กฎในเมนูนี้เป็นเงื่อนไขสร้างกลุ่มเป้าหมายได้ โดยเห็นเฉพาะกฎที่สร้างภายใน 3 เดือนล่าสุด

จุดที่ควรระวัง​

  • แก้กฎแล้วบอทยังตอบเป็นค่าเดิม ให้รอสักครู่ — การตอบจริงเกิดที่บริการเบื้องหลังซึ่งอ่านจากตาราง Redis ตารางนั้นถูกเขียนใหม่ทันทีตอนกดบันทึก แต่ถ้าจังหวะไม่ลงตัวยังมี cron ทุก 5 นาทีตามมาเก็บอีกชั้น
  • กฎที่ผูกกับ Rich message ที่ถูกลบจะเงียบสนิท ไม่มีข้อผิดพลาดที่ไหน — สวิตช์ยังเปิด กฎยังอยู่ในตาราง แต่ไม่มีใครตอบ ให้ดูป้ายกำกับในคอลัมน์ Rich message เป็นอย่างแรกเมื่อมีคนแจ้งว่า "บอทไม่ตอบ"
  • keyword ต้องตรงทั้งคำ — ผู้ใช้พิมพ์ "เวลาทำการครับ" จะไม่ตรงกับ keyword "เวลาทำการ" ถ้าต้องการรองรับหลายรูปแบบ ต้องเพิ่มเป็นหลาย keyword ในกฎเดียว (ระบบตอบเมื่อตรงคำใดคำหนึ่ง)
  • ถ้า LINE OA ตั้งลำดับจัดการข้อความเป็น ai_classifier_only กฎทั้งหมดในเมนูนี้ไม่ทำงานเลย — แถบเตือนที่หน้ารายการเป็นสัญญาณเดียวที่มี และแถบนี้ปิดได้ ปิดไปแล้วจะไม่มีอะไรเตือนอีก
  • keyword ยาวเกิน 30 ตัวอักษรถูกกันที่หน้าเว็บเท่านั้น — เพดานนี้ไม่มีการตรวจซ้ำที่ backend เลย
  • การกดสวิตช์สถานะเป็นเส้นทางที่ไม่ตรวจข้อมูล — ใช้งานผ่านหน้าเว็บปกติปลอดภัย แต่การเรียก API เส้นทางนี้เองมีความเสี่ยงเขียนค่าที่ระบบไม่รู้จักลงฐานข้อมูล ซึ่งจะทำให้กฎเงียบไปโดยที่หน้าจออาจแสดงผลไม่ตรงความจริง
  • ชื่อกฎซ้ำถูกปฏิเสธเป็นรายฟิลด์ — ระบบตอบ 400 พร้อมชี้ที่ฟิลด์ name ว่า "Title is already exist"
  • ไม่มีการตรวจว่า Rich message ที่เลือกเป็นของ OA ตัวเอง — ในทางปฏิบัติหน้าเว็บให้เลือกได้แค่จากรายการของ OA ตัวเองอยู่แล้ว แต่ระดับ API ไม่มีการกันไว้

สิทธิ์การเข้าถึง (ตรวจสอบจากซอร์สโค้ดจริง)​

  • ฝั่งหน้าเว็บ — ทั้งหน้ารายการและหน้าฟอร์มถูกครอบด้วย PermissionGuard ตรวจ action VIEW ของ subject auto-response
  • ฝั่งเซิร์ฟเวอร์ — ทุกเส้นทางทั้ง 8 เส้นทางของโมดูลนี้ถูกครอบด้วย ModuleGate(d, "auto-response") ที่บังคับใช้จริง (เหมือนโมดูล Rich message, Template message และ Campaign และต่างจากโมดูล Quick reply ที่ไม่มี ModuleGate เลย) คอมเมนต์ในโค้ดระบุพฤติกรรมไว้ชัด: ผู้เรียกประเภทลูกค้าที่องค์กรถูกผู้ดูแลระดับแพลตฟอร์มปิดโมดูล "auto-response" ไว้ จะได้ 403 ส่วนผู้เรียกภายใน (onemoby) ผ่านได้
  • คอมเมนต์บนหัวไฟล์ controller.go บันทึกไว้ว่า @Public() ระดับ controller ในระบบต้นฉบับถูกคอมเมนต์ทิ้งไว้ ทุกเส้นทางจึงวิ่งผ่านการตรวจ JWT ทั้งหมด ไม่มีเส้นทางสาธารณะในโมดูลนี้
  • policy annotation ระดับการกระทำ (create/read/readAll/update/delete) มีประกาศไว้ครบ แต่วิ่งผ่าน middleware ที่เป็น no-op เหมือนโมดูลอื่นส่วนใหญ่ — การบังคับจริงจึงอยู่ที่ ModuleGate ระดับโมดูล
  • DELETE /api/auto-response/:id/hard ต้องเป็น Super Admin และต้องส่ง confirm=true (ค่าที่ไม่ใช่ true/false ตรงตัวจะถูกปฏิเสธด้วย "Validation failed (boolean string is expected)") — และตามที่ระบุไว้ข้างต้น การลบถาวรนี้ไม่ได้จำกัดอยู่แค่ OA ของผู้เรียก
  • การกันข้อมูลข้ามองค์กรบังคับที่เส้นทางอื่นทั้งหมด — การอ่าน รายการ แก้ไข สลับสถานะ และการลบแบบนุ่มนวล ผูก line_oa_id ของผู้เรียกไว้ทุกเส้นทาง การเรียก id ที่ไม่ใช่ของตนจะได้ 400 APP_007 ส่วนการลบที่ไม่พบเป้าหมายจะได้ 400 AUS_102

ไฟล์อ้างอิงจากซอร์สโค้ด​

Frontend (cms-web-2026)

  • src/app/auto-response/page.tsx — จุดเข้าหน้ารายการ, PermissionGuard, การอ่านค่า Message Handling ของ LINE OA เพื่อขึ้นแถบเตือน
  • src/app/auto-response/form/page.tsx — จุดเข้าหน้าฟอร์ม (สร้าง/แก้ไข/ทำซ้ำ/ดู)
  • src/components/auto-response/list/auto-response.container.tsx — ตาราง, สวิตช์สถานะ, ป้ายกำกับสถานะของ Rich message
  • src/components/auto-response/form/auto-response-form.tsx — ช่องกรอก keyword แบบแท็ก, การตรวจซ้ำแบบหน่วงเวลา, การแจ้งเตือนพร้อมลิงก์ไปกฎที่ชนกัน
  • src/components/auto-response/form/auto-response-form.container.tsx — การล้างค่า Rich message ที่ถูกลบตอนเปิดฟอร์มแก้ไข
  • src/services/auto-response.service.ts — endpoint ทั้งหมดที่หน้าเว็บเรียกใช้
  • messages/th/auto-response.json, messages/en/auto-response.json — ข้อความ UI ทั้งหมด

Backend (line-management-cms-api-go)

  • internal/modules/autoresponse/controller.go — 8 เส้นทาง, ModuleGate("auto-response"), SuperAdminGuard ของ hard delete, เส้นทางสลับสถานะที่ไม่ตรวจข้อมูล
  • internal/modules/autoresponse/service.go — การเขียนตาราง keyword ใน Redis ใหม่ทั้งชุด, การตัดกฎที่ Rich message ใช้ไม่ได้ออก, IsKeywordExists
  • internal/modules/autoresponse/dto.go — กฎตรวจสอบข้อมูลขาเข้าและพฤติกรรมการแปลงค่าแบบ JavaScript
  • internal/modules/autoresponse/query.go — การ bind พารามิเตอร์รายการและการสร้างคีย์ cache
  • internal/modules/richmessage/service.go — การล้างตาราง keyword เมื่อ Rich message ถูกลบ

Worker (line-management-worker-go)

  • internal/autoresponse/service.go — การอ่านตาราง keyword ตอนรันจริง, การอุ่นแคชแบบ cache-aside, การส่งต่อให้ AI, การแทน merge tag
  • internal/cronscheduler/auto_response_sync.go — cron ทุก 5 นาทีที่ sync keyword ของทุก OA

ดูรายละเอียดเชิงเทคนิคเพิ่มเติม (เวอร์ชันก่อนหน้าของทีมเอกสาร) ที่ ตอบกลับอัตโนมัติ (Auto Response)