fix(hrm): thông báo rõ ràng + ổn định, provisioning Keycloak, sửa xoá nhân viên
Thông báo (notification):
- Nhân viên mới: bỏ Username, sắp xếp lại Mã NV · Chức vụ · Phòng cho gọn.
- Nghỉ phép & OT: định dạng ngày dd/MM/yyyy (gộp khi cùng ngày), thêm "Duyệt bởi / Từ chối bởi: <tên>" để biết ai xử lý đơn.
- Chống trùng (ổn định hơn): publish() bỏ qua noti y hệt (cùng người nhận
- type + title + body) trong 10s gần đây, chặn double-submit/retry tạo thông báo lặp. Áp dụng cả employee-service và attendance-service.
Đăng nhập SSO cho tài khoản mới (Keycloak provisioning):
- Thêm KeycloakAdminService: đồng bộ vòng đời user sang Keycloak qua Admin REST (tạo + set mật khẩu + business_role, đổi mật khẩu, đổi vai trò, khoá/mở, xoá). Best-effort: Keycloak lỗi không chặn luồng HRM.
- AuthService gọi đồng bộ ở createUser/resetPassword/updateRole/lock/delete.
- Cấu hình app.keycloak.* (url/realm/admin/enabled); mật khẩu admin lấy từ .env, thiếu thì tự tắt provisioning.
Sửa xoá nhân viên (UX ~8s + báo lỗi sai):
- FE: guard chống double-click, toast loading→done, coi 404/409 là đã xoá.
- BE: xử lý OptimisticLockingFailureException → 409; rút timeout gọi ChamCong (1.5s) để không treo khi service phụ chậm.