refactor: 统一项目代码风格并修复多处类型与调用问题

本次提交包含多项优化:
1.  移除大量冗余的文件头注释与过时的from __future__导入
2.  将CRUD的list方法统一重命名为get_list保持接口一致
3.  修复前后端状态字段类型不匹配问题,将string类型status改为number
4.  修正前端文案错别字,将"代办事项"修正为标准写法
5.  更新sqlalchemy版本并调整依赖配置
6.  新增缓存工具类替代fastapi-cache2,重构缓存调用逻辑
7.  新增开源授权函生成相关工具与数据库字段支持
8.  为多个业务模块添加防重复提交loading状态
9.  修复邮件模型的外键关联缺失问题
10. 优化pdf生成工具的导入时机与文档注释
This commit is contained in:
zhangtao
2026-06-21 17:34:11 +08:00
parent 3169ef2355
commit 7d2367e34e
106 changed files with 1968 additions and 966 deletions
@@ -0,0 +1,97 @@
"""开发辅助脚本:为 platform_invoice.json 中所有已开票(status=1)的种子发票生成示例 PDF。
使用场景:
- 首次启动开发环境后,初始化数据已导入,但 PDF 文件并不存在
- 前端访问 /static/invoice/...pdf 会 404
- 跑此脚本批量生成,发票 PDF + 授权函 PDF,路径与 JSON 中 pdf_url / oss_license_pdf_url 完全一致
用法:
cd backend
uv run python tests/scripts/seed_invoice_pdfs.py
依赖:
- weasyprint(pyproject.toml 已包含)
- macOS 上需先安装系统库:brew install glib pango libffi(Linux 部署环境正常)
"""
import asyncio
import json
import sys
from pathlib import Path
BACKEND_DIR = Path(__file__).resolve().parent.parent.parent
sys.path.insert(0, str(BACKEND_DIR))
from app.api.v1.module_platform.invoice.pdf_helper import ( # noqa: E402
_render_invoice_pdf,
_render_oss_license_pdf,
)
from app.api.v1.module_platform.invoice.schema import InvoiceOutSchema # noqa: E402
SEED_JSON = BACKEND_DIR / "app" / "scripts" / "data" / "platform_invoice.json"
def _to_out_schema(record: dict) -> InvoiceOutSchema:
"""把 JSON 字典转为 InvoiceOutSchema,缺失的字段用合理默认填充"""
return InvoiceOutSchema(
id=record.get("id", 0),
invoice_no=record["invoice_no"],
order_id=record["order_id"],
tenant_id=record["tenant_id"],
invoice_type=record["invoice_type"],
title=record["title"],
tax_no=record.get("tax_no"),
bank_info=record.get("bank_info"),
address_info=record.get("address_info"),
amount=record["amount"],
tax_amount=record.get("tax_amount", 0),
status=record.get("status", 1),
description=record.get("description"),
created_time=record.get("created_time", "2026-01-01 00:00:00"),
updated_time=record.get("updated_time", "2026-01-01 00:00:00"),
created_by=record.get("created_by", {"id": 1, "name": "admin"}),
updated_by=record.get("updated_by", {"id": 1, "name": "admin"}),
)
async def main() -> int:
if not SEED_JSON.exists():
print(f"[ERR] 找不到种子数据: {SEED_JSON}")
return 1
records = json.loads(SEED_JSON.read_text(encoding="utf-8"))
issued = [r for r in records if r.get("status") == 1]
print(f"种子数据共 {len(records)} 条,其中 status=1(已开票){len(issued)} 条\n")
if not issued:
print("无需生成")
return 0
success = 0
failed = 0
for rec in issued:
invoice_no = rec["invoice_no"]
try:
invoice = _to_out_schema(rec)
invoice_url = _render_invoice_pdf(invoice)
license_url = _render_oss_license_pdf(invoice)
inv_full = BACKEND_DIR / invoice_url.lstrip("/")
lic_full = BACKEND_DIR / license_url.lstrip("/")
print(f" ✓ {invoice_no}")
print(f" 发票 PDF: {invoice_url} ({inv_full.stat().st_size} bytes)")
print(f" 授权函 PDF: {license_url} ({lic_full.stat().st_size} bytes)")
success += 1
except Exception as e:
print(f" ✗ {invoice_no}: {type(e).__name__}: {e}")
failed += 1
print(f"\n=== 完成:成功 {success} 条,失败 {failed} 条 ===")
if failed:
print("\n如果提示缺少 libgobject/pango:")
print(" macOS: brew install glib pango libffi")
print(" Ubuntu: sudo apt-get install libpango-1.0-0 libpangoft2-1.0-0")
return 0 if failed == 0 else 2
if __name__ == "__main__":
sys.exit(asyncio.run(main()))