feat(expense): 전부 다운로드 zip에 승인 목록 엑셀 동봉
- _build_approved_xlsx 헬퍼로 엑셀 생성 로직 추출(export/zip 공용)
- zip 최상단에 승인목록_{month}.xlsx 포함 + 첨부 파일들
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -402,19 +402,12 @@ async def approved_page(request: Request) -> HTMLResponse:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/api/approved/export.xlsx")
|
def _build_approved_xlsx(
|
||||||
async def approved_export(
|
items: list[dict[str, Any]], names: dict[str, str]
|
||||||
request: Request,
|
) -> io.BytesIO:
|
||||||
user: dict[str, Any] = Depends(_require_approver),
|
"""승인완료 목록 + 직원별합계 시트 xlsx 바이트 생성."""
|
||||||
) -> StreamingResponse:
|
|
||||||
from openpyxl import Workbook # 지연 import
|
from openpyxl import Workbook # 지연 import
|
||||||
|
|
||||||
store = _store(request)
|
|
||||||
_require_db_store(store)
|
|
||||||
year, mon, raw = _parse_month(request)
|
|
||||||
items = store.list_approved(year=year, month=mon)
|
|
||||||
names = _name_map(request)
|
|
||||||
|
|
||||||
wb = Workbook()
|
wb = Workbook()
|
||||||
ws = wb.active
|
ws = wb.active
|
||||||
ws.title = "승인완료"
|
ws.title = "승인완료"
|
||||||
@@ -453,6 +446,20 @@ async def approved_export(
|
|||||||
buf = io.BytesIO()
|
buf = io.BytesIO()
|
||||||
wb.save(buf)
|
wb.save(buf)
|
||||||
buf.seek(0)
|
buf.seek(0)
|
||||||
|
return buf
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/approved/export.xlsx")
|
||||||
|
async def approved_export(
|
||||||
|
request: Request,
|
||||||
|
user: dict[str, Any] = Depends(_require_approver),
|
||||||
|
) -> StreamingResponse:
|
||||||
|
store = _store(request)
|
||||||
|
_require_db_store(store)
|
||||||
|
year, mon, raw = _parse_month(request)
|
||||||
|
items = store.list_approved(year=year, month=mon)
|
||||||
|
names = _name_map(request)
|
||||||
|
buf = _build_approved_xlsx(items, names)
|
||||||
fname = f"expense_approved_{raw}.xlsx"
|
fname = f"expense_approved_{raw}.xlsx"
|
||||||
return StreamingResponse(
|
return StreamingResponse(
|
||||||
buf,
|
buf,
|
||||||
@@ -470,6 +477,7 @@ async def approved_attachments_zip(
|
|||||||
store = _store(request)
|
store = _store(request)
|
||||||
_require_db_store(store)
|
_require_db_store(store)
|
||||||
year, mon, raw = _parse_month(request)
|
year, mon, raw = _parse_month(request)
|
||||||
|
items = store.list_approved(year=year, month=mon)
|
||||||
atts = store.approved_attachments(year=year, month=mon)
|
atts = store.approved_attachments(year=year, month=mon)
|
||||||
names = _name_map(request)
|
names = _name_map(request)
|
||||||
upload_root = _upload_dir(request)
|
upload_root = _upload_dir(request)
|
||||||
@@ -495,6 +503,10 @@ async def approved_attachments_zip(
|
|||||||
buf = io.BytesIO()
|
buf = io.BytesIO()
|
||||||
used: dict[str, int] = {}
|
used: dict[str, int] = {}
|
||||||
with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf:
|
with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf:
|
||||||
|
# 1) 승인 목록 엑셀 동봉
|
||||||
|
xlsx_buf = _build_approved_xlsx(items, names)
|
||||||
|
zf.writestr(f"승인목록_{raw}.xlsx", xlsx_buf.getvalue())
|
||||||
|
# 2) 첨부 파일들
|
||||||
for a in atts:
|
for a in atts:
|
||||||
path = _resolve(a)
|
path = _resolve(a)
|
||||||
if path is None:
|
if path is None:
|
||||||
|
|||||||
Reference in New Issue
Block a user