Skip to content

Achievement - Technical Map

Source map

Frontend

FileVai trò
diva-admin/src/modules/achievement/module.tsĐăng ký route, navigation, permission config
diva-admin/src/modules/achievement/types.tsRoute constants và full-scope roles
diva-admin/src/modules/achievement/pages/AchievementManagement.tsxTab quản lý huy hiệu cá nhân/phòng ban
diva-admin/src/modules/achievement/pages/AchievementProgram.tsxTab quản lý chương trình cá nhân/phòng ban
diva-admin/src/modules/achievement/pages/PersonalManagementDetail.tsxDetail nhân viên
diva-admin/src/modules/achievement/pages/DepartmentManagementDetail.tsxDetail phòng ban
diva-admin/src/modules/achievement/graphql/achievement-program.graphqlQuery/mutation cá nhân
diva-admin/src/modules/achievement/graphql/department-achievement-program.graphqlQuery/mutation phòng ban
diva-admin/src/modules/achievement/compositions/useProgramImport.tsValidate và build file import cá nhân
diva-admin/src/modules/achievement/compositions/useDepartmentProgramImport.tsValidate và build file import phòng ban

Backend

FileVai trò
diva-backend/services/controller/migrations/default/1718883205125_employee_achievement/up.sqlTạo bảng cá nhân và program
diva-backend/services/controller/migrations/ecommerce/1718785620656_department_program/up.sqlTạo bảng phòng ban
diva-backend/services/controller/migrations/default/1720069376030_add_achievement_role_module/up.sqlGán role module cho achievement
diva-backend/services/controller/migrations/default/1720516140850_add_permissions/up.sqlThêm role module cho nhiều role khác
diva-backend/services/controller/metadata/databases/default/tables/*.yamlHasura metadata cho bảng cá nhân
diva-backend/services/controller/metadata/databases/ecommerce/tables/*.yamlHasura metadata cho bảng phòng ban
diva-backend/services/crm-api/action/apply_employee_program.goAction backend áp dụng program cá nhân thành link huy hiệu

Route map

RouteComponentGuard / moduleId
/a/achievement-managementAchievementManagementachievement_management
/a/achievement-management/account/:accountCodePersonalManagementDetailachievement_management
/a/achievement-management/department/:departmentCodeDepartmentManagementDetailachievement_management
/a/achievement-programAchievementProgramprogram_management

Route gốc /a redirect sang /a/achievement-program (diva-admin/src/modules/achievement/module.ts).

Permission / navigation

ItemRule
Sidebar groupmoduleId = "achievement", chỉ hiện trên PLATFORM_ADMIN
Submenu huy hiệuachievement_management, yêu cầu FULL_ACHIEVEMENT_MANAGEMENT_ROLES
Submenu chương trìnhprogram_management, không gắn permissions, nhưng vẫn bị module/role gate ở router
Router guardCho phép nếu user có module tương ứng hoặc là achievement trên platform admin

GraphQL operations

4.1 Cá nhân

OperationTypeDùng ở đâuGhi chú
GetProgramqueryProgramTableLấy danh sách program cá nhân + aggregate
GetProgramForSelectqueryProgramSelect, import validatorDùng làm select box và kiểm tra program code
GetProgramByPkqueryProgramCreate, ProgramDetailLoad detail 1 program
CreateProgrammutationProgramCreateInsert program + nested link
UpdateProgramByPkmutationProgramCreateUpdate program + replace toàn bộ links
DeleteProgrammutationCó trong file graphql nhưng chưa thấy UI gọi trực tiếp
UpdateProgramEmployeeAchievementLinkmutationProgramApply, ProgramImportBulk insert employee_achievement_link
GetProgramEmployeeAchievementLinkqueryPersonalAchievementTable, ProgramDetailLấy link nhân viên - huy hiệu
GetAccountWithAchievementLinkqueryPersonalManagementDetailLoad detail account + achievements

4.2 Phòng ban

OperationTypeDùng ở đâuGhi chú
GetDepartmentProgramqueryDepartmentProgramTableLấy danh sách department_program + aggregate
GetDepartmentProgramForSelectqueryDepartmentProgramSelect, import validatorDùng làm select box và kiểm tra program code
GetDepartmentProgramByPkqueryDepartmentProgramCreate, DepartmentProgramApplyLoad detail 1 department_program
CreateDepartmentProgrammutationDepartmentProgramCreateInsert department_program + nested link
UpdateDepartmentProgramByPkmutationDepartmentProgramCreateUpdate + replace link
DeleteDepartmentProgrammutationCó trong file graphql nhưng chưa thấy UI gọi trực tiếp
UpdateProgramDepartmentAchievementLinkmutationDepartmentProgramApply, DepartmentProgramImportBulk insert department_achievement_link
GetProgramDepartmentAchievementLinkqueryDepartmentAchievementTable, DepartmentProgramDetailLấy link phòng ban - huy hiệu
GetDepartmentWithAchievementLinkqueryDepartmentManagementDetailLoad detail department + achievements

Data model

5.1 Bảng cá nhân

TableKey columnsÝ nghĩa
achievementcode, name, description, image_urlDanh mục huy hiệu cá nhân
programcode, name, duration_from, duration_to, description, created_atChương trình cá nhân
program_achievement_linkachievement_code, program_codeLink program -> achievement
program_manager_linkaccount_code, program_codeManager của program
program_employee_linkaccount_code, program_codeThành viên program
employee_achievement_linkaccount_code, achievement_code, program_code, created_atHuy hiệu đã phát cho nhân viên

5.2 Bảng phòng ban

TableKey columnsÝ nghĩa
department_achievementcode, name, description, image_urlDanh mục huy hiệu phòng ban
department_programcode, name, duration_from, duration_to, description, created_atChương trình phòng ban
department_program_achievement_linkachievement_code, program_codeLink program -> achievement
department_program_manager_linkaccount_code, program_codeManager của program
department_achievement_linkdepartment_code, achievement_code, program_code, created_atHuy hiệu đã phát cho phòng ban

5.3 Defaults và code prefix

EntityPrefixSequence
achievement.codeHHCNachievement_seq
program.codeCTCNprogram_seq
department_achievement.codeHHPBachievement_seq
department_program.codeCTPBprogram_seq

Flow triển khai

6.1 List và detail

  1. AchievementManagement / AchievementProgram đọc query.tab để chọn tab mặc định.
  2. Danh sách chính dùng XTable + pagination trên GraphQL aggregate.
  3. Search input chỉ lọc theo _ilike trên codename.
  4. Detail screens query theo accountCode hoặc departmentCode rồi filter tiếp theo programCode, keywords, createdAt.

6.2 Create / update program

  1. Form lấy dữ liệu hiện tại bằng GetProgramByPk hoặc GetDepartmentProgramByPk.
  2. Khi create:
    • insert master table,
    • nested insert managers,
    • nested insert achievements.
  3. Khi update:
    • update_*_by_pk,
    • delete toàn bộ *_achievement_link cũ,
    • insert lại toàn bộ link mới,
    • delete toàn bộ *_manager_link cũ,
    • insert lại manager link mới.

6.3 Apply

  1. Chọn program.
  2. Load list huy hiệu thuộc program.
  3. Chọn nhân viên/phòng ban hoặc chọn tất cả.
  4. Build mảng { program_code, achievement_code, account_code|department_code, created_at }.
  5. Gọi bulk insert mutation.

6.4 Import

  1. Load file Excel bằng exceljs.
  2. Dò 4 cột theo template.
  3. Validate program, achievement, account/department, created_at.
  4. Sau khi hợp lệ mới cho phép bulk insert.

Hasura permissions

7.1 Cá nhân

TableSelectInsertUpdateDelete
achievementuseruseruseruser
employee_achievement_linkuseruser-user
programuseruseruseruser
program_achievement_linkuseruser-user
program_manager_linkuseruser-user

7.2 Phòng ban

TableSelectInsertUpdateDelete
department_achievementuseruseruseruser
department_achievement_linkuseruser-user
department_programuseruseruseruser
department_program_achievement_linkuseruser-user
department_program_manager_linkuseruser-user

Observability / NFR

Hạng mụcGhi chú
PaginationDùng aggregate count làm rowsNumber để XTable tính trang
Network policyCác query quan trọng đều network-only để tránh cache cũ
ValidationImport không xử lý theo transaction; dữ liệu phải sạch trước khi mutate
UX stateMột số component lưu userBehavior.limit theo route key riêng

Rủi ro / Findings kỹ thuật

MứcFileVấn đề
P1diva-admin/src/modules/achievement/compositions/useProgramImport.ts:105-160sheet.eachRow(async ...) không được await, nên kiểm tra row có thể chưa xong nhưng progress/import đã tiếp tục.
P1diva-admin/src/modules/achievement/compositions/useDepartmentProgramImport.ts:105-163Cùng lỗi async iteration như luồng import cá nhân.
P2diva-admin/src/modules/achievement/components/AchievementManagement/PersonalAchievementTable.tsx:39-41,146-151Key đọc userBehavior và key ghi userBehavior không khớp (-personal vs -personal-detail), limit đã chọn khó được persist đúng.
P2diva-admin/src/modules/achievement/components/AchievementManagement/DepartmentAchievementTable.tsx:42-45,150-155Lỗi persist limit tương tự ở tab phòng ban.
P2diva-admin/src/modules/achievement/components/AchievementProgram/ProgramDetail.tsx:21-27 + diva-backend/services/controller/metadata/databases/default/tables/public_account.yamlQuery dùng filter department_id trên account, trong khi metadata account hiện chỉ thể hiện relation departments; đây là điểm cần xác minh vì có rủi ro không khớp schema hiện tại.