체크된 계좌만 해당 역할에 노출됩니다. 체크하지 않은 계좌(신규 업로드 포함)는 관리·영업/구매 역할에 보이지 않습니다.
관리
영업/구매
은행
계좌번호
계좌종류
거래건수
블락리스트 · 영업/구매 차단 조건
하나라도 일치하면 영업/구매 역할에 노출되지 않습니다.
활성
필드
매칭
값
생성
📈 자금흐름 그래프
X축: 1/1 ~ 12/31 · Y축: 일별 말잔액(그날 마지막 거래 기준) · 선형 포워드필. 연도 체크박스로 과거 해까지 동시 비교.
연도 (복수 선택)
시리즈 (전체 자금 + 계좌별)
데이터 로드 중…
로딩 중…
선택된 조건에 해당하는 데이터가 없습니다.
📘 시스템 가이드 (시스템관리자 전용)
SFiT-Bank 의 구조·인증·역할·데이터 흐름·백업·배포 파이프라인을 다이어그램으로 정리한 운영 문서.
각 다이어그램은 운영 중 의사결정(권한 이슈·데이터 복구·버전업) 시 참조.
1. 전체 아키텍처
클라이언트 → Nginx → Flask → PostgreSQL / MinIO / LDAP. 모두 단일 호스트(192.168.1.15) 의 Docker 스택.
graph TB
U[사용자 브라우저] -->|HTTPS/HTTP :7111| N[Nginx bank-frontend]
N -->|정적 HTML/CSS/JS| U
N -->|/api/*| B[Flask + gunicorn bank-backend :5000]
B --> DB[(PostgreSQL 16 bank-db :5432)]
B --> M[MinIO bank-minio]
B -->|LDAP SIMPLE bind| L[AD sun.sft.co.kr:389]
subgraph "Docker Stack - host 192.168.1.15"
N
B
DB
M
end
R[Harbor Registry hub.sft.co.kr/bank] -->|pull| B
R -->|pull| N
2. 인증 흐름 (LDAP + 로컬 bcrypt)
users 테이블의 ldap_user 플래그로 분기. LDAP 는 UPN(user@sft.co.kr) 으로 SIMPLE bind. 로컬은 bcrypt 검증.
sequenceDiagram
participant 사용자
participant 프론트
participant 백엔드
participant LDAP
participant DB
사용자->>프론트: 아이디 / 비밀번호
프론트->>백엔드: POST /api/login
백엔드->>DB: SELECT users WHERE username=?
DB-->>백엔드: row (ldap_user, password_hash, role, enabled)
alt ldap_user = TRUE
백엔드->>LDAP: bind(user@sft.co.kr, pw)
LDAP-->>백엔드: 성공 / 실패
else 로컬 계정
백엔드->>백엔드: bcrypt.checkpw(pw, hash)
end
백엔드->>DB: UPDATE users SET last_login = NOW()
백엔드-->>프론트: 세션 쿠키 + {role, display_name}
프론트-->>사용자: UI 렌더 (역할별 버튼 노출/숨김)
admin 계정 보호: 시스템관리자 고정, 역할 변경·비활성화·삭제 불가 (비밀번호만 교체 가능).
·
기본 비노출: 신규 업로드로 나타난 계좌는 관리·영업/구매 역할에 자동으로 안 보임. 시스템관리자가 🏦 에서 체크해야 노출.
4. Excel 업로드 → DB 저장
헤더 기반 동적 매핑(HEADER_MAP) + SHA256 해시로 중복 자동 제거. V0.09.0부터 tx_date/tx_time 은 DATE/TIME 네이티브 타입.
flowchart TD
Start([Excel 업로드]) --> Head[첫 행 헤더 인식 HEADER_MAP 으로 컬럼→DB필드 매핑]
Head --> Err{헤더 인식?}
Err -->|실패| Fail[400 응답: 포맷 오류]
Err -->|성공| Loop[각 데이터 행 순회]
Loop --> Parse[tx_date → datetime.date tx_time → datetime.time 금액 → int]
Parse --> Skip{bank_name account_no tx_date 있음?}
Skip -->|없음| Drop[skip]
Skip -->|있음| Hash["SHA256 해시 생성 (account|ISO date|HH:MM:SS| dep|wd|bal)[:32]"]
Hash --> Ins[(INSERT ... ON CONFLICT hash DO NOTHING)]
Ins -->|신규| OK[inserted++]
Ins -->|해시 중복| Dup[duplicated++]
OK --> Loop
Dup --> Loop
Drop --> Loop
Loop --> End([총 / 신규 / 중복 카운트 반환])
5. 조회 필터 체인 (역할별)
/api/ledger·/api/summary 공통. AND 로 결합. /api/export 는 관리자 전용이라 별도 필터 없음.
flowchart LR
Q[쿼리 시작 currency=KRW] --> S{role}
S -->|sales| S1[AND withdrawal=0 AND account_visibility.sales=TRUE AND NOT 블락룰 매칭]
S -->|manager| S2[AND account_visibility.manager=TRUE]
S -->|그 외| S3[필터 없음]
S1 --> D[AND tx_date 범위]
S2 --> D
S3 --> D
D --> Search[AND 검색어 ILIKE summary·counterparty·memo· detail_memo·branch]
Search --> Order[ORDER BY bank_name, account_no, tx_date, tx_time]
Order --> Result[응답]
Result --> Mask{sales?}
Mask -->|예| M1[balance·total_withdrawal = null 프론트 *** 마스킹]
Mask -->|아니오| M2[원값 반환]
6. DB 백업 흐름 (NFS → Synology NAS)
pg_dump | gzip → /mnt/nas-backup/Bank/ (NFSv3). deploy 시점 + 매일 03:00 크론. 최신 10카피 회전.
sequenceDiagram
participant Dev as 로컬 (개발자 PC)
participant Harbor as hub.sft.co.kr/bank
participant Srv as 서버 192.168.1.15
participant DB
participant NAS
Dev->>Dev: VERSION 파일 편집
Dev->>Dev: docker build (backend · frontend)
Dev->>Harbor: docker push :TAG + :latest
Dev->>Srv: ssh / sftp (paramiko)
Srv->>Harbor: docker compose pull
Srv->>Srv: docker compose up -d
Srv->>DB: 백엔드 기동 → init_db() 스키마 마이그레이션 자동 실행
Srv->>NAS: backup.sh deploy V → NFS
Srv->>Srv: crontab 재등록 (idempotent)
Srv-->>Dev: 컨테이너 상태 출력