Skip to content

Type Deep Dive — Ticket Lifecycle And Results

1. Mục tiêu của flow này

Flow ticket lifecycle xử lý 3 việc khác nhau nhưng đang đi chung một runtime:

  • create/update dữ liệu ticket,
  • đổi status theo assignee hoặc kết quả,
  • sinh ticket kế tiếp nếu complete dẫn sang follow-up mới.

Điểm quan trọng: FE orchestrate nhiều mutation, nhưng backend mới là nơi quyết định transition hợp lệ và việc có duplicate ticket hay không.

2. Create / Update Orchestration ở FE

2.1 Save flow thực tế

TicketCreate.tsx đang chạy theo chuỗi sau (TicketCreate.tsx:184-340):

text
Submit form
  -> createTicket hoặc updateTicket
  -> nếu có newCallObj thì update incall_call.ticket_id
  -> nếu có assignee và status hiện tại là new -> changeStatusTicket(assigned)
  -> nếu bỏ assignee và status hiện tại là assigned -> changeStatusTicket(new)
  -> nếu có result -> changeStatusTicket(completed)
  -> nếu backend trả new_ticket_id và result cho phép -> route sang ticket mới
  -> insert ticket log

2.2 Rule ngầm trong FE

RuleNguồn
make_consultant_appointmentmove_consultant_appointment bắt buộc có callBackDate + appointmentDateTicketCreate.tsx:185-194
Save với assignee trên ticket new sẽ auto chuyển sang assignedTicketCreate.tsx:223-243
Save bỏ assignee trên ticket assigned sẽ auto chuyển về newTicketCreate.tsx:244-264
Save với result sẽ luôn gọi changeStatusTicket sang completedTicketCreate.tsx:266-285

3. Transition Engine ở Backend

3.1 Contract

changeStatusTicket nhận:

  • ticket_id
  • status_id
  • note
  • due_date
  • appointment_start_at

Backend load ticket hiện tại, gọi ticket.ValidateNewStatus(...), rồi mới xử lý transition (change_status_ticket.go:21-46).

3.2 Hai nhánh xử lý

NhánhHành vi
status != completedupdate_ticket_by_pk với status_idoutput_note
status == completedgọi ticket.Duplicate(...) và trả new_ticket_id nếu có

Nghĩa là completed ở đây không phải "đóng ticket cũ rồi xong", mà là điểm vào của chain engine.

4. Result Và Sinh Ticket Mới

4.1 Result không sinh ticket mới

FE đang chặn redirect sang ticket mới với các result:

  • cancel_consultant_appointment
  • cancel_service
  • wrong_number
  • wrong_information
  • completed

Đây là whitelist ở UI để coi kết quả là terminal outcome (TicketCreate.tsx:174-181).

4.2 Result có thể sinh ticket mới

Nếu changeStatusTicket trả new_ticket_id và result không nằm trong nhóm trên:

  • popup mode: emit refresh(new_ticket_id) rồi đóng popup,
  • full page mode: route sang ROUTE_TICKET_UPDATE hoặc ROUTE_TICKET_DETAIL của ticket mới.

Hệ quả:

  • FE state sau submit có thể nhảy sang ticket khác,
  • QA phải xác minh cả ticket cũ lẫn ticket mới,
  • analytics nếu chỉ đếm một ticket hoàn tất có thể miss chain length.

5. Event Side Effects

5.1 Ticket insert

ticket_insert.go đang làm thêm các side effects sau khi row mới được tạo:

  • refresh service groups qua UpdateTicketServiceGroups,
  • ghi KPI log MetricTicketCreated,
  • ghép keywords của ticket với keywords của address,
  • thêm assignee/in-charge vào account.related_people nếu có.

5.2 Ticket update

ticket_update.go đang làm:

  • nếu output_note có dữ liệu và status chuyển sang completed thì tạo customer_note,
  • refresh keywords,
  • cập nhật account.related_people khi assignee/in-charge thay đổi.

Như vậy history thực tế không chỉ nằm ở ticket_history_log, mà còn kéo side effects sang customer note và account relation.

6. Appointment Và Due Date

FieldVai trò trong lifecycle
due_dateCallback / follow-up deadline cho ticket hiện tại hoặc ticket kế tiếp
appointment_start_atMốc lịch hẹn dùng trong completed/duplicate path
appointment_idKhi tạo từ appointment hoặc gắn với appointment

remind_ticket_tomorrow không query ticket theo due date. Nó query appointment ngày mai trước, rồi map ngược ra ticket qua appointment_id. Đây là rule khác hẳn với remind_ticket_today.

7. QA Focus

  1. Tạo ticket có assignee từ đầu để xác minh auto new -> assigned.
  2. Sửa ticket assigned rồi bỏ assignee để xác minh assigned -> new.
  3. Chốt result thuộc nhóm terminal để xác minh không redirect sang ticket mới.
  4. Chốt result thuộc nhóm follow-up để xác minh backend trả new_ticket_id và UI chuyển sang ticket kế tiếp.
  5. Xác minh output_note khi completed có sinh customer_note.
  6. Xác minh tạo ticket từ call runtime có update incall_call.ticket_id.

8. Rủi ro / Findings kỹ thuật

IDMứcFinding
LC-F01P1FE đang chồng nhiều mutation trong một submit flow, nên retry/error handling có thể rơi vào trạng thái partial success.
LC-F02P1changeStatusTicket trả new_ticket_id nhưng UI decision lại phụ thuộc thêm vào whitelist result phía FE; đây là dual-control dễ drift.
LC-F03P2note trong action contract và output_note ở update path rất gần nghĩa nhưng không hoàn toàn đồng nhất, dễ gây nhầm khi map form fields.