2way-meeting-backoffice — Persistence & Integrations
2way-meeting-backoffice (branch: prod) ไม่มีฐานข้อมูลของตัวเอง — เป็น Next.js frontend ล้วน ข้อมูลทั้งหมดมาจาก HTTP/WebSocket ไปยัง backend อื่น ไม่พบ Prisma / TypeORM / Mongoose / DB driver ใน package.json
ค่า APP_CONNECT_DB_* และ APP_CONNECT_SMTP_* ใน .env* ถูก map ใน next.config.js:61-68 แต่ไม่มีโค้ดที่เปิด connection — remnant จาก scaffold reportmonitor
Integration map (ภาพรวม)
Browser (basePath /2way-backoffice)
│
├──[admin L2]──► 2way-api (appConnectAPI)
│ auth / surveys / announces / employee / complaints
│
├──[admin L2]──► chat-center-api (appConnectChatCenterAPI + fetchRedCrossAPI/chatCenterPath)
│ rooms / teamAdmin / tags / appointment / satisfaction
│ ▲
│ └── WebSocket wss://... path /chat-center-ws/socket.io
│
├──[LIFF + FAQ]─► 2way-vtrc-api (appConnectChatAPI = APP_CONNECT_API_BASIC)
│ getProfile / register / FAQs
│
├──[incident]───► incident-management-api (appConnectIncidentAPI) [UNVERIFIED repo]
│
└──[observability]► Sentry (client+server init; webpack plugin commented out)Integration 1 — 2way-api (NestJS)
Config
| Env file | ค่า |
|---|---|
.env.production:6 | APP_CONNECT_API=https://vtrcapi.redcross.or.th/2way-api |
.env.uat:6 | https://uat-vtrcapi.redcross.or.th/2way-api |
| Client | process.env.appConnectAPI (next.config.js:53) |
ขอบเขตการใช้งาน
- Auth: login, verifyToken, redirectbypass, Forgot password flows
- Announces CRUD + types
- Surveys CRUD + summary + adminApprove/adminReject
- Employee org tree dropdowns
- Complaints/Feedback multi-step approval
ยืนยัน alignment กับ backend: path api/v1/surveys/types ตรงกับ 2way-api @Controller('surveys') (ดูเอกสาร volume ของ 2way-api)
ความเสี่ยงข้าม repo
Login ยิง endpoint เดียวกับที่มี backdoor credential ใน 2way-api (SEC-2WAYAPI-01) — ความปลอดภัยของหน้า Login จึงพึ่งพา backend โดยตรง
Integration 2 — chat-center-api (Domain Microservice)
Config สองทางที่ชี้ปลายทางเดียวกัน
| กลไก | ประกอบ URL อย่างไร |
|---|---|
appConnectChatCenterAPI | absolute base จาก APP_CONNECT_API_CHAT เช่น https://vtrcapi.../chat-center-api/api/v1 แล้วต่อ /teamAdmin/list |
fetchRedCrossAPI + chatCenterPath | ${APP_PATH} + chat-center-api/api/v1 + /chat/rooms |
ทั้งคู่ต้องชี้ host เดียว — production: vtrcapi.redcross.or.th (.env.production:7,10)
REST surface ที่ frontend เรียก (ยืนยันจากโค้ด)
| ฟังก์ชัน / call site | Method | Path (หลัง base) |
|---|---|---|
getTeamAdminList | GET | /teamAdmin/list |
| teamAdmin create/update | POST/PUT | /teamAdmin, /teamAdmin/{teamId} |
listMember search | GET | /teamAdmin/listMember?fullName= |
listCareTaker | GET/POST | /teamAdmin/listCareTaker |
getTagList | GET | /tags/list |
getChatRoomList | GET | /chat/rooms |
putChatRoom | PUT | /chat/{id} |
putOpenChatRoom | PUT | /chat/open/{id} |
| chat history | GET | /chat/chatRoomHistory?roomEmpCode= |
getChatListNoti | GET | /chat/listNoti |
putChatNoti | PUT | /chat/Noti/{id} |
getChatRoomStatusHistory | GET | /chat/roomStatusHistory |
postCreateChatHistory | POST | /createChatHistory |
| appointment | GET/POST/PUT | /appointment, /appointment/{id} |
| satisfaction report | GET | /satisfactedurvey/reportServey |
| satisfaction public/gen | POST | /satisfactedurvey/public, /genSurvey |
แหล่ง: utils/chatCenterApi.tsx ทั้งไฟล์ + ChatCenter/index.tsx + NotificationListForm.tsx + teamAdminModal/*
WebSocket
io.connect(`${process.env.appConnectWebSocket}`, {
transports: ["websocket"],
path: "/chat-center-ws/socket.io",
});(ChatCenter/index.tsx:173-176)
- Production WS host:
wss://vtrcapi.redcross.or.th(.env.production:11) - Path แยกจาก REST prefix — reverse proxy ต้อง route
/chat-center-ws/ไป chat-center service
Cross-group coupling
chat-center-api อยู่ในกลุ่ม Domain Microservices ตาม workspace map — repo นี้ในกลุ่ม 2way Platform เรียกข้ามกลุ่มโดยตรง ควรบันทึกใน canonical truths
Hardcoded room ใน services/chat-center.tsx
`${process.env.appConnectChatCenterAPI}/chat/chatRoomHistory?roomEmpCode=${"U4bc7f4b3936c4eebf2e1aabf72e1caab"}`(services/chat-center.tsx:6) — ค่าทดสอบค้าง; หน้า ChatCenter จริงใช้ chatRoom?.empCode แทน (index.tsx:109)
Integration 3 — 2way-vtrc-api (Express legacy) ผ่าน appConnectChatAPI
Config
| Shell | APP_CONNECT_API_BASIC=https://vtrcapi.redcross.or.th/2way (.env.production:9) |
| Client | appConnectChatAPI (next.config.js:57) |
| ชื่อที่ทำให้สับสน | มีคำว่า "Chat" แต่ไม่ใช่ chat-center |
Endpoints ที่ยืนยันจาก call sites
| Path | ใช้ที่ |
|---|---|
/getProfile | Announce, Survey, Complaint, Incident (LIFF) |
/verifyUserLine, /verifyOTPUserLine, /createUserLine | Register RC |
/verifyUserLine/cu, /verifyOTPUserLine/cu, /createUserLine/cu | RegisterCu |
/getListFAQs, /createQuestion , /sendMessageLineFAQsStepYes | Problem LIFF |
/getListFAQs, /addNewFAQs, /updateFAQs, /updateStatusFAQs | Question backoffice |
/appointment | NotificationListForm.tsx:77 (POST ไป appConnectChatAPI — คนละ base กับ chat-center appointment) |
/dropdownDivision, /dropdownDepartment, /getUserByCondition | employee picker ใน Announce (อ้างจากเอกสารเดิม + Form paths) |
ข้อสรุป canonical: backend หลักของหน้าฝั่งพนักงานคือ 2way-vtrc-api ไม่ใช่ NestJS 2way-api
Integration 4 — LINE LIFF (@line/liff)
- Dynamic import ใน
_app.tsx:90-93เมื่อ path เป็นline/line-cu liff.init({ liffId })แล้วบังคับliff.loginถ้ายังไม่ login (:97-99)- LIFF ID แยก RC/CU และ prod/non-prod (ตารางใน 02-core-pipeline)
- ใช้ระบุตัวผู้ใช้ LINE แทน username/password ของ backoffice
- มีไฟล์ backup
_app.tsx.bkใน pages — legacy backup ตามกฎ workspace
Integration 5 — incident-management-api (UNVERIFIED)
Config
APP_CONNECT_API_INCIDENT → production https://vtrcapi.redcross.or.th/incident-management-api (.env.production:8)
Call sites
| ไฟล์ | Path |
|---|---|
services/line/incidents.tsx:6 | /master/list/003 |
services/line/incidents.tsx:14+ | /incidents/list/empCode/{empCode}, /incidents/{id} |
ChatCenter/index.tsx:146 | /incidents/chat-center/list/{empCode} |
Repo incident-management-api ไม่มีใน workspace ณ เวลาเขียนเอกสาร — โครงสร้าง auth/schema ฝั่ง server ยืนยันไม่ได้ → ระบุ UNVERIFIED
Integration 6 — Sentry (@sentry/nextjs)
ไฟล์ที่เกี่ยวข้อง
| ไฟล์ | บทบาท |
|---|---|
sentry.client.config.js | Sentry.init ฝั่ง browser |
sentry.server.config.js | Sentry.init ฝั่ง Node (SSR / API routes ของ Next) |
src/pages/_error.tsx | Sentry.captureException + flush(2000) |
next.config.js:11-23,79-80 | withSentryConfig ถูก comment ออก — export moduleExports ตรง ๆ |
Init options
Sentry.init({
dsn: SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN
|| 'https://…@o1092051.ingest.sentry.io/6113872', // hardcoded fallback
tracesSampleRate: 1.0,
});(sentry.client.config.js:7-12, sentry.server.config.js:7-12)
ข้อสังเกต:
- DSN fallback ถูก commit ใน repo — ถ้า env ไม่ตั้ง DSN ก็ยังส่ง event ไป org ที่ hardcode
tracesSampleRate: 1.0= ส่งทุก transaction (ต้นทุน/噪声 สูงใน production)- Webpack plugin สำหรับ upload source map ไม่ได้เปิด เพราะ
withSentryConfigcomment ออก (next.config.js:79-80) — stack trace ใน Sentry อาจไม่มี source map จาก build นี้ _error.tsxจับ error ของ Next pages และเรียกSentry.captureExceptionทั้ง client workaround และgetInitialProps(_error.tsx:18,52,65-67)
สิ่งที่ Sentry ไม่ครอบ
- Axios error ที่ถูก
resolve(error)ใน wrapper — ไม่ throw → ไม่ถึง Error Boundary /_errorโดยอัตโนมัติ console.logของ production ถูก mute ใน_appแต่ไม่ใช่ Sentry breadcrumb pipeline
Integration 7 — i18n และ static public assets
next-i18next: localesth,en;defaultLocale: 'th';localeDetection: false(next-i18next.config.js:2-6)- ไฟล์แปลอยู่ที่
public/locales/{th,en,de}/— มีdeในโฟลเดอร์แต่ config ไม่ใส่deในlocalesarray - Navbar / menu มาจาก JSON ใต้
public/mockDatas/ไม่ใช่จาก API
Group / Approver admin — สรุปตำแหน่งในระบบนี้
คำว่า "approver admin" ในบริบท repo นี้แตกเป็นหลายกลไก (ไม่ใช่ meeting approver):
| กลไก | ที่อยู่ | Backend |
|---|---|---|
| Chat Center teamAdmin (ทีม + สมาชิก + tags) | ChatCenter/admin | chat-center-api /teamAdmin/* |
| Survey adminApprove / adminReject | services/surveys.tsx | 2way-api |
| Complaint adminAssign / secretary / superAdmin* | Feedback/Edit/Form.tsx | 2way-api /api/v1/complaints/* |
| Announce contentAssigns (ผู้รับประกาศ) | Announce/*/Form.tsx + employee.tsx | 2way-api announces |
profile.level === 1 → isSuperAdmin | utils/auth.tsx:71 | ใช้ใน UI เงื่อนไขสิทธิ์ |
Embedded / build artifacts
| Artifact | สร้างจาก | Deploy ใช้จริง? |
|---|---|---|
.next/ | yarn build | ใช่ — Docker copy เข้า runner (Dockerfile:31) |
out/ | yarn out / yarn export (package.json:9,14) | Script มี; pipeline หลักใช้ next start ไม่ใช่ static host จาก out/ |
| Docker image | bitbucket-pipelines.yml build-docker-image | Push GCP registry พร้อม tag commit |
.env.production ใน image | Dockerfile:27 | ฝังใน image — เปลี่ยน API host ต้อง rebuild |
ไม่มีโฟลเดอร์ build/ แบบ CRA — เป็น Next .next ล้วน
สิ่งที่ไม่มี (อย่าสมมติ)
- ไม่เชื่อม
meeting-vtrc-api/meeting-backoffice/meeting-backoffice-new - ไม่เชื่อม GraphQL ของ
vtrc-api/ Apollo - ไม่มี Redis / queue client ฝั่ง frontend
- ไม่มี Prisma schema / migration ใน repo นี้