Vấn đề
Ở CloudJet, tôi làm backend cho một nền tảng HRM và đánh giá KPI. Sản phẩm bao gồm hồ sơ nhân viên, phòng ban, chu kỳ KPI, đặt mục tiêu, đánh giá hiệu suất và phê duyệt.
Một lần đánh giá liên quan đến nhiều người. Nhân viên đặt mục tiêu và nộp kết quả, trưởng phòng xem xét, nhân sự theo dõi cả chu kỳ, còn quản trị viên lo phần cấu hình. Mỗi vai trò trong bốn vai trò này cần thấy một phần dữ liệu khác nhau. Nhân viên không được đọc đánh giá của đồng nghiệp, và hàng chờ phê duyệt của trưởng phòng chỉ nên chứa hồ sơ của phòng mình.
Kết quả đánh giá còn ảnh hưởng đến quyết định về con người, nên lịch sử rất quan trọng. Ai duyệt gì, ai từ chối, vào lúc nào đều phải truy lại được. Phần báo cáo cũng có bài toán tải riêng: xuất báo cáo Excel, PDF hay tải dashboard có thể chậm nếu mọi request đều tự làm hết việc.
Tôi đã làm gì
Schema chuẩn hóa quanh vòng đời đánh giá
Tôi thiết kế và hiện thực backend Django REST cùng các schema PostgreSQL cho nhân viên, vai trò, KPI template, tiêu chí đánh giá, mục tiêu, kết quả đánh giá, lịch sử phê duyệt và audit log. KPI template và tiêu chí đánh giá nằm ở bảng riêng, tách khỏi mục tiêu và kết quả được ghi nhận theo chúng.
Đổi lại là nhiều bảng và nhiều join hơn một thiết kế phẳng. Tôi chấp nhận vì mô hình chuẩn hóa giữ một nguồn sự thật cho mỗi dữ kiện, điều quan trọng khi điểm số hay quyết định phê duyệt bị hỏi lại sau này.
Phân quyền theo bốn vai trò
Tôi hiện thực role-based access control cho quản trị viên, nhân sự, trưởng phòng và nhân viên. Quy tắc truy cập giới hạn bản ghi nào, dữ liệu KPI nào và hàng chờ phê duyệt nào mà mỗi vai trò được chạm tới, và API kiểm tra chúng ở phía server.
Cái giá là endpoint mới nào cũng phải tính kỹ và test quy tắc truy cập. Việc này làm chậm tính năng một chút, và đó là chỗ đáng để chậm, vì bỏ sót một quy tắc trên dữ liệu đánh giá là vấn đề quyền riêng tư.
Tính điểm có trọng số, theo dõi trạng thái dễ audit
Tôi phát triển phần tính điểm KPI có trọng số cùng các bản tổng hợp theo cá nhân và theo phòng ban. Mỗi hồ sơ đi qua các trạng thái được theo dõi, và lịch sử phê duyệt cùng audit log ghi lại đường đi của nó.
Giữ đầy đủ dấu vết nghĩa là lưu nhiều dòng hơn và viết thêm code ở mỗi lần đổi trạng thái. Bù lại, một điểm số bị tranh cãi có thể được giải thích bằng dữ liệu thay vì trí nhớ.
Thông báo gắn với sự kiện trong workflow
Tôi xây các workflow thông báo cho việc nộp, phê duyệt, từ chối và nhắc nhở, để mọi người biết có việc cần mình xử lý mà không phải tự vào app kiểm tra.
Đổi lại là thêm thành phần quanh mỗi lần đổi trạng thái, và thêm một thứ phải test ở mỗi bước của luồng. Tôi chấp nhận vì một hồ sơ nằm im trong hàng chờ của ai đó mà không ai hay sẽ làm cả chu kỳ đứng lại.
Báo cáo nặng chạy nền, API dashboard nhẹ hơn
Tôi xây phần tạo báo cáo Excel và PDF bất đồng bộ bằng AWS SQS và ECS. API đẩy một job báo cáo vào queue, và worker tạo file bên ngoài request. Với dashboard, tôi tối ưu API bằng filtering, pagination và selective prefetching, viết tài liệu bằng OpenAPI và có test đi kèm.
Báo cáo chạy nền nghĩa là người dùng phải chờ file thay vì nhận ngay trong cùng response, và có thêm một service để deploy và theo dõi. Như vậy vẫn tốt hơn để web request bị giữ lâu vì các lần export dài.
Kết quả
Nền tảng có một luồng đánh giá duy nhất từ đặt mục tiêu, nộp, xem xét đến phê duyệt, với quyền truy cập chia theo bốn vai trò. Lịch sử phê duyệt và audit log giúp truy lại được luồng đó. Việc tạo báo cáo chạy nền qua queue và worker, còn các API dashboard có tài liệu và test. Tôi không có số liệu đo về hiệu năng hay mức sử dụng từ dự án này, nên kết quả được mô tả định tính.
Nếu làm lại
Ngay từ đầu, tôi sẽ viết các quy tắc truy cập thành một permission matrix duy nhất, theo từng vai trò và từng resource, rồi sinh test từ đó. Như vậy quy tắc dễ review hơn và khó bỏ sót hơn khi có endpoint mới. Tôi cũng sẽ đo thời gian cho report worker và API dashboard từ ngày đầu, để có thể chứng minh hiệu quả tối ưu bằng con số.