PayrollManagementSystem/backend/pyproject.toml
liuwenxin 8ad3650dd3 feat(system): 计提参数版本管理、变更留痕与计算预览接口
- 9 个端点:目录快照(asOf)/单参数历史/变更批次提交与撤回/批次分页与明细/两日期对比/Excel 导出/计算预览
- submit_change 全量前置校验(注册表/维度岗位/取值域/同批去重)→ 建批次 → 逐项留痕(旧值取提交时生效值)
- 撤回:FOR UPDATE 锁行 + 已生效禁撤,删除后解析自然回退;同日多次变更取最新留痕
- 预览按岗位模板分派公式(经理聚合口径明确拒绝),出参含所用参数与生效时点;导出走 openpyxl
- ECharts 决策记录:前端统计图使用 echarts(用户指定)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-12 20:24:17 +08:00

109 lines
4.3 KiB
TOML
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.

[project]
name = "payroll-backend"
version = "0.1.0"
description = "衍水集团营销人员工资管理系统 —— 后端服务"
readme = "README.md"
# 锁定 3.12:系统默认是 3.14,第三方库轮子覆盖不如 3.12 完备
requires-python = ">=3.12,<3.13"
dependencies = [
"fastapi>=0.115",
# starlette 已进入 1.x(当前 1.7.0)。FastAPI 对它的约束是 `starlette>=0.46.0`,
# **没有上界** —— uv lock --upgrade 时可能漂移到未验证的大版本。
# 我们的异常处理器与 TestClient 直接依赖其 API,故显式限定主版本。
# 当前组合(fastapi 0.143 + starlette 1.7.0)已实测通过全部用例。
"starlette>=1.7,<2",
"uvicorn[standard]>=0.32",
"pydantic>=2.9",
"pydantic-settings>=2.6",
# ORM 与驱动:采用同步 —— 本项目并发极低,异步无吞吐收益;
# 而重活(绩效批量核算、pandas 报表、Excel 导出)全是同步阻塞代码,
# 在异步路由里跑会卡死事件循环。同步路由由 FastAPI 自动放入线程池执行。
"sqlalchemy>=2.0.36",
# 必须带 [rsa]:MySQL 8.0 默认 caching_sha2_password,容器重启后首次连接走
# 全量认证需要 cryptography 做 RSA 交换,缺失时 PyMySQL 直接抛 RuntimeError
# (报错出现在建连阶段,极易被误读成"密码错误")
"pymysql[rsa]>=1.2.3",
"alembic>=1.14",
# 验证码、登录限流、Token 黑名单
"redis[hiredis]>=5.2",
# 鉴权与密码哈希
# 注意:不用 passlib —— 它与 bcrypt>=4.1 存在 __about__ 属性缺失的不兼容问题
"pyjwt>=2.10",
"pwdlib[bcrypt]>=0.2",
# 图形验证码(纯 Python,依赖 Pillow)
"captcha>=0.6",
"pillow>=11.0",
"openpyxl>=3.1.5",
]
[dependency-groups]
dev = [
"pytest>=8.3",
"pytest-cov>=7",
"httpx>=0.28,<1.0",
# 用假 Redis 做单测,无需起容器即可覆盖 GETDEL 一次性语义
"fakeredis>=2.30",
# lint + format 二合一,替代 flake8 + isort + black
"ruff>=0.14",
]
# 本项目按应用而非库来管理,不打包安装自身
[tool.uv]
package = false
[tool.pytest.ini_options]
testpaths = ["tests"]
markers = [
"integration: 需要 MySQL/Redis 容器或完整应用实例的测试",
]
# ==================== 代码检查与格式化 ====================
[tool.ruff]
# 与项目根 .editorconfig 保持一致:Python 用 4 空格(缩进由 formatter 控制)
target-version = "py312"
line-length = 100
src = ["app", "tests"]
[tool.ruff.lint]
select = [
"E", # pycodestyle 错误
"W", # pycodestyle 警告
"F", # pyflakes:未使用的导入、未定义的名称等
"I", # isort:导入顺序
"B", # flake8-bugbear:常见陷阱(可变默认参数、循环引用等)
"C4", # flake8-comprehensions:推导式可简化处
"UP", # pyupgrade:按目标 Python 版本升级旧写法
"SIM", # flake8-simplify:可简化的分支与判断
"RUF", # ruff 自有规则
]
ignore = [
# 行宽已由 formatter 控制,lint 不再重复报——长中文注释很容易触发
"E501",
# FastAPI 的依赖注入要求在参数默认值处调用 Depends(),是框架约定而非缺陷。
# 项目内已尽量改用 Annotated 形式(见 api/deps.py),此处兜底。
"B008",
# RUF001/002/003 检查「易混淆的 Unicode 字符」,分别针对字符串字面量、
# 文档字符串、注释 —— 这套规则的默认前提是英文文本。
# 对中文会把全角逗号、句号、括号、冒号全部判定为混淆字符(本项目实测 800+ 条),
# 而中文里全角标点正是规范写法,故一并关闭。
"RUF001",
"RUF002",
"RUF003",
]
[tool.ruff.lint.isort]
# 必须显式声明:本项目 `[tool.uv] package = false`(不作为包安装),
# ruff 无法从项目布局推断出 `app` 是第一方包,否则会把第三方依赖
# 排到 `app.*` 之后(按字母序把两者当成同一组)。
known-first-party = ["app", "tests"]
[tool.ruff.lint.per-file-ignores]
# Alembic 自动生成的迁移脚本不按手写代码的标准要求。
# 这些文件由 `alembic revision --autogenerate` 产出,手工修 lint 会在下次生成时被覆盖。
"alembic/versions/*.py" = ["E501", "I001", "W291"]
[tool.ruff.format]
quote-style = "double"