financial_system/README.md
2026-06-23 09:13:13 +08:00

390 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 薪酬考勤管理系统
本项目是一套前后端分离的薪酬考勤管理系统,用于处理钉钉月度汇总 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 DesktopMySQL 地址通常写:
```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` | 数据库连接 |
| `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
```
SQL 文件说明:
| 文件 | 说明 |
| --- | --- |
| `schema.sql` | 建库建表脚本,包含所有表和字段注释 |
| `seed.sql` | 初始化默认超级管理员 |
| `init_mysql.sql` | 一键初始化脚本,包含建库、建表、默认配置、默认管理员 |
| `upgrade_20260617_payroll_modules.sql` | 当前薪酬考勤完整模块升级脚本 |
| `upgrade_20260618_monthly_payroll_center.sql` | 实时考勤同步、薪资预估、月度核算批次和异常清单升级脚本 |
主要业务表:
| 表 | 说明 |
| --- | --- |
| `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.*` 后重启服务即可生效。