Backend Changelog

NHN On-Premise 백엔드(cone-watcher-backend) 변경 이력

Initial Setup — NHN 전용 기능 변경

추가된 기능

파트너 사용량 관리

파트너(MSP 업체)별 클라우드 서비스 이용량을 월 단위로 집계하고 과금하는 기능.

  • 파트너 목록/상세 조회, 기본 할인율(0~100%) 및 할인 기간(시작월~종료월) 설정
  • apply_immediately=True 시 미발행(Unissued) 상태 사용량의 할인율을 즉시 재계산
  • 파트너 사용량 상태: Origin → Unissued → Invoiced → Paid → Overdue
  • 사용량 목록/상세 엑셀 다운로드
  • 리셀러 타입: NHN Cloud, NHN InjeINC, Grumatic, 없음
  • Worker 태스크: 회사별 월간 발행 청구서 수를 집계하여 건당 단가 산정 (30건 초과: 30,000원/건, 30건 이하: 27,500원/건, FREE_INVOICE_COUNT=0). 리셀러 할인율 적용 후 Origin + Unissued 이중 레코드 생성
  • Scheduler: partner_usage_task — cron 기반 자동 실행

회사 이메일 설정 관리

청구서 이메일 발송 시 본문에 삽입되는 커스텀 머리말(email_header)/꼬리말(email_footer) 설정.

  • company_settings 컬렉션에 company_id 기준으로 저장
  • 설정이 없으면 자동 생성(upsert-on-read)
  • 청구서 이메일 발송 시 CUSTOM_HEADER, CUSTOM_FOOTER 파라미터로 본문에 삽입

파일 관리 API (로고/직인)

회사 로고 및 직인 이미지를 MongoDB GridFS 기반으로 업로드/관리하는 기능.

  • DefaultFSService (Singleton, GridFS 기반, company_id 인덱스)
  • ImageFSService (이미지 검증 및 리사이징)
  • LogoFSService, StampFSService (로고/직인 전용 구현)
  • 업로드 시 기존 파일 자동 교체, 메타데이터(원본 파일명, 확장자, 크기, 업로드일) 저장

거래명세서

청구서 기반 거래명세서 Excel 생성 및 다운로드. invoice_full.xlsx 템플릿 사용.

시스템 에러 로깅

error_log 컬렉션에 source(smtp/nhn_api/worker/scheduler), action, exception_type, message, traceback, context 필드로 에러 저장. TTL 90일 자동 삭제. SMTP 연결/발송 실패, NHN API 요청 실패, Worker 태스크 실패 등에 적용.

이메일 발송 로깅

invoice_deliveries 컬렉션에 발송 결과 저장. 필드: status(SUCCESS/FAILED), requested/accepted/refused recipients, cc/bcc recipients, sender_name, subject, attachments, error_message, smtp_context. TTL 1년. SMTP의 send_email() 반환값을 bool에서 dict로 변경하여 refused_recipients 등 상세 결과 추적.

스케줄러 (APScheduler)

APScheduler 기반 cron 스케줄러. 5개 정기 작업 등록:

  • nhn_invoice_task — NHN 청구서 자동 생성
  • update_nhn_project_list_task — NHN 프로젝트 목록 동기화
  • contract_expiration_task — 계약 만료 알림
  • auto_suspend_expired_organizations — 만료 고객사 자동 중지
  • partner_usage_task — 파트너 사용량 집계

수정된 기능

사용자/역할 체계

  • 역할 계층: ROOT, SUPERUSER, ADMIN, MANAGER, CLIENT_ADMIN, CLIENT_USER (6단계)
  • SUPERUSER 역할이 ROOT과 ADMIN 사이에 추가됨. Admin 포탈 접근 및 파트너 관리 권한 보유.
  • is_superuser 프로퍼티 추가, includes_role() 메서드에 SUPERUSER 체인 삽입
  • CloudProviderType: Literal['aws', 'ncp', 'nhn']Literal['nhn'] (단일 CSP)
  • NHNCloudType: Literal['NORMAL']Literal['NORMAL', 'GOV'] (GOV 타입 추가)

고객사(조직) — 계정 모델 재설계

NHN 파트너 이메일 기반의 단일 CSP 계정 구조.

  • NHNPartnerEmail(uid, email, discount_rate) + NHNPartnerAccount(org_id, org_name, org_type, org_status, project_id, project_name, project_type, project_status, discount_rate)
  • 계정 관리 단위가 프로젝트 단위에서 파트너 이메일 단위로 변경
  • cloud_accounts 필드 타입: List[Union[AWSAccount, NCPAccount, NHNAccount]]list[NHNPartnerAccount]
  • partner_emails: list[NHNPartnerEmail] 필드 추가
  • cc_integrated_allow (CC 연동 허용) 필드 제거
  • 이메일 수신자 자동 결정: get_default_recipients() (billing_email_option='primary'인 연락처), get_cc_recipients() (billing_email_option='cc'인 연락처)
  • 조직 생성 시 계정 연결 단계 제거 (별도 프로세스로 분리)
  • 조직 목록 스키마: number_of_aws_accounts, number_of_ncp_accountsnumber_of_accounts 단일 필드
  • 조직 요약 by_csp: {'aws': 0, 'ncp': 0}{'nhn': 0}

청구서

  • 환율 관련 필드 제거: exchange_rate_id, exchange_rate_value, exchange_rate_source (NHN은 원화 전용)
  • org_cloud_cost 필드 추가: 고객사 전체 청구서의 cloud_cost.krw 합산값을 각 청구서에 저장
  • 청구서 필터링 스키마 추가: 날짜 범위, 조직 ID 목록, 상태 목록, 청구서 ID 목록으로 복합 필터
  • 대량 상태 변경 스키마 추가: 여러 청구서를 한번에 Invoiced로 변경하면서 이메일 발송, 보증금 처리 일괄 수행
  • 자동완성 스키마 추가: 청구서 ID/고객사명 기반 검색
  • 수신자 구조 변경: email_list: list[str]recipients, cc_recipients, bcc_recipients (To/CC/BCC 분리)
  • 이메일 발송 시 회사 설정(email_header/email_footer)을 본문에 삽입
  • CSV 다운로드 기능 제거

청구서 PDF

  • 인보이스 타입: Union[AWSInvoice, NCPInvoice, NHNInvoice]NHNInvoiceModel 단일
  • 로고 로딩: CDN URL 참조 → LogoFSService에서 GridFS 파일 로드 후 base64 인코딩
  • 커버 페이지에 NHN 원가(ORIGIN_CLOUD_USAGE), NHN 할인액(CLOUD_DISCOUNT) 구분 표시
  • 계정별 요약에 OriginUsage, CloudDiscount 컬럼 추가
  • 클라우드 사용 상세에 카운터 항목별 USAGE_COST, DISCOUNT_RATE, COST 분리 표시
  • Excel 템플릿: invoice_consolidation.xlsxinvoice.xlsx, invoice_consolidation_full.xlsxinvoice_full.xlsx (멀티CSP 시트 로직 제거)

NHN 계정 API — 인증 방식 변경

  • ID/PW 인증 전용(tenant_id, username, password, cloud_type). NHNResellerClient 사용.
  • 인증 정보를 config-level NHNCredential로 관리. NORMAL/GOV 각각 nhn, nhn_gov 설정으로 분리.
  • 제거된 기능: 계정 계층 구조 조회, TemporaryData 기반 UI 생성 플로우, UUID 별도 업데이트, 사용자 정보 검증, 할당 프로젝트 목록 조회
  • 추가된 기능: cloud_type(NORMAL/GOV) 지원, 중복 UUID 체크, account_name 변경

NHN 매출 API

  • 매출 항목에 invoice_id 필드 추가
  • NHNProjectExtra 모델 추가: 프로젝트별 조정(project_extra.total_adjustment) 및 할인(project_discount.total_adjustment) 상세 내역 포함
  • 매출 그래프: purchase_month/supply_month 분리 → target_month 하나로 통합
  • 매출 테이블: 삭제된 조직도 포함하여 조회 (include_deleted=True)
  • 매출 매입 상세 API 추가: 특정 청구서의 프로젝트별 서비스>리전>상품 계층 매입 내역

Worker — 청구서 자동 생성 재설계

  • 조직의 partner_emails 순회 → 이메일별 get_projects_by_email() → CLOSED 상태/기존 프로젝트/이미 발행된 청구서 스킵 → partner.discount_rate 적용. 기존 프로젝트는 건너뜀.

Worker — 계정 동기화 재설계

  • 조직의 partner_emails 순회 → 이메일별 프로젝트 목록 조회 → 신규/기존 NHNPartnerAccount 생성/갱신 → 사라진 프로젝트를 부가서비스/할인/계약에서 자동 제거 → 신규 프로젝트 발견 시(매월 4일 15:00 이후) 자동 청구서 생성 태스크 실행
  • 태스크명 변경: update_nhn_account_hierarchyupdate_nhn_project_list (파라미터: account_uidaccount_id + organization_id)

이메일 발송

  • 클라이언트: AWS SES → SMTP 직접 연동 (common/client/email/smtp.py)
  • 수신자: 단일(recipient: str) → 다중(recipients: list[str] + cc/bcc)
  • 로고: CDN URL → LogoFSService(GridFS)에서 파일 존재 확인 후 URL 설정
  • 발신자: SENDER_NAME, SENDER_EMAIL, SENDER_ADDRESS, CUSTOM_SENDER 파라미터 추가
  • Jinja2 커스텀 필터: nl2br(줄바꿈→BR), to_preview(HTML 태그 제거)
  • 영문 템플릿 전체 제거, 한국어 전용
  • 이메일 제목: 하드코딩 [heka][{{APP_NAME}}] 동적 치환
  • 청구서 이메일 제목: [{{COMPANY_NAME}}] {{BILLING_MONTH}} 청구서 - {{CUSTOMER_NAME}}

회사 모델

  • 추가 필드: reseller_type(NONE/NHN/INJE/GRMT), reseller_discount_rate(0~1), discount_start_month, discount_end_month
  • is_trial 기본값 True→False, trial_date 기본값 변경, remove_prefix 필드 제거

2026년 3월

03-11

  • 청구서 자동 생성 스킵 조건 추가 (PoC #2): org.options.invoice_creation이 False, org.partner_emails가 비어있음, 해당 프로젝트의 모든 계약이 만료된 경우 각각 logger.warning으로 사유를 기록하고 건너뜀
  • 초대 로그인 시간 기록 (PoC #4): verify_user_invited_login 메서드에서 토큰 생성 전 update_last_login() 호출 추가. 기존에는 일반 로그인에서만 기록하고 초대 로그인에서는 누락
  • 계약 변경 시 고객사 상태 자동 재판단 (PoC #5): 계약 수정/삭제 후 _reevaluate_organization_status() 호출. auto_status_change 옵션이 True일 때, 모든 계약이 만료이면 in-use/poc → suspended, 유효 계약이 하나라도 있으면 suspended → in-use로 변경
  • 마지막 관리자 역할 변경 방지 (PoC #6): 대상 사용자가 ADMIN이고 다른 역할로 변경 요청 시, 해당 회사에 ADMIN 이상 사용자가 1명 이하이면 DeleteLastAdminException 발생
  • 고객사 목록 등록 역순 정렬 (PoC #10): 조회 시 최신 등록 순으로 정렬
  • 계약 알림 일수 음수 방지 (PoC #11): ContractSchemage=0 제약 추가
  • 크레딧 VAT 별도 금액 차감 (PoC #13): supply = subtotal - deposit으로 공급가액 산출, VAT를 supply * 0.1로 계산 (기존: subtotal * 0.1). PDF 커버에서 BALANCE_DUE 항목 제거, 크레딧을 할인 아래 별도 행으로 표시. "선납금" → "크레딧", "인보이스 합계" → "크레딧 차감액", "납부하실 금액 (VAT 별도)" → "(VAT 포함)"으로 용어 변경
  • 프로젝트 선택 필터링 (PoC #16): NHNPartnerEmailselected_projects: list[SelectedProject] 필드 추가. 계정 추가/수정 시 프로젝트 미리보기 API(POST /{org_id}/account/preview)로 이메일 기반 프로젝트 목록 조회 후 선택 저장. Worker 동기화 시 selected_ids 필터 적용하여 선택된 프로젝트만 cloud_accounts에 포함. API에서 더 이상 조회되지 않는 프로젝트는 available=False로 갱신.

03-12

  • 프로젝트 필터링 후속 수정 (PoC #16): 파트너 이메일 확인 시 404/409 에러 처리 추가. 청구서 자동 생성 Worker에서 selected_ids 필터가 실제 반영되도록 수정.

03-20

  • "계정" → "프로젝트" 명칭 통일 (PoC #25): 청구서/이메일 템플릿 8개에서 "NHN Cloud 계정" → "NHN Cloud 프로젝트" 변경
  • 부가서비스/할인에 프로젝트ID 표기 (PoC #22): PDF 부가서비스/할인 항목에 프로젝트ID 컬럼 추가
  • 원 단위 통일 (PoC #42): 이메일 청구서 금액 표기를 원 단위로 통일
  • 클라우드 요금 개요 섹션 (PoC #15): PDF에 "서비스별 클라우드 요금 개요" 테이블 추가 (컬럼: 프로젝트, 카테고리, 리전, 서비스, 금액). NHN 인보이스 data를 서비스>리전>상품 3단계로 순회하여 ProductTotalCost 출력. 기존 "서비스별 클라우드 요금"은 "서비스별 클라우드 상세 요금"으로 명칭 변경. "클라우드 제공사별 요약" 섹션 비활성화.
  • 리포트 프로젝트별 청구 금액 (PoC #17): ReportSettingsModelprojects: list[str] 필터 추가. NHN 인보이스를 project_id 기준으로 그룹핑하여 월별 cloud_cost + additional_cost - discount_cost 합산. 엑셀에 "프로젝트별 청구금액" 시트 추가 (컬럼: 날짜, 고객사명, 프로젝트명, 금액). GET /organizations/cloud-accounts 엔드포인트 추가.
  • 보조용언 띄어쓰기 통일 (PoC #41): 이메일 템플릿 내 보조용언 띄어쓰기 일괄 수정
  • 표기 수정 반영: 청구서/리포트/매출 Excel/PDF에서 "미납" → "연체" 등 용어 수정
  • 비밀번호 재설정 이메일 검증 (PoC #44): 비밀번호 재설정 시 이메일 불일치에 대한 명확한 오류 응답 추가

03-23

  • 페르소나 로그인 활성화: Admin 라우터에서 페르소나(가장) 로그인 엔드포인트 활성화

03-24

  • 클라우드 요금 개요 PDF 렌더링 수정 (PoC #15)

03-27

  • 사용자 이메일 검증 API (PoC #66): GET /users/check-email?email= 엔드포인트 추가. 초대 전 이메일 중복 여부 사전 확인.
  • 초대 완료 오류 조건 강화 (PoC #60): 초대 완료 처리 시 404(이메일 불일치), 401(토큰 만료), 400(이미 설정 완료) 별 구체적 오류 응답

03-30

  • Admin 권한 분리 (PoC #83): Admin 라우터 5개 엔드포인트의 scope를 ROOT, SUPERUSER로 제한
  • Admin 청구서 단가 변경 (PoC #82): 단가 설정 스키마 추가

03-31

  • 역할 체계 재정비 (PoC #83): SUPERUSERSYSTEM_ADMIN으로 명칭 변경. 역할 계층: ROOT > SYSTEM_ADMIN > ADMIN > MANAGER. 로그인 채널 분리 — is_admin_login=True 시 SYSTEM_ADMIN 이상만 로그인 가능, 일반 콘솔에서 SYSTEM_ADMIN 차단. 사용자 목록에서 SYSTEM_ADMIN 비노출. 회사 설정/로고/NHN 계정 등 약 20개 엔드포인트에서 SUPERUSER scope 제거하여 ROOT > ADMIN > MANAGER 체계로 통일.
  • 거래명세서 수정: 거래명세서 생성 로직 수정

2026년 4월

04-10

  • 크레딧 내역 수정: 청구서 PDF 최근 3개월 크레딧 내역의 계산/표시 오류 수정

04-13

  • 최신 청구서 판별 로직 추가: 청구서 상세 API 응답에 IsLatest: bool 필드 추가. nhn_invoice_service.get_latest_date_by_organization_id()로 해당 고객사의 최신 인보이스 날짜를 DB에서 조회하여, 현재 청구서의 date가 최신 날짜와 일치하면 IsLatest=True. 프론트엔드에서 최신 월이 아닌 청구서의 금액 수정을 차단하는 데 사용.