提交
This commit is contained in:
1 parent
c3bd2c00ae
commit
a52fe77e34
39 files changed
+609647
-9238
No files matched your search
@@ -1,6 +1,10 @@
|
||||
import io
|
||||
from datetime import date as date_cls
|
||||
from typing import List, Optional
|
||||
from urllib.parse import quote
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
|
||||
from fastapi.responses import StreamingResponse
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@@ -21,6 +25,13 @@ from app.schemas.bx.reimburse import (
|
||||
)
|
||||
from app.services.bx.expense_item import ExpenseItemService
|
||||
from app.services.bx.reimburse import ReimburseService
|
||||
from app.services.bx.reimburse_import import (
|
||||
build_applicant_label,
|
||||
build_import_template_bytes,
|
||||
import_reimburse_workbook,
|
||||
load_applicant_options,
|
||||
load_expense_nodes_flat,
|
||||
)
|
||||
from app.utils.bx_codegen import generate_apply_code, generate_title, parse_optional_date
|
||||
from app.utils.bx_date_range import append_create_time_filters
|
||||
|
||||
@@ -84,6 +95,54 @@ def get_generated_title(
|
||||
return ApiResponse(data=title)
|
||||
|
||||
|
||||
@router.get("/import-template")
|
||||
def download_reimburse_import_template(
|
||||
db: Session = Depends(get_db),
|
||||
user: BxUserContext = Depends(get_bx_current_user),
|
||||
):
|
||||
tenant_no = _tenant(db, user)
|
||||
nodes = load_expense_nodes_flat(db, tenant_no)
|
||||
applicants = load_applicant_options(db, user=user, tenant_no=tenant_no)
|
||||
me = next((a for a in applicants if a["id"] == user.id), None)
|
||||
if me:
|
||||
cur_label = build_applicant_label(me["nick_name"], me["user_no"], me["id"])
|
||||
else:
|
||||
cur_label = build_applicant_label(user.name or "", "", user.id)
|
||||
applicants = [
|
||||
{"id": user.id, "nick_name": user.name or "", "user_no": ""}
|
||||
] + applicants
|
||||
raw = build_import_template_bytes(
|
||||
expense_nodes=nodes,
|
||||
applicants=applicants,
|
||||
current_applicant_label=cur_label,
|
||||
today=date_cls.today(),
|
||||
)
|
||||
filename = quote("报销申请导入模板.xlsx")
|
||||
return StreamingResponse(
|
||||
io.BytesIO(raw),
|
||||
media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
headers={
|
||||
"Content-Disposition": f"attachment; filename={filename}; filename*=UTF-8''{filename}"
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.post("/import", response_model=ApiResponse[dict])
|
||||
def import_reimburses(
|
||||
file: UploadFile = File(...),
|
||||
db: Session = Depends(get_db),
|
||||
user: BxUserContext = Depends(get_bx_current_user),
|
||||
):
|
||||
content = file.file.read()
|
||||
if not content:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="文件为空")
|
||||
try:
|
||||
result = import_reimburse_workbook(db, file_bytes=content, user=user)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
|
||||
return ApiResponse(data=result)
|
||||
|
||||
|
||||
@router.get("/", response_model=ApiResponse[PagedData[ReimburseApplyOut]])
|
||||
def list_reimburses(
|
||||
page: int = 1,
|
||||
|
||||
Reference in new issue
Block a user