forked from jiaoly/financial_system
398 lines
13 KiB
Markdown
398 lines
13 KiB
Markdown
# 薪酬考勤管理系统
|
||
|
||
本项目是一套前后端分离的薪酬考勤管理系统,用于处理钉钉月度汇总 Excel、后续钉钉实时接口、员工档案、薪资档案、提成、考勤扣款、加班费、工资汇总和统计报表。
|
||
|
||
核心目标是把人工工资核算链路拆成可维护的数据流:
|
||
|
||
```text
|
||
钉钉考勤接口 / Excel导入
|
||
-> 数据标准化
|
||
-> 考勤 / 请假 / 加班引擎
|
||
-> 工时统计
|
||
-> 薪资 / 提成 / 奖惩计算
|
||
-> 工资汇总
|
||
-> 工资条 / 月报表 / 财务报表
|
||
```
|
||
|
||
## 当前能力
|
||
|
||
- 支持导入钉钉月度汇总 Excel 计算工资。
|
||
- 支持实时考勤看板:按员工档案中的钉钉 userId 自动同步本月至今打卡,不需要人工输入 userId。
|
||
- 支持月度核算中心:按月份导入 Excel 或同步钉钉计算,生成异常清单、核算批次、锁定状态和导出入口。
|
||
- 自动统计出勤天数、缺勤天数、请假工时、缺卡、迟到扣款。
|
||
- 按下班打卡时间自动计算加班:17:00 下班,18:00 计 1 小时,20:30 计 3 小时。
|
||
- 自动计算:`剩余加班工时 = 打卡推算加班工时 - 请假工时`。
|
||
- 迟到规则:5 分钟内 3 次合格,超过后每次扣 30 元;超过 5 分钟每次扣 30 元。
|
||
- 缺卡规则:每次扣 20 元。
|
||
- 支持组织架构、员工维护、薪资维护、提成管理、规则配置、操作日志、统计报表。
|
||
- 薪资模式支持:包月、计时、计件、试用期。
|
||
- 加班费支持:工作日、周末、法定节假日独立单价。
|
||
- 提成支持手工维护和 Excel 导入,并按工资月份自动汇总进工资计算。
|
||
- 工资计算结果会落库为工资汇总、工资明细、考勤记录、请假记录和加班记录。
|
||
- 实时薪资预估只用于过程查看,最终工资以月度核算锁定结果为准。
|
||
|
||
## 项目结构
|
||
|
||
```text
|
||
main.py 后端启动入口
|
||
config/ 后端配置文件
|
||
financial_system/
|
||
api/ FastAPI app、路由、schema、依赖注入
|
||
core/ 配置、权限、安全、日志
|
||
database/ ORM、数据库会话、SQL脚本
|
||
domain/ 领域模型、工资计算器
|
||
integrations/ 钉钉等外部系统适配
|
||
io/ Excel解析、导出、文件存储
|
||
repositories/ 数据库读写层
|
||
services/ 业务服务层
|
||
frontend/ Vue3 前端项目
|
||
```
|
||
|
||
分层约定:
|
||
|
||
- `routers` 只处理 HTTP、权限、参数和操作日志。
|
||
- `schemas` 只定义请求响应结构。
|
||
- `services` 只做业务编排和校验。
|
||
- `repositories` 只负责 ORM 读写。
|
||
- `domain` 只负责纯计算规则,不依赖数据库和 HTTP。
|
||
|
||
## 运行环境
|
||
|
||
后端使用 Conda 环境:
|
||
|
||
```bash
|
||
/Users/jiaolongyan/miniconda3/envs/Financial_System/bin/python main.py
|
||
```
|
||
|
||
默认访问:
|
||
|
||
- 后端接口文档:http://127.0.0.1:8000/docs
|
||
- 健康检查:http://127.0.0.1:8000/health
|
||
- 前端开发地址:http://127.0.0.1:5173
|
||
|
||
前端启动:
|
||
|
||
```bash
|
||
cd frontend
|
||
npm install
|
||
npm run dev
|
||
```
|
||
|
||
前端构建:
|
||
|
||
```bash
|
||
cd frontend
|
||
npm run build
|
||
```
|
||
|
||
## Docker 运行(外部 MySQL)
|
||
|
||
项目已提供后端镜像、前端 Nginx 镜像和 `docker-compose.yml`。数据库使用外部 MySQL,不会在 compose 里启动 MySQL 容器。
|
||
|
||
1. 准备环境变量:
|
||
|
||
```bash
|
||
cp .env.docker.example .env
|
||
```
|
||
|
||
2. 修改 `.env` 里的 `DATABASE_URL`:
|
||
|
||
```env
|
||
DATABASE_URL=mysql+pymysql://用户名:密码@MySQL地址:3306/financial_system?charset=utf8mb4
|
||
```
|
||
|
||
如果 MySQL 就运行在当前电脑,并且你使用 Docker Desktop,MySQL 地址通常写:
|
||
|
||
```env
|
||
DATABASE_URL=mysql+pymysql://root:12345678@host.docker.internal:3306/financial_system?charset=utf8mb4
|
||
```
|
||
|
||
如果 MySQL 在另一台服务器,写那台服务器的内网 IP、外网 IP 或域名。不要在容器里使用 `localhost` 连接外部 MySQL,因为 `localhost` 指向的是后端容器本身。
|
||
|
||
3. 启动:
|
||
|
||
```bash
|
||
docker compose up --build
|
||
```
|
||
|
||
默认访问:
|
||
|
||
- 前端系统:http://127.0.0.1:5173
|
||
- 后端接口:http://127.0.0.1:8000
|
||
- 接口文档:http://127.0.0.1:5173/docs
|
||
|
||
后端容器启动时会按外部 MySQL 自动建库、建表并初始化默认超级管理员。请确认外部 MySQL 已允许该账号远程连接,并且账号有创建数据库和建表权限。
|
||
|
||
## 统一配置
|
||
|
||
后端配置统一放在:
|
||
|
||
```text
|
||
config/app_settings.json
|
||
```
|
||
|
||
常用配置:
|
||
|
||
| 配置 | 说明 |
|
||
| --- | --- |
|
||
| `server.host` / `server.port` | 后端监听地址和端口 |
|
||
| `database.url` | 数据库连接 |
|
||
| 系统时区 | 后端统一使用 `Asia/Shanghai`,MySQL 会话启动时自动设置为 `+08:00` |
|
||
| `dingtalk.app_key` / `dingtalk.app_secret` | 钉钉开放平台凭证 |
|
||
| `storage.upload_dir` | 上传文件目录 |
|
||
| `storage.output_dir` | 导出工资文件目录 |
|
||
| `storage.avatar_dir` | 头像上传目录 |
|
||
| `logging.*` | info/error 日志文件和滚动策略 |
|
||
| `auth.secret_key` | Token 签名密钥 |
|
||
| `bootstrap_superuser.*` | 首次启动超级管理员 |
|
||
| `cors.allowed_origins` | 前端跨域来源 |
|
||
|
||
默认 MySQL:
|
||
|
||
```json
|
||
{
|
||
"database": {
|
||
"url": "mysql+pymysql://root:12345678@localhost:3306/financial_system?charset=utf8mb4"
|
||
}
|
||
}
|
||
```
|
||
|
||
如需使用其他配置文件:
|
||
|
||
```bash
|
||
APP_CONFIG_FILE=/path/to/app_settings.json /Users/jiaolongyan/miniconda3/envs/Financial_System/bin/python main.py
|
||
```
|
||
|
||
## 数据库
|
||
|
||
本地 MySQL:
|
||
|
||
```text
|
||
host: localhost
|
||
port: 3306
|
||
user: root
|
||
password: 12345678
|
||
database: financial_system
|
||
```
|
||
|
||
完整初始化:
|
||
|
||
```bash
|
||
mysql -h localhost -P 3306 -u root -p12345678 < financial_system/database/sql/init_mysql.sql
|
||
```
|
||
|
||
已有旧库升级到当前版本:
|
||
|
||
```bash
|
||
mysql -h localhost -P 3306 -u root -p12345678 financial_system < financial_system/database/sql/upgrade_20260617_payroll_modules.sql
|
||
mysql -h localhost -P 3306 -u root -p12345678 financial_system < financial_system/database/sql/upgrade_20260618_monthly_payroll_center.sql
|
||
```
|
||
|
||
如果历史页面时间整体少 8 小时,说明旧数据曾按 UTC 写入,可确认后执行一次修正脚本:
|
||
|
||
```bash
|
||
mysql -h localhost -P 3306 -u root -p12345678 financial_system < financial_system/database/sql/upgrade_20260623_timezone_shanghai.sql
|
||
```
|
||
|
||
SQL 文件说明:
|
||
|
||
| 文件 | 说明 |
|
||
| --- | --- |
|
||
| `schema.sql` | 建库建表脚本,包含所有表和字段注释 |
|
||
| `seed.sql` | 初始化默认超级管理员 |
|
||
| `init_mysql.sql` | 一键初始化脚本,包含建库、建表、默认配置、默认管理员 |
|
||
| `upgrade_20260617_payroll_modules.sql` | 当前薪酬考勤完整模块升级脚本 |
|
||
| `upgrade_20260618_monthly_payroll_center.sql` | 实时考勤同步、薪资预估、月度核算批次和异常清单升级脚本 |
|
||
| `upgrade_20260623_timezone_shanghai.sql` | 一次性修正历史 UTC 时间为北京时间,确认整体少 8 小时后再执行 |
|
||
|
||
主要业务表:
|
||
|
||
| 表 | 说明 |
|
||
| --- | --- |
|
||
| `users` | 系统用户 |
|
||
| `departments` | 部门及上下级关系 |
|
||
| `positions` | 部门下的岗位 |
|
||
| `employees` | 员工档案 |
|
||
| `salary_profiles` | 员工薪资档案 |
|
||
| `attendance_record` | 标准化考勤记录 |
|
||
| `leave_record` | 请假/调休记录 |
|
||
| `overtime_record` | 加班记录 |
|
||
| `commission_record` | 提成/奖金记录 |
|
||
| `payroll_jobs` | 工资计算任务 |
|
||
| `payroll_results` | 员工工资计算结果 |
|
||
| `attendance_sync_jobs` | 钉钉/Excel 考勤同步批次 |
|
||
| `salary_preview` | 本月进行中的薪资预估 |
|
||
| `monthly_payroll_runs` | 月度正式核算批次 |
|
||
| `payroll_exceptions` | 月度核算异常清单 |
|
||
| `salary_record` | 月度工资汇总 |
|
||
| `salary_detail` | 工资明细项 |
|
||
| `salary_config` | 规则配置中心 |
|
||
| `operation_logs` | 操作日志 |
|
||
|
||
服务启动时会执行 ORM 建表检查,并补齐默认超级管理员和规则配置。
|
||
|
||
组织架构启动时会按内置层级补齐部门和岗位:
|
||
|
||
- 部门顺序按总经办、行政人事部、财务部、订单部、工程部、杭州运营中心、华南/华中/西南运营中心、生产中心等层级维护。
|
||
- `工程部-安装队`、`工程部-项目预算` 会挂到自动补齐的 `工程部` 父级下。
|
||
- `杭州运营中心-销售部` 会挂到自动补齐的 `杭州运营中心` 父级下。
|
||
- `生产中心-采购部/仓库/品管部/生产部` 会挂到 `生产中心` 下。
|
||
- `西南运营中心-办事处/销售部` 会挂到 `西南运营中心` 下。
|
||
- 岗位编码由系统自动生成,页面只展示编码,不需要人工维护。
|
||
|
||
员工维护中,员工编号同样由系统自动生成,默认格式为 `ZA0001`、`ZA0002` 递增,前端只展示不手工维护。
|
||
|
||
## 规则配置
|
||
|
||
规则配置既可以通过前端“规则配置”页面维护,也可以参考:
|
||
|
||
```text
|
||
config/salary_rules.example.json
|
||
```
|
||
|
||
默认关键规则:
|
||
|
||
- 上班时间:08:30
|
||
- 下班时间:17:00
|
||
- 加班取整:60 分钟向下取整
|
||
- 标准日工时:8 小时
|
||
- 5 分钟内迟到免扣次数:3 次
|
||
- 迟到扣款:30 元/次
|
||
- 缺卡扣款:20 元/次
|
||
- 周末定义:周六、周日
|
||
- 法定节假日:可在规则配置中维护日期数组
|
||
|
||
工资公式:
|
||
|
||
```text
|
||
应发工资 = 基础工资 + 提成 + 加班费 - 迟到扣款 - 缺卡扣款 - 其他扣款
|
||
```
|
||
|
||
基础工资按薪资模式计算:
|
||
|
||
- 包月:固定底薪
|
||
- 计时:实际工作工时 × 小时单价
|
||
- 计件:计件数量 × 计件单价
|
||
- 试用期:底薪 × 固定比例,或固定金额
|
||
|
||
## 前端页面
|
||
|
||
| 页面 | 路由 | 说明 |
|
||
| --- | --- | --- |
|
||
| 登录 | `/login` | 用户登录 |
|
||
| 工作台 | `/dashboard` | 系统概览 |
|
||
| 实时考勤 | `/attendance/realtime` | 查看今日打卡、迟到、缺卡、请假、加班和本月薪资预估 |
|
||
| 月度核算 | `/payroll/monthly` | 按月导入/同步、计算、异常处理、锁定和导出 |
|
||
| 工资计算 | `/payroll` | Excel 导入和钉钉实时计算 |
|
||
| 计算记录 | `/payroll/jobs` | 查看历史计算任务 |
|
||
| 提成管理 | `/payroll/commissions` | 手工维护和 Excel 导入提成 |
|
||
| 统计报表 | `/reports` | 工资汇总、部门汇总、考勤工时 |
|
||
| 组织架构 | `/system/organization` | 维护部门上下级和部门岗位 |
|
||
| 员工维护 | `/system/employees` | 员工分页维护 |
|
||
| 薪资维护 | `/system/salary-profiles` | 员工薪资模式和加班单价 |
|
||
| 规则配置 | `/system/configs` | 考勤和薪资规则 |
|
||
| 用户管理 | `/system/users` | 超级用户创建账号 |
|
||
| 操作日志 | `/system/operation-logs` | 查看系统操作审计 |
|
||
|
||
前端支持主题色切换、侧边栏收起、个人资料修改、头像上传、修改密码。
|
||
|
||
## 登录与权限
|
||
|
||
首次启动默认超级管理员:
|
||
|
||
```text
|
||
用户名:admin
|
||
密码:Admin@123456
|
||
角色:superuser
|
||
```
|
||
|
||
角色:
|
||
|
||
| 角色 | 说明 |
|
||
| --- | --- |
|
||
| `superuser` | 超级用户,拥有全部菜单和操作权限 |
|
||
| `manager` | 管理者,可维护组织架构、员工、薪资、提成、规则、报表和工资计算 |
|
||
| `viewer` | 查看用户,可查看计算记录、下载结果和统计报表 |
|
||
|
||
登录示例:
|
||
|
||
```bash
|
||
curl -X POST "http://127.0.0.1:8000/api/auth/login" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"username":"admin","password":"Admin@123456"}'
|
||
```
|
||
|
||
## 常用接口
|
||
|
||
上传 Excel 计算工资:
|
||
|
||
```bash
|
||
curl -X POST "http://127.0.0.1:8000/api/payroll/excel" \
|
||
-H "Authorization: Bearer <access_token>" \
|
||
-F "file=@/path/to/月度汇总.xlsx" \
|
||
-F "export_excel=true"
|
||
```
|
||
|
||
实时考勤看板同步钉钉:
|
||
|
||
```bash
|
||
curl -X POST "http://127.0.0.1:8000/api/attendance/realtime/sync" \
|
||
-H "Authorization: Bearer <access_token>" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"attendance_date":"2026-06-22","include_salary_preview":true}'
|
||
```
|
||
|
||
查看实时考勤看板:
|
||
|
||
```bash
|
||
curl "http://127.0.0.1:8000/api/attendance/realtime/today?date=2026-06-22" \
|
||
-H "Authorization: Bearer <access_token>"
|
||
```
|
||
|
||
月度核算同步钉钉并计算:
|
||
|
||
```bash
|
||
curl -X POST "http://127.0.0.1:8000/api/payroll/monthly/dingtalk" \
|
||
-H "Authorization: Bearer <access_token>" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"salary_month":"2026-06","source_type":"dingtalk","export_excel":true}'
|
||
```
|
||
|
||
旧版钉钉实时计算接口仍可使用,但需要手动传 user_ids:
|
||
|
||
```bash
|
||
curl -X POST "http://127.0.0.1:8000/api/payroll/dingtalk/realtime" \
|
||
-H "Authorization: Bearer <access_token>" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"user_ids":["001","002"],"start_date":"2026-05-01","end_date":"2026-05-31","export_excel":true}'
|
||
```
|
||
|
||
新增提成:
|
||
|
||
```bash
|
||
curl -X POST "http://127.0.0.1:8000/api/commissions" \
|
||
-H "Authorization: Bearer <access_token>" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"employee_id":1,"commission_month":"2026-06","commission_type":"销售提成","amount":1000,"source_type":"manual","business_ref":"","remark":""}'
|
||
```
|
||
|
||
查询统计报表:
|
||
|
||
```bash
|
||
curl "http://127.0.0.1:8000/api/reports/payroll-summary?salary_month=2026-06" \
|
||
-H "Authorization: Bearer <access_token>"
|
||
```
|
||
|
||
## 日志
|
||
|
||
日志统一由 `financial_system/core/logger.py` 封装。
|
||
|
||
默认文件:
|
||
|
||
| 文件 | 说明 |
|
||
| --- | --- |
|
||
| `logs/info.log` | 正常流程日志 |
|
||
| `logs/error.log` | 错误和异常日志 |
|
||
|
||
修改 `config/app_settings.json` 中 `logging.*` 后重启服务即可生效。
|