Commit Graph

15 Commits

Author SHA1 Message Date
king 0b04a05b26 feat(expense): 관리자 분류 설정 메뉴 추가 (동적 분류)
- CategoryStore: 분류 항목 JSON 저장소(DATA_DIR/expense_categories.json)
- 관리자 설정 페이지(/expense/settings) + 분류 CRUD API
- _normalize 분류 고정목록 검증 제거 — 추가 분류 즉시 등록 폼/집계 반영
- index/reports 분류를 동적 목록으로 교체

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 17:22:01 +09:00
king ec8c9edcc9 fix(expense): 라운드 제거 대상은 .erp-table-wrap + 클립 아이콘 22px 강제
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 02:14:21 +09:00
king 7ff3500844 ui(expense): 내역 표 첫 행 모서리 라운드 제거 + 첨부 아이콘 확대
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 02:11:44 +09:00
king 84624baf8e ui(expense): 경비 내역 표 가운데 정렬 + 동작 헤더 제거 + 한 줄(너비 자동)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 02:08:22 +09:00
king d728c55e2a fix(expense): 요약카드 70px 강제(!important) + 요약줄·등록폼 간격 추가
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:40:22 +09:00
king 55c98b6b95 fix(expense): 요약카드 70px — grid-auto-rows 로 행 높이 고정(stretch 무력화)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:37:16 +09:00
king ca53042eb4 ui(expense): 상단 요약카드 70px + 경비등록(좌)/경비내역(우) 2단 배치
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:31:32 +09:00
king fa1027fa1b feat(time): 프로젝트 전체 시간 KST(UTC+9) 통일
- app/timezone.py 신설: KST 고정오프셋(+9, DST 없음) + now_kst/today_kst/to_kst_iso
- DB 직렬화 created_at/updated_at/decided_at/uploaded_at 표시를 UTC→KST 로 변환
  (expense/cupang/vacation db.py)
- _now_iso(JSON 저장) KST 기준
- 라우터 date.today()/datetime.now() → today_kst()/now_kst() (달력 '오늘'/엑셀 파일명)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 08:48:28 +09:00
king 6918426264 feat(expense): 첨부 뷰어 패닝/엑셀 + 체크박스 일괄작업 + 정렬
[첨부 뷰어]
- 펜 주석 기능 제거 (요구사항 정정).
- 이미지: 마우스 드래그로 패닝, 축소/확대/100%/맞춤 줌 도구.
- 엑셀 (xlsx/xls/xlsm/csv/ods): SheetJS lazy load(CDN) 후 시트 탭으로 표시.
- 기타 파일: 다운로드/새 창 링크.

[경비 내역 / 승인 대기 공통]
- 행 단위 첫 컬럼 체크박스 + thead 전체선택 체크박스.
- 표 제목 상단에 일괄 동작 버튼 (선택 0이면 disabled).
- 카드 헤더와 행 모두 vertical-align: middle 로 일직선 정렬.

[경비 내역]
- 첨부 추가 버튼의 📎 아이콘 제거. "기타" → "기타 파일".
- 행 단위 "제출" 버튼 제거 → 상단 "선택 항목 제출" 단일화.
- 행 단위 첨부 보기 아이콘(📎) 추가 — 클릭 시 ErpAttachViewer 호출.

[승인 대기]
- 일괄 승인 (체크 후 상단 버튼).
- 반려는 항목별 유지 (사유 필수라 일괄 부적합).

[CSS]
- erp-table tbody td vertical-align top → middle (admin 포함 일관).
2026-05-29 03:57:18 +09:00
king 151de492ad feat(expense): 첨부 뷰어 모달 — 이미지 미리보기 + 펜 주석
승인 대기 페이지의 "첨부" 텍스트 링크를 클립 아이콘 버튼으로 교체.
클릭 시 모달 팝업으로 이미지 미리보기 + 마우스 펜 주석 + 다운로드.

뷰어 컴포넌트 (전역, 다른 페이지에서도 재사용 가능):
- 좌측: 첨부 목록 (썸네일/메타)
- 우측: 캔버스 스택 (img + 투명 canvas)
- 도구: 펜/지우개, 색상 4종, 굵기 3종, 전체 지우기, 합성 PNG 저장, 원본 열기
- 이미지 외 파일은 다운로드 링크만 표시
- ESC/배경 클릭으로 닫기, pointer events 지원

전역 노출: window.ErpAttachViewer.{open, openFor, close}
2026-05-29 03:40:03 +09:00
king d4af2dc064 ui(expense): 첨부 버튼을 동작 셀에 직접 노출 (화살표 토글 제거)
기존: 행마다 ▸ 화살표 클릭 → 상세 영역 펼침 → 영수증/기타 추가
변경: 동작 셀에 📎영수증 / 📎기타 버튼 항상 노출.
      첨부 목록은 메인 행 바로 아래 인라인으로 항상 표시.

페이지 로드 시 모든 항목의 첨부 자동 fetch.
업로드 input 위치 변경에 맞춰 JS 핸들러 보정.
2026-05-29 03:33:41 +09:00
king d2c1dfa2a0 fix(expense-db): _serialize 에서 decided_at 도 ISO 문자열로 변환
신규 워크플로 컬럼 decided_at (TIMESTAMPTZ) 가 datetime 그대로 템플릿에
전달돼 'datetime.datetime' object is not subscriptable 로 500 발생.
created_at/updated_at 과 같이 isoformat 변환 대상에 포함.
2026-05-29 03:29:16 +09:00
king a4eaf9b770 fix(expense-db): 앱 부팅 시 DDL 실행 제거 + lazy pool open
PostgreSQL 15+ 는 public 스키마 CREATE 권한을 PUBLIC 역할에서 회수했기 때문에
expense_app (앱 전용 비특권 계정) 으로 CREATE TABLE 시도하면
"permission denied for schema public" 으로 컨테이너 부팅 실패.

스키마 책임 분리:
- DDL: scripts/sql/expense_db_init.sql + expense_db_002_workflow_attachments.sql
       (superuser 가 사전 적용)
- 런타임: SELECT/INSERT/UPDATE/DELETE 만

ConnectionPool 도 open=False + lazy open 으로 변경. DB 가 잠시 끊겨도
컨테이너가 죽지 않게 함.
2026-05-29 03:22:08 +09:00
king 550867ba0c feat(expense+admin): 결재 워크플로 + 첨부 + 집계 + 엑셀 + 사용자 직접 등록
[admin]
- POST /api/users 사용자 직접 등록 (이메일만으로). UserStore.create_user 추가
- admin.html: 등록 폼 + 삭제 버튼 + 한글 라벨 + 신규 권한 표시
- 신규 권한 키: expense_approver, vacation_approver (APPROVER_KEYS)
- is_approver(user_rec, kind) 헬퍼

[expense 워크플로]
- 상태 전이: 작성중 → 제출 → 승인/반려 → 정산완료
- API: /api/items/{id}/{submit,revert,approve,reject,settle}
- 권한: submit/revert=owner, approve/reject/settle=expense_approver 또는 admin
- expense_items 컬럼: approver_email, decided_at, reject_reason
- 작성중/반려 상태에서만 수정/삭제/첨부 가능

[expense 첨부]
- 영수증/기타 (kind: receipt|other). 최대 20MB, 확장자 화이트리스트
- 저장: DATA_DIR/uploads/expense/{item_id}/{att_id}_{filename}
- expense_attachments 테이블 (CASCADE on item delete)
- API: 업로드/목록/다운로드/삭제

[expense 집계]
- /expense/reports: 연도별 월×카테고리 피벗 표

[expense 엑셀]
- GET /expense/api/export.xlsx?from&to&scope=mine|all
- scope=all 은 승인자/관리자만

[DDL]
- expense_db_init.sql: 신규 컬럼/테이블 포함 (멱등)
- expense_db_002_workflow_attachments.sql: 운영 DB 마이그레이션용

[deps]
- openpyxl>=3.1, python-multipart>=0.0.20

[docs]
- DATABASES.md: 워크플로 다이어그램, attachments 테이블, 마이그레이션
- PROJECT_OVERVIEW.md: 권한 키 표
- DEPLOYMENT.md: DATA_DIR/uploads 안내
2026-05-29 02:52:44 +09:00
king 9c58b022e2 feat(expense): 개인경비 모듈 + ERP 좌측메뉴 셸 + expense_db 연결
- ERP 셸: 좌측 사이드바 + 상단 헤더 + 콘텐츠 영역(erp_base.html)
- 분기: 슈퍼관리자 → 업무모듈 카드, 일반사용자 → ERP 메인(erp_home.html)
- 신규 라우트: /modules (슈퍼관리자 모듈 카드 재진입)
- 개인경비 모듈: app/modules/expense/ (라우터/저장소/템플릿)
  - JSON 저장소(ExpenseStore) + PostgreSQL 저장소(ExpenseDBStore)
  - 팩토리: EXPENSE_DB_URL 있으면 DB, 없으면 JSON 폴백
- DB: scripts/sql/expense_db_init.sql (멱등 DDL, postgres-db 컨테이너)
  - expense_db, 역할 expense_app, 테이블 expense_items, 인덱스/트리거
- 마이그레이션: scripts/migrate_expense_json_to_db.py (멱등, --dry-run)
- 의존성: psycopg[binary,pool]>=3.2
- 환경변수: EXPENSE_DB_URL 추가
- 문서: CLAUDE.md 작업 기준 + docs/{PROJECT_OVERVIEW,SERVER_ARCHITECTURE,DATABASES,DEPLOYMENT}.md
  - main-app 배포 경로 /opt/www/main 고정 명시
  - 위험 명령(DROP/TRUNCATE/rm -rf/volume 삭제) 사용자 승인 정책
2026-05-29 02:21:03 +09:00