
Core Beat
Mục lục
- 0. Giới thiệu chung
- 1. Xác thực & phiên đăng nhập
- 2. Phân quyền & quản lý người dùng
- 3. Tổ chức & hồ sơ nhân sự
- 4. Ca, lịch làm việc & chấm công
- 5. Nghỉ phép
- 6. Tăng ca (OT)
- 7. Dự án & công việc
- 8. Luồng duyệt dùng chung
- 9. Tính lương
- 10. Tài sản
- 11. Chi phí & quỹ tiền
- 12. Ngân sách & mua sắm
- 13. Thông báo
- 14. Chưa triển khai
Kiến trúc kỹ thuật
Sơ đồ tổng quan
Các tầng xếp theo đường đi của một request, từ trình duyệt tới database.
Trình duyệt
apps/webbuild tĩnhCông nghệ giao diện
- ~45 feature ở
src/features/<tên>, mỗi feature trùng tên module API tương ứng. - Access token chỉ ở bộ nhớ. Web Locks và BroadcastChannel để nhiều tab dùng chung một lần refresh.
- usePermissions() ẩn/hiện menu và nút theo quyền; API vẫn là nơi kiểm tra quyền thật.
- Bản dịch là file TypeScript: thiếu hoặc sai khóa là lỗi biên dịch, không phải lỗi lúc chạy.
Authorization: Bearer (15 phút) · cookie httpOnly refresh (14 ngày)Biên & proxy
Coolifycontainer web- Một domain cho web và API: không cần CORS, không cần
VITE_API_URL. - nginx phục vụ file tĩnh của Vite và chuyển
/api/*sangapi:3000. TRUST_PROXYbật đểreq.iplà IP public; chấm công kiểm tra theo dải IP văn phòng.
/api/* → api:3000 · mạng riêng DockerAPI
apps/apicontainer apiCông nghệ
Đường đi của một request
- AuthGuardKiểm JWT, đọc lại user từ database mỗi request
- PermissionGuard
@RequirePermissionkiểm có quyền - Zod parseSchema lấy từ
contracts - Service + DataScopeSinh điều kiện lọc OWN → ALL
- TransactionPrisma, kèm
AuditService - ApiError
fieldErrorsgắn thẳng vào ô form
Hạ tầng dùng chung
Một engine cho mọi loại đơn; handler chạy cùng transaction; ủy quyền, nhắc, leo thang.
Phép, ngân sách, quỹ tiền, công nợ. Muốn sửa phải ghi bút toán đảo.
mathjs BigNumber + allowlist từng nút; dùng cho lương và trường tùy chỉnh.
RBAC + phạm vi dữ liệu; cache 60 giây trong tiến trình.
policy_settings, thuế, bảo hiểm, hệ số OT; đổi luật không sửa code.
DailyShiftsService: nguồn ca duy nhất cho chấm công, phép, OT.
setInterval trong tiến trình API; chưa có hàng đợi riêng.
AES-256-GCM cho CCCD, số tài khoản (*_enc).
Thông báo trong ứng dụng; audit_logs cho mọi thay đổi.
Module nghiệp vụ · src/modules/<tên>
legal-entities, branches, departments, positions, grades, employeesshifts, work-schedules, holidays, shift-rosters, attendance, attendance-periods, worklogsleave-types, leave-policies, leave-requests, leave-balancesot-requestsprojects, project-types, project-templates, taskspay-items, payroll-params, payroll-periodsasset-categories, assetsexpense-categories, expense-claims, cash-funds, employee-debtsbudgets, purchase-requests, purchase-orders, vendorsauth, users, rbac, approvals, notificationsTruy cập dữ liệu
trong container apicontainer api- Migration viết bằng SQL, chạy
prisma migrate deploykhi API khởi động. - Prisma Client sinh từ schema của database, kiểu dữ liệu chặt từ truy vấn tới giao diện.
- Điều kiện phạm vi dữ liệu ghép bằng
AND; cột ngày nhận đối tượngDate.
pg · migration · TimeZone=UTCCơ sở dữ liệu
PostgreSQLcontainer postgres- Khóa chính uuid; bảng nhật ký, sổ cái lớn dùng
bigint identity. - Trạng thái dùng
text+CHECKthay cho ENUM. - Hiệu lực theo ngày, chống chồng lấn bằng
EXCLUDE USING gist. - Trigger chặn
UPDATE/DELETEtrên các bảng sổ cái. - Snapshot cho bảng lương và người duyệt lúc gửi đơn.
- Cột
*_encgiữ dữ liệu đã mã hóa; không bao giờ có bản rõ.
Phát triển & CI
gốc repopnpm lint,typecheck,testchạy qua Turborepo.test:integrationdùng PostgreSQL thật, không mock database.- CI chạy lint, typecheck, test, build với service PostgreSQL 16.
I.1. Tech stack
Monorepo quản lý bằng pnpm workspaces (pnpm 10) + Turborepo, gồm 3 package:
| Package | Công nghệ chính |
|---|---|
apps/api | NestJS 12 chạy ESM, TypeScript 6, Prisma 7 (driver adapter @prisma/adapter-pg, không dùng engine Rust mặc định), PostgreSQL 16, @nestjs/jwt (JWT HS256), @node-rs/argon2 (băm mật khẩu), mathjs (biểu thức công thức an toàn), exceljs (xuất Excel) |
apps/web | React 19, Vite 8, Tailwind CSS 4, shadcn/ui, TanStack Query 5 (gọi API, cache), React Hook Form 7 + @hookform/resolvers (zodResolver), react-router 8, i18next + react-i18next (đa ngôn ngữ), react-organizational-chart (sơ đồ tổ chức) |
packages/contracts | Zod 4: toàn bộ DTO/schema dùng chung, build ra .d.ts + .js, import ở cả hai app qua workspace:* |
Node >= 22. Không dùng class-validator, không dùng ORM khác ngoài Prisma, không có backend-for-frontend riêng, web gọi thẳng API NestJS.
I.2. Cấu trúc monorepo & quy ước module
Module nghiệp vụ backend (apps/api/src/modules/<ten-module>) và frontend (apps/web/src/features/<ten-module>) dùng cùng một tên kebab-case, số nhiều, ví dụ: leave-types, leave-requests, attendance-logs, worklogs, overtime-requests → hiện có khoảng 45 module mỗi phía (approvals, assets, attendance, budgets, cash-funds, departments, employees, leave-, ot-requests, payroll-, projects, project-types, purchase-, tasks, users, vendors, worklogs...).
packages/contracts chỉ chứa schema Zod + type suy ra bằng z.infer, không chứa logic nghiệp vụ; một DTO chỉ định nghĩa một lần ở đây, API và web import từ @corebeat/contracts, không khai báo lại type ở hai nơi. Các hàm tính toán thuần (không phụ thuộc DB/HTTP) như computeAttendanceDay, planLeaveDays, reconcileOt, applyMovement, payroll-calc.ts... cũng đặt trong contracts hoặc common/ của API để dùng chung và test độc lập.
Khác biệt nghiệp vụ giữa các khách hàng giải quyết theo thứ tự ưu tiên: dữ liệu cấu hình → công thức lương → policy_settings → strategy → hook sự kiện, không bao giờ rẽ nhánh theo tên khách hàng trong code.
I.3. Thiết kế database
PostgreSQL 16 với 140 bảng và 5 view, chia theo 15 nhóm module, từ dữ liệu dùng chung đến thông báo. Migration viết bằng SQL và áp dụng chỉ bằng một lệnh pnpm db:migrate.
Quy ước chính:
- Khóa chính
uuid(gen_random_uuid()), không lộ thứ tự qua API; riêng bảng nhật ký/sổ cái khối lượng lớn dùngbigint identity. - Tên bảng/cột
snake_casetiếng Anh, số nhiều; cột audit chuẩncreated_at/by,updated_at/by(không đặt FK cho*_byđể job hệ thống ghi được). - Trạng thái/loại dùng
text+CHECK, không dùngENUMcủa PostgreSQL, thêm giá trị mới chỉ cần sửa constraint, không cần migration kiểu enum. - Tiền
numeric(18,2), côngnumeric(4,3)/numeric(6,3), giờnumeric(5,2), tỉ lệ/hệ sốnumeric(6,4). - Khoảng hiệu lực
effective_from/effective_to(NULL = còn hiệu lực), chống chồng lấn bằngEXCLUDE USING gist. - Dữ liệu nhạy cảm (CCCD, số tài khoản ngân hàng) mã hóa AES-256-GCM ở tầng ứng dụng (
FieldEncryptionService), lưu cột hậu tố_enc; database không bao giờ giữ bản rõ. - Xóa mềm (
deleted_at) chỉ cho dữ liệu gốc (nhân viên, dự án, task, tài sản); phần còn lại dùng "ngừng dùng" (is_active) hoặc hủy trạng thái. - Sổ cái (ledger) thay cho cột số dư: quỹ phép, ngân sách, quỹ tiền, công nợ nhân viên đều chỉ
INSERT, số dư tính qua view; trigger chặnUPDATE/DELETEtrên các bảng này, muốn sửa phải ghi bút toán đảo. - Luồng duyệt đa hình dùng chung: mọi loại đơn tạo một bản ghi
approval_requests(request_type, reference_id); các bước và người duyệt được chụp (snapshot) lúc gửi đơn nên đổi sơ đồ tổ chức sau đó không ảnh hưởng đơn đang chạy.
I.4. DTO dùng chung & định dạng lỗi API
Một schema Zod trong packages/contracts dùng cho cả hai việc: validate request ở API (qua ZodValidationPipe/parse thủ công) và validate form ở web (qua zodResolver của React Hook Form), chỉ viết một lần, không lệch giữa frontend/backend. Thông báo lỗi mặc định của Zod dùng tiếng Việt (z.config(z.locales.vi())) ở cả hai phía.
Lỗi API trả về theo một định dạng thống nhất:
ApiError { statusCode, error, message, fieldErrors?: [{ path, message }] }Web gắn fieldErrors thẳng vào đúng ô form bị lỗi.
I.5. Xác thực & phân quyền (chi tiết kỹ thuật)
- Access token JWT (HS256,
@nestjs/jwt) sống 15 phút, gửi qua headerAuthorization: Bearer, chỉ giữ trong bộ nhớ trình duyệt (khônglocalStorage) để giảm rủi ro XSS đánh cắp token dài hạn. - Refresh token: chuỗi ngẫu nhiên 32 byte, chỉ lưu hash SHA-256 trong bảng
refresh_tokens; cookiecorebeat_rthttpOnly,SameSite=Lax,Secureở production,Path=/api/auth, sống 14 ngày, xoay vòng mỗi lần refresh. - Phát hiện dùng lại token (reuse detection) + cửa sổ ân hạn (
REFRESH_REUSE_GRACE_SECONDS): token đã bị xoay mà bị gọi lại trong cửa sổ ân hạn thì coi là gọi trùng (cấp token mới, giữ phiên); ngoài cửa sổ thì thu hồi toàn bộ token của user (nghi ngờ bị đánh cắp). - Mật khẩu băm bằng
@node-rs/argon2; sai 5 lần liên tiếp thì khóa tài khoản và thu hồi toàn bộ refresh token. - Guard toàn cục đọc lại user từ database ở mỗi request (khóa/vô hiệu hóa tài khoản có hiệu lực ngay lập tức, không cần đợi access token hết hạn); route công khai đánh dấu bằng decorator
@Public(). - RBAC + phạm vi dữ liệu: quyền hiệu lực của một người = hợp các vai trò còn hạn; mỗi quyền có phạm vi
OWN/SUBORDINATES/DEPARTMENT/BRANCH/ALL, có thể bị giới hạn thêm theo chi nhánh/phòng ban cụ thể của vai trò.DataScopeServicesinh điều kiện lọc Prisma (where) theo phạm vi, controller không tự lọc dữ liệu,@RequirePermission()chỉ kiểm tra "có quyền ở phạm vi nào đó hay không". - Cache quyền trong bộ nhớ tiến trình (chưa dùng Redis), hạn 60 giây làm lưới an toàn; đổi vai trò gọi
PermissionsService.invalidate(userId)để có hiệu lực ngay trong cùng tiến trình, chạy nhiều bản API thì cache giữa các bản có thể lệch nhau tới 60 giây. - Đa tab cùng trình duyệt: dùng Web Locks API (
navigator.locks) để chỉ một tab refresh token tại một thời điểm, vàBroadcastChannelđể các tab còn lại dùng ngay token mới mà không phải tự gọi refresh.
I.6. Hạ tầng job nền & công thức động an toàn
- Không có hàng đợi (queue) riêng (chưa dùng BullMQ/Redis...): mọi việc định kỳ (nhắc hạn, leo thang duyệt, khóa logtime quá hạn, cộng phép, tính khấu hao...) chạy bằng
setIntervalngay trong tiến trình API theo biến môi trường cấu hình (ATTENDANCE_JOB_INTERVAL_MINUTES,APPROVAL_JOB_INTERVAL_MINUTES...),0để tắt. Chạy nhiều bản API cùng lúc có thể gửi trùng một vài thông báo, nhưng dữ liệu nghiệp vụ vẫn đúng nhờ ràng buộc duy nhất (unique constraint) ở database. - Tính lương chạy nền trong tiến trình API (không phải hàng đợi riêng): kỳ lương chuyển trạng thái
CALCULATING, tính tuần tự từng người, web hỏi lại tiến độ mỗi 2 giây; tiến trình API dừng giữa chừng thì kỳ bị kẹt ởCALCULATING. - Công thức động (công thức lương, trường tùy chỉnh dự án, điều kiện ngân sách...) đánh giá bằng
mathjs(BigNumber, 64 chữ số) sau khi kiểm từng nút của cây biểu thức qua một allowlist dùng chung (common/safe-expression.ts): chỉ cho phép biến đã khai báo, phép toán số học/so sánh/logic,?:, và các hàmmin/max/round/floor/ceil/abs, không có script hayevaltự do, tránh thực thi mã tùy ý.
I.7. Đa ngôn ngữ (i18n)
i18next + react-i18next, hiện có vi (mặc định, bản gốc) và en. Người dùng tự chọn ngôn ngữ (không tự nhận diện trình duyệt), lưu localStorage. Bản dịch là file TypeScript (không phải JSON) ở apps/web/src/i18n/locales/<ngôn ngữ>/<namespace>.ts; bản vi là gốc, các ngôn ngữ khác khai báo kiểu typeof của bản vi nên thiếu khóa hoặc gõ sai khóa là lỗi biên dịch TypeScript, không phải lỗi runtime.
I.8. Triển khai (deployment)
- Docker Compose cho Coolify (
docker-compose.prod.yml): 3 servicepostgres+api+web, mỗi khách hàng một bộ riêng (chưa làm multi-tenant).Dockerfileriêng choapps/apivàapps/web, build context là gốc repo, mỗi image chỉ cài package cần thiết (pnpm install --filter "<package>..."). - Web và API chung một domain: nginx trong image web vừa phục vụ file tĩnh vừa
proxy_passcác request/api/*sang serviceapi:3000, không cần cấu hình CORS, không cần biếnVITE_API_URL. - Migration tự chạy khi API khởi động (
prisma migrate deploytrongdocker-entrypoint.shtrước khi start, tắt được bằngRUN_MIGRATIONS=false). TRUST_PROXY: cấu hìnhtrust proxycủa Express khi chạy sau reverse proxy (Traefik/nginx), đểreq.iplà IP public thật của người dùng, quan trọng vì chấm công kiểm tra theo dải IP văn phòng.- PostgreSQL chạy UTC (
-c timezone=UTC) ở production vì@prisma/adapter-pggửitimestamptzkhông kèm múi giờ; ứng dụng tự quy đổi sangAsia/Ho_Chi_Minhkhi cần (tính công, job hằng ngày).
I.9. Kiểm thử, lint & CI
- Vitest cho
apps/apivàpackages/contracts; test tích hợp API dùng PostgreSQL thật (tự tạo lại databasecorebeat_test), không mock database. - ESLint (flat config +
typescript-eslint) và Prettier, cấu hình chung ở gốc repo, chạy qua Turborepo (pnpm lint,pnpm typecheck,pnpm test). - GitHub Actions chạy lint, typecheck, test, build với service PostgreSQL 16 cho mỗi lần đẩy code.
- Swagger/OpenAPI: chưa làm, hoãn tới khi có app mobile hoặc bên thứ ba cần tích hợp.
Nghiệp vụ & tính năng
0. Giới thiệu chung
Corebeat là hệ thống HRM (quản trị nhân sự) cho doanh nghiệp Việt Nam, gồm các khối nghiệp vụ: hồ sơ & tổ chức, chấm công & logtime, nghỉ phép, tăng ca, tính lương, dự án & công việc, tài sản, chi phí & quỹ, ngân sách & mua sắm, tất cả xoay quanh một luồng duyệt dùng chung và một cơ chế phân quyền theo phạm vi dữ liệu áp dụng nhất quán cho mọi module.
Nguyên tắc sản phẩm xuyên suốt: một bộ source code cho mọi khách hàng, khác biệt giữa doanh nghiệp giải quyết bằng dữ liệu cấu hình (chính sách, công thức lương, luồng duyệt, loại phép...), không viết if (khách hàng === 'X').

giao diện đăng nhập
1. Xác thực & phiên đăng nhập
- Đăng nhập bằng tên đăng nhập + mật khẩu; access token JWT sống 15 phút (chỉ giữ trong bộ nhớ trình duyệt, không lưu
localStorage), refresh token 14 ngày nằm trong cookie an toàn, tự xoay vòng mỗi lần làm mới. - Sai mật khẩu 5 lần liên tiếp → tài khoản bị khóa (
LOCKED), thu hồi toàn bộ phiên đăng nhập; chỉ có quản trị viên mở khóa lại được. - Nhiều tab trình duyệt dùng chung một lượt làm mới phiên (không tab nào phải refresh riêng); đăng xuất ở một tab thì các tab khác tự về trang đăng nhập.
- Người dùng tự đổi mật khẩu; đổi mật khẩu sẽ thu hồi các phiên đăng nhập khác.

trang đổi mật khẩu
Cách mởmở từ menu tài khoản ở góc trên, không nằm trong menu điều hướng chính
2. Phân quyền & quản lý người dùng
- Phân quyền theo vai trò (RBAC) + phạm vi dữ liệu: mỗi vai trò được cấp một số quyền, mỗi quyền có phạm vi áp dụng là
OWN(của tôi),SUBORDINATES(cấp dưới trực tiếp/đệ quy),DEPARTMENT(phòng ban),BRANCH(chi nhánh) hoặcALL(toàn công ty). Một người có thể giữ nhiều vai trò, quyền hiệu lực là hợp của tất cả vai trò còn hạn. - Vai trò có thể bị giới hạn thêm theo chi nhánh/phòng ban cụ thể (ví dụ: HR chỉ quản lý chi nhánh Hà Nội) và theo ngày hết hạn (vai trò tạm thời).
- Quản lý người dùng: tìm kiếm, lọc trạng thái, gán/gỡ vai trò, đổi trạng thái tài khoản (Hoạt động/Khóa/Vô hiệu hóa), đặt lại mật khẩu (sinh mật khẩu tạm, hiển thị một lần). Có các chốt an toàn: không tự khóa/đặt lại mật khẩu của chính mình, không gỡ vai trò quản trị hệ thống cuối cùng.
- Mọi thay đổi quyền/trạng thái người dùng được ghi lại đầy đủ nhật ký (ai đổi, lúc nào, từ IP nào, giá trị cũ/mới).
- Giao diện tự ẩn/hiện menu và nút bấm theo quyền của người đang đăng nhập (API luôn là nơi kiểm tra quyền thật sự).

danh sách người dùng, gán vai trò

cấu hình luồng duyệt
3. Tổ chức & hồ sơ nhân sự
3.1. Cơ cấu tổ chức
Quản lý pháp nhân, chi nhánh, phòng ban (dạng cây, có thể chuyển phòng cha trong cùng chi nhánh), chức danh, cấp bậc (kèm khung lương tham chiếu). Mã các đối tượng này bất biến sau khi tạo. Ngừng dùng bị chặn nếu còn phần tử con đang hoạt động; xóa cứng chỉ khi chưa có gì tham chiếu.
Trang Phòng ban có 2 chế độ xem: Bảng (thao tác: sửa, thêm phòng con, ngừng dùng, xóa) và Sơ đồ tổ chức (chỉ xem, vẽ cây bằng đường nối, mở đúng ngăn kéo sửa khi bấm vào một ô).

danh sách pháp nhân

danh sách chi nhánh

trang phòng ban — chế độ Bảng

trang phòng ban — chế độ Sơ đồ tổ chức
Cách mởchuyển sang chế độ "Sơ đồ"

danh sách chức danh

danh sách cấp bậc
3.2. Hồ sơ nhân viên
Danh sách và hồ sơ chi tiết nhân viên: thông tin cơ bản, CCCD/CMND (mã hóa, chỉ hiển thị bản che số cuối), người phụ thuộc, tài khoản ngân hàng (đổi tài khoản = thêm tài khoản mới, tài khoản cũ tự đóng), hợp đồng lao động và lương/phụ cấp cố định.
Vòng đời nhân viên (một phần): thử việc → chính thức, chuyển qua việc ký hợp đồng tương ứng. Trang tách tab "Nhân viên" (đang làm) và "Đã nghỉ việc".
Hợp đồng lao động: vòng đời Nháp → Ký (hiệu lực) → hết hiệu lực do ký hợp đồng mới hoặc chấm dứt sớm; kiểm tra điều kiện pháp lý (thời hạn hợp đồng, thời gian thử việc, lương thử việc tối thiểu 85%) ngay trên form. Sau khi ký, đổi lương/chức danh thực hiện bằng phụ lục hợp đồng.

danh sách nhân viên

ngăn kéo hồ sơ nhân viên — tab thông tin chung
Cách mởbấm vào một dòng nhân viên để mở ngăn kéo chi tiết

tab Hợp đồng trong hồ sơ nhân viên
Cách mởmở hồ sơ → tab "Hợp đồng"

tab Lương & phụ cấp trong hồ sơ nhân viên
Cách mởmở hồ sơ → tab "Lương & phụ cấp"

trang Hợp đồng (toàn công ty)
4. Ca, lịch làm việc & chấm công
4.1. Ca và lịch làm việc
Khai báo ca làm việc (cố định, xoay ca, linh hoạt), lịch mẫu theo tuần, ngày lễ/nghỉ bù/nghỉ công ty/làm bù, và xếp ca theo ngày cho từng nhân viên. Hệ thống tự sinh ca làm việc hằng ngày cho mỗi nhân viên dựa trên thứ tự ưu tiên: đơn đổi ca đã duyệt > xếp ca tay > lịch mẫu theo nhân viên/phòng ban/chi nhánh/công ty.
Nhân viên có thể gửi đơn đổi ca (đổi sang ca khác hoặc đổi với đồng nghiệp cùng phòng), đi qua luồng duyệt chung.

danh mục ca làm việc

lịch làm việc theo tuần

danh mục ngày lễ

xếp ca theo ngày

đơn đổi ca
4.2. Chấm công
Chấm công qua web, kiểm tra theo dải IP khai báo cho từng điểm chấm công (ngoài dải vẫn ghi log nhưng không tính công). Hệ thống tự tính công theo ngày dựa trên giờ vào/ra thực tế so với ca được xếp: trừ công phần đi trễ/về sớm vượt mức ân hạn (theo đúng số phút thực tế, không phạt tiền/trừ công hai lần, tuân thủ Điều 127 Bộ luật Lao động), nhận diện quên chấm công, vắng không lý do.
Đơn nghỉ/công tác/WFH đã duyệt, sự cố máy chấm công, và kết quả giải trình công đều được đưa vào khi tính lại bảng công ngày.

danh mục điểm chấm công & dải IP

trang chấm công của tôi

bảng công tổng hợp (ngày/tháng)
4.3. Giải trình công & kỳ công
Nhân viên có thể giải trình khi công bị ghi sai/thiếu (quên chấm công, đi trễ có lý do, vắng cần hồi tố thành nghỉ phép/công tác/WFH...). Giải trình đi qua 2 bước: quản lý trực tiếp xác nhận đúng/không đúng thực tế → HR duyệt kèm chọn hình thức xử lý cụ thể (thêm log, tạo đơn phép hồi tố, miễn trừ phút trễ, mở khóa logtime...).
Kỳ công theo tháng, có mốc hạn tạo đơn/xác nhận; vòng đời Mở → nhân viên xác nhận → quản lý xác nhận → chốt (khóa dữ liệu công, không sửa được nữa). Chặn chốt nếu còn giải trình chưa xử lý xong.

trang giải trình công

quản lý kỳ công — chốt/mở khóa
4.4. Logtime (nhật ký công việc)
Logtime độc lập với chấm công: không bị giới hạn theo giờ quẹt thẻ (phục vụ công tác, WFH, làm nửa buổi ở ngoài); là bằng chứng công việc, công hưởng lương vẫn tính từ chấm công + đơn đã duyệt, không lấy từ logtime (trừ khi có chính sách khác, hiện chưa bật).
Mỗi dòng logtime gắn tối đa một việc: một task cụ thể, một dự án (việc chung), hoặc một "loại việc chung" (họp, hành chính...). Log theo ngày, nộp theo hạn, quá hạn tự khóa; quản lý trực tiếp duyệt/trả lại theo ngày (không qua engine duyệt chung).

trang ghi logtime

duyệt logtime của nhân viên

danh mục loại việc chung
5. Nghỉ phép
Chính sách phép cấu hình theo đối tượng (loại nhân sự, cấp bậc, chi nhánh, giới tính), gồm số ngày/năm, cách cộng dồn (theo tháng, thâm niên), hạn chuyển năm, có cho nghỉ âm quỹ hay không.
Sổ cái phép tự động cộng phép hằng tháng, cấp một lần đầu năm cho người vào giữa năm, cộng thâm niên ngày 01/01, và xử lý chuyển năm (giữ lại một phần, phần vượt trần bị thanh toán hoặc hủy theo chính sách).
Đơn nghỉ phép/công tác/WFH dùng chung một luồng: tự tính số ngày nghỉ theo ca làm việc thực tế (ngày đầu/cuối có thể nghỉ nửa buổi), kiểm tra giới tính, số ngày tối đa mỗi lần, báo trước tối thiểu, trùng lịch, đủ quỹ phép; cảnh báo (không chặn) khi phòng ban có nhiều người nghỉ cùng ngày. Gửi duyệt qua luồng chung; hủy đơn đã duyệt phải gửi yêu cầu hủy và chờ duyệt lại.

danh mục loại phép

chính sách phép

đơn nghỉ phép / công tác / WFH

quỹ phép (số dư) của nhân viên

lịch nghỉ nhóm/phòng ban
6. Tăng ca (OT)
Đăng ký tăng ca cho bản thân hoặc đăng ký hộ cho cả nhóm (quản lý), nằm ngoài giờ ca đã xếp; hệ thống kiểm tra các giới hạn giờ OT theo ngày/tháng/năm (đọc từ cấu hình, có thể khác nhau theo chi nhánh), cảnh báo khi gần chạm trần.
Sau khi được duyệt và đến ngày làm thực tế, hệ thống đối chiếu với chấm công để tính giờ OT thực tế (tách ngày/đêm), áp hệ số OT theo loại ngày (ngày thường/cuối tuần/lễ) và theo thời điểm hiệu lực. Có thể chọn quy đổi OT thành nghỉ bù thay vì trả tiền, nghỉ bù có hạn sử dụng, quá hạn được thanh toán.
Đơn OT có thể gắn với một task/dự án cụ thể để biết OT phục vụ việc gì.

đăng ký tăng ca

cấu hình hệ số tăng ca
7. Dự án & công việc
7.1. Loại dự án, mẫu dự án
Hệ thống cho phép cấu hình loại dự án (ví dụ: dự án phần mềm, xây dựng, nội bộ) gồm: các trạng thái và bước chuyển trạng thái hợp lệ, vai trò thành viên và quyền hạn của từng vai trò trong dự án, các loại task (mỗi loại một quy trình trạng thái riêng), trường tùy chỉnh, loại mốc, có cần duyệt khi đổi trạng thái/qua giai đoạn hay không. Từ một loại dự án có thể dựng mẫu dự án (khung giai đoạn/mốc/task dựng sẵn, có nhiều phiên bản) để tạo dự án mới nhanh.

danh sách loại dự án

cấu hình chi tiết một loại dự án

chi tiết mẫu dự án
7.2. Dự án, giai đoạn, mốc
Tạo dự án (từ mẫu hoặc trống), có thành viên với vai trò khác nhau; giai đoạn có thể tuần tự hoặc song song, có cổng kiểm soát (gate) cần duyệt mới qua giai đoạn tiếp theo; mốc (milestone) theo loại cấu hình. Tiến độ dự án tính tự động theo số task/giờ dự toán/trọng số giai đoạn, hoặc nhập tay.
Đổi trạng thái dự án hoặc qua cổng giai đoạn ở các loại dự án yêu cầu duyệt sẽ đi qua luồng duyệt chung, người duyệt có thể là người giữ một vai trò cụ thể trong dự án.

danh sách dự án

chi tiết dự án — tab Giai đoạn & mốc

chi tiết dự án — biểu đồ Gantt

chi tiết dự án — tab Thành viên

chi tiết dự án — tab Giờ làm
7.3. Task & công việc cá nhân
Task và sub-task theo quy trình trạng thái của loại task; có checklist, người theo dõi, bình luận nhắc tên, lịch sử thay đổi. Trang "Việc của tôi" xem theo bảng hoặc Kanban kéo-thả (cột theo nhóm trạng thái), nhắc việc sắp đến hạn/quá hạn.

chi tiết dự án — tab Task dạng bảng

Việc của tôi — dạng bảng

Việc của tôi — Kanban
Cách mởchuyển sang chế độ xem Kanban

chi tiết một task
Cách mởmở từ /tasks hoặc tab Task của dự án, bấm vào một task để xem ngăn kéo chi tiết
8. Luồng duyệt dùng chung
Đây là hạ tầng duyệt dùng cho mọi loại đơn trong hệ thống: nghỉ phép, hủy đơn nghỉ, tăng ca, đổi ca, đề nghị chi, đề xuất mua, đơn mua hàng, ngân sách, điều chỉnh ngân sách, đổi trạng thái/qua giai đoạn dự án.
- Quy trình duyệt cấu hình theo khoảng giá trị (số tiền, số ngày nghỉ, số giờ OT..., ví dụ đơn dưới 5 triệu chỉ cần quản lý trực tiếp duyệt, trên 5 triệu cần thêm Ban giám đốc.
- Mỗi bước chọn người duyệt theo nhiều cách: quản lý trực tiếp, quản lý cấp N, trưởng phòng, người giữ một vai trò (hệ thống hoặc vai trò trong dự án), hoặc một người cụ thể; bước có thể yêu cầu một người bất kỳ hoặc tất cả người duyệt đồng ý.
- Người duyệt được chụp lại lúc gửi đơn (không đổi theo nhân sự sau đó); bỏ qua bước trùng người hoặc không còn ai.
- Ủy quyền duyệt: nghỉ/vắng có thể ủy quyền duyệt thay trong khoảng thời gian, theo loại đơn.
- Nhắc & leo thang: quá hạn chưa duyệt thì nhắc, quá hạn tiếp thì tự thêm người duyệt cấp cao hơn vào bước.
- Bước duyệt thêm tự nối vào khi đơn vượt ngân sách hoặc vượt định mức.
- Duyệt hàng loạt tối đa 100 đơn cùng lúc.
- Người duyệt/ủy quyền xem được đơn trong hộp "Việc cần duyệt" dù không có quyền quản lý loại đơn đó.

hộp "Việc cần duyệt"

trang ủy quyền duyệt

cấu hình một quy trình duyệt theo khoảng tiền
Cách mởchọn một loại đơn rồi mở một quy trình
9. Tính lương
- Khoản mục lương (lương cơ bản, phụ cấp, ăn trưa, chuyên cần...) mỗi khoản gắn một công thức tính theo ngày hiệu lực, công thức dùng biến chuẩn (số công, số ngày OT, hệ số...), được kiểm an toàn trước khi lưu (không cho chạy mã tùy ý).
- Tham số pháp lý (thuế TNCN, tỉ lệ bảo hiểm, lương tối thiểu vùng, mức tham chiếu...) lưu theo ngày hiệu lực, đổi luật không cần sửa code.
- Lương cố định của từng nhân viên (lương, các khoản phụ cấp theo mức riêng) khai báo trong hồ sơ nhân viên.
- Kỳ lương: lập kỳ → tính nền (chạy ngầm, có tiến độ, tính lại từng người khi cần) → nhập khoản biến động tay (thưởng, phạt hợp lệ...) → so sánh với kỳ trước để phát hiện bất thường → gửi duyệt qua luồng chung → khóa → phát hành (nhân viên xem được phiếu lương) → đánh dấu đã chi. Có xử lý khiếu nại và mở khóa kỳ đã chốt khi cần (có kiểm soát).
- Mỗi dòng lương lưu lại toàn bộ dữ liệu dùng để tính (snapshot: hợp đồng, phòng ban, công thức, giá trị biến...) để tra soát sau này mà không sợ dữ liệu gốc thay đổi.
- Lương thử việc tự áp theo tỉ lệ % đã khai trên hợp đồng thử việc.

danh mục khoản mục lương & công thức

tham số lương theo thời điểm hiệu lực

danh sách kỳ lương

chi tiết một kỳ lương — bảng lương từng người
Cách mởbấm vào một kỳ để mở chi tiết

phiếu lương của tôi
10. Tài sản
- Danh mục tài sản (gắn thời gian khấu hao mặc định, gắn danh mục chi phí để mua sắm trừ đúng ngân sách), hồ sơ từng tài sản theo mã riêng.
- Mọi thay đổi vị trí/người giữ/tình trạng đi qua nghiệp vụ (cấp phát, điều chuyển, thu hồi, gửi sửa, báo hỏng/mất, thanh lý), không sửa trực tiếp; mỗi nghiệp vụ có số biên bản riêng và quy tắc chuyển tình trạng chặt chẽ (ví dụ: chỉ thanh lý được tài sản trong kho/hỏng/mất).
- Người được cấp phát/điều chuyển phải xác nhận đã nhận.
- Khấu hao đường thẳng tính khi xem (chưa có job cuối tháng), chỉ phục vụ báo cáo nội bộ.
- Tài sản phát sinh từ đề xuất mua đã duyệt ở trạng thái "Chờ nhận hàng" cho tới khi làm nghiệp vụ nhận hàng (xem mục Mua sắm).
- Người giữ tài sản tự báo hỏng/mất ngay trên trang "Tài sản của tôi".

danh mục tài sản

danh sách tài sản (quản lý)

form ghi nghiệp vụ tài sản (cấp phát/điều chuyển/thu hồi...)
Cách mởmở một tài sản → "Ghi nghiệp vụ"

Tài sản của tôi
11. Chi phí & quỹ tiền
- Danh mục chi phí 2 cấp, mỗi danh mục có thể gắn định mức riêng theo cấp bậc (ví dụ: định mức công tác phí/ngày khác nhau theo cấp).
- Phiếu chi gồm 3 loại: tạm ứng, hoàn ứng (quyết toán tạm ứng), thanh toán thường, mỗi dòng phiếu trước VAT, tổng phiếu = tiền + VAT; vượt định mức vẫn gửi được nhưng buộc ghi lý do.
- Chống trùng hóa đơn (một hóa đơn chỉ gắn một phiếu còn hiệu lực); giới hạn số tiền được chi bằng tiền mặt.
- Gửi phiếu được kiểm tra với ngân sách ngay (chặn/cảnh báo/yêu cầu duyệt thêm tùy chính sách danh mục).
- Gửi duyệt qua luồng chung; duyệt xong cam kết ngân sách, khi thực chi mới ghi nhận chi phí thật.
- Sổ quỹ (thu/chi khác, chuyển quỹ, kiểm quỹ) chỉ ghi thêm, không sửa/xóa; kiểm tra số dư trước khi chi để quỹ không âm.
- Công nợ nhân viên (tạm ứng chưa hoàn, hạn hoàn ứng) xem được ở một trang riêng.

danh mục chi phí dạng cây + định mức

trang Đề nghị chi — các tab theo vai trò

quỹ tiền — sổ quỹ

công nợ nhân viên
12. Ngân sách & mua sắm
12.1. Ngân sách
Lập ngân sách theo năm tài chính, mỗi khoản = phạm vi (công ty/phòng ban) × danh mục × cách chia kỳ (năm/quý/tháng). Gửi duyệt qua luồng chung; sau khi duyệt chỉ sửa được bằng điều chỉnh ngân sách (chuyển giữa các dòng hoặc bổ sung), cũng phải duyệt. Mọi khoản chi trong hệ thống (đề nghị chi, đề xuất mua, đơn mua) đều tự khớp vào đúng dòng ngân sách và cam kết/giải ngân theo thời gian thực.

danh sách ngân sách theo năm

chi tiết ngân sách — các dòng theo kỳ, % đã dùng
Cách mởbấm vào một ngân sách

điều chỉnh ngân sách
Cách mởtab "Điều chỉnh" của một ngân sách
12.2. Mua sắm tài sản
Quy trình đầy đủ: Đề xuất mua (nhân viên lập, duyệt qua luồng chung) → duyệt xong tự tạo tài sản ở trạng thái "Chờ nhận hàng" → báo giá của nhà cung cấp (bắt buộc đủ số báo giá tối thiểu nếu giá trị lớn) → chọn báo giá thắng → đơn mua hàng (duyệt riêng theo giá trị) → phiếu nhận hàng (chuyển tài sản sang "Trong kho", chốt nguyên giá thật) → đề nghị thanh toán nhà cung cấp (tự tạo phiếu chi, đi qua đúng quy trình Đề nghị chi ở trên).

danh mục nhà cung cấp

đề xuất mua tài sản

chi tiết đề xuất — báo giá & chọn báo giá thắng
Cách mởbấm vào một đề xuất đã duyệt

đơn mua hàng

phiếu nhận hàng của một đơn mua
Cách mởmở một đơn mua → "Nhận hàng"
13. Thông báo
Chuông thông báo trong ứng dụng (tự hỏi lại mỗi phút): tới lượt duyệt, nhắc/leo thang, kết quả duyệt, nhắc giải trình, nhắc task sắp đến hạn/quá hạn, cảnh báo nhân viên có dấu hiệu tự ý bỏ việc... Bấm vào thông báo mở đúng đơn/trang liên quan.

menu thông báo (chuông)
Cách mởmở từ icon chuông ở thanh trên cùng, có ở mọi trang
14. Chưa triển khai
Các phần sau chưa có trong phiên bản hiện tại:
- Chấm công bằng máy/app: đồng bộ máy chấm công vân tay (ZKTeco), app mobile (GPS/BSSID/selfie), QR động, import roster từ Excel.
- Đính kèm file: ảnh/biên bản cho giải trình công, tài sản, chi phí; file đính kèm cho task; đọc hóa đơn XML/mã tra cứu.
- Lương: lương NET, kỳ lương ngoài chu kỳ, import Excel, file ngân hàng chi lương hàng loạt, báo cáo bảo hiểm/thuế, xuất PDF phiếu lương, tạm ứng lương, KPI, khen thưởng/bồi thường, tự chuyển trạng thái kỳ công/kỳ lương theo mốc thời gian (hiện bấm tay).
- Tài sản: cấp phát/điều chuyển/thanh lý qua luồng duyệt (engine đã có nhưng chưa nối vào), gán license theo người, lịch bảo trì, job khấu hao cuối tháng, kiểm kê bằng QR, khấu trừ bồi thường vào lương.
- Chi phí: tạm ứng lương, nhắc hoàn ứng quá hạn tự động, khấu trừ tạm ứng quá hạn vào lương, file chi hàng loạt cho ngân hàng.
- Dự án: file đính kèm, KPI, quản lý nguồn lực/chi phí/doanh thu dự án, đồng bộ thay đổi mẫu vào dự án đang chạy (chủ đích không làm).
- Nghỉ việc: checklist tài sản/công nợ khi nghỉ việc, thanh toán phép tồn khi nghỉ việc (chờ module lương xử lý).
- Hạ tầng chung: chưa có hàng đợi xử lý nền (tính lương chạy trong tiến trình API), chưa multi-tenant (mỗi khách một server/database riêng), chưa có Swagger/OpenAPI (hoãn tới khi có app mobile hoặc tích hợp bên thứ ba).