콘텐츠로 이동

labor_ledger 스키마

월별 노임대장 문서의 전체 스키마. 각 현장의 월별 근로자 출역/공수/임금/수수료를 집계 관리합니다.

저장 위치

companies/{company_id}/sites/{site_id}/labor_ledger/{YYYYMM}
  • doc_id는 연월을 "YYYYMM" 형식으로 고정 (예: "202601").
  • 문서는 현장의 출역(attendance_logs) 트리거 또는 출역 수정 시 init_labor_ledger()에 의해 자동 생성됩니다.
  • companies/{company_id}/settings/tags 문서에서 labor_suppliers, commission 설정을 초기값으로 복사해옵니다.

생성/갱신 흐름

출역 생성(attendance_logs)
  → init_labor_ledger (문서 없으면 생성)
  → add_labor_ledger_attendance_data (data[].attendance[day] += man_days)
  → 수수료(commission) 자동 계산 (auto_commission=True일 때)

출역 삭제(attendance_logs delete)
  → delete_labor_ledger_attendance_data (attendance[day] -= man_days)
  → attendance_id 전 일자가 모두 비면 해당 사용자 엔트리 pop

출역 수정(attendance_logs update)
  → 이전 데이터 delete → 새 데이터 add 2단계로 진행
  → 현장 변경(before_site_id != after_site_id) 시 두 현장 labor_ledger 모두 갱신

수동 수정 엔드포인트(change_labor_ledger_*) 는 전체 문서를 get → in-memory 수정 → update로 덮어쓰는 방식입니다.

문서 필드

필드 타입 설명
company_name string 노임대장 생성 시점의 회사명 (엑셀 헤더용)
site_name string 현장명
supervisor_name string 현장 대리인 이름
tag_settings object 업체/수수료 설정 — 아래 TagSettings 참조
custom_commissions array (예약 필드) 사용자별 커스텀 수수료
fields string[] 이 대장에 등장한 field(직종) 목록 (중복 제거)
tags string[] 이 대장에 등장한 labor_supplier(업체) 목록 (중복 제거)
data UserEntry[] 근로자별 엔트리 배열
field_sum object 직종별 일자별 공수 합계 — 아래 FieldSum / TagSum 참조
tag_sum object 업체별 일자별 공수 합계

TagSettings

{
  "labor_suppliers": ["A업체", "B업체"],
  "commission": [
    { "type": "amount",  "value": 10000 },
    { "type": "percent", "value": 0.05 }
  ]
}
필드 타입 설명
labor_suppliers string[] 인력 공급업체 태그 배열. 인덱스 기준으로 commission과 매칭
commission object[] 각 업체별 수수료 규칙 (길이는 labor_suppliers와 동일)
commission[].type string "amount"(고정 금액) | "percent"(비율)
commission[].value number type=amount이면 원 단위, type=percent이면 비율(0~1)

수수료 계산식 (calculate_commission): - type=amount: value × man_days_sum (원) - type=percent: value × man_days_sum × wage_rate (= 비율 × 총 인건비) - 업체가 labor_suppliers에 없거나 "없음"이면 0원

UserEntry

data[] 배열의 각 엔트리로, 한 근로자의 월 단위 출역/임금/수수료 레코드.

{
  "UID": "uid_worker_1",
  "field": "철근",
  "labor_supplier": "A업체",
  "name": "홍길동",
  "birth": "1985-03-15T00:00:00Z",
  "sex": "male",
  "main_address": "서울특별시 강남구",
  "sub_address_enc": "AES(...)",
  "phone_enc": "AES(...)",
  "phone_masked": "010-****-5678",
  "wage_rate": 180000,
  "attendance_source": "company",
  "attendance": [0, 1, 1, 0.5, 0, ...],
  "attendance_id": {
    "0": [],
    "1": ["log_id_1", "log_id_2"],
    ...
  },
  "man_days_sum": 2.5,
  "commission": 25000,
  "auto_commission": true,
  "field_sum": {},
  "tag_sum": {}
}
필드 타입 단위 설명
UID string - 근로자 UID (매칭 키)
field string - 직종 (예: "철근", "형틀", "없음")
labor_supplier string - 공급 업체명 (없으면 "없음")
name string - 근로자 이름 (당시 값 스냅샷)
birth timestamp? - 생년월일 (엑셀 주민번호 생성에 사용)
sex string? - "male" | "female"
main_address string? - 주소 (평문)
sub_address_enc string? - 상세주소 AES 암호화
phone_enc string? - 전화번호 AES 암호화
phone_masked string? - "010-****-XXXX" 마스킹 표시용
wage_rate int 원/공수 단가 (1공수 기준 금액)
attendance_source string - "company"(회사 attendance_logs) | "site"(현장 attendance_logs)
attendance number[31] 공수 일자별 공수 배열. 인덱스 i = 그 달 i+1
attendance_id map - 일자별 원본 attendance_log id 배열. 키는 "0"~"30" 문자열
man_days_sum number 공수 sum(attendance) (월 총공수)
commission int 수수료 금액. auto_commission=true이면 자동 계산
auto_commission bool - true: calculate_commission으로 자동 갱신 / false: 수동 입력값 유지
field_sum object - (과거 필드, 현재 미사용 — 문서 최상위 field_sum에 집계)
tag_sum object - (과거 필드, 현재 미사용)

매칭 규칙: find_matching_index는 현재 UID 단독으로 비교합니다(기존 field/tags까지 비교하던 로직은 주석 처리됨). 즉 한 UID는 labor_ledger 당 1개 엔트리.

FieldSum / TagSum

{
  "field_sum": {
    "철근":   [0, 2, 3, 0, ...],
    "형틀":   [1, 1, 0, 0, ...],
    "없음":   [0, 0, 0, 0, ...]
  },
  "tag_sum": {
    "A업체":  [1, 3, 2, 0, ...],
    "B업체":  [0, 0, 1, 0, ...],
    "없음":   [0, 0, 0, 0, ...]
  }
}
  • 문서 최상위 필드.
  • 키: 직종명 / 업체명. 값: 길이 31의 공수 합계 배열.
  • calculate_tag_field_sumdata[]를 순회하여 일자별 합계를 재계산 후 저장.

수동 수정 엔드포인트 매트릭스

엔드포인트 수정 대상 필드
change_labor_ledger_meta_data company_name, site_name, supervisor_name
change_labor_ledger_user_data data[].field, labor_supplier, phone_enc, sub_address_enc, main_address, phone_masked (+ 자동 수수료 재계산 + field_sum/tag_sum 재집계)
change_labor_ledger_user_wage data[].wage_rate, commission, auto_commission (new_commission == -1이면 자동계산 모드로 전환)
change_labor_ledger_tag_data tag_settings.labor_suppliers, tag_settings.commission (+ 모든 auto_commission=true 사용자의 수수료 재계산)

엑셀 출력

create_labor_ledger_excel 엔드포인트는 labor_ledger 문서를 읽어 업체(tags)별로 시트를 분리한 엑셀(.xlsx)을 생성하고 Firebase Storage에 업로드한 뒤 signed URL을 반환합니다.

  • 저장 경로: companies/{company_id}/sites/{site_id}/labor_ledger/{site_name}_{YYYYMM}.xlsx
  • signed URL 유효기간: 10분

예시 문서

{
  "company_name": "건설24 주식회사",
  "site_name": "판교 오피스 신축",
  "supervisor_name": "김대리",
  "tag_settings": {
    "labor_suppliers": ["A업체", "B업체"],
    "commission": [
      { "type": "amount", "value": 10000 },
      { "type": "percent", "value": 0.05 }
    ]
  },
  "custom_commissions": [],
  "fields": ["철근", "형틀"],
  "tags": ["A업체", "B업체"],
  "data": [
    {
      "UID": "uid_worker_1",
      "field": "철근",
      "labor_supplier": "A업체",
      "name": "홍길동",
      "wage_rate": 180000,
      "attendance_source": "company",
      "attendance": [0, 1, 1, 0.5, 0, "... (31 길이)"],
      "attendance_id": { "0": [], "1": ["log_1"], "2": ["log_2"], "3": ["log_3"] },
      "man_days_sum": 2.5,
      "commission": 25000,
      "auto_commission": true
    }
  ],
  "field_sum": {
    "철근": [0, 1, 1, 0.5, 0, "..."],
    "형틀": [0, 0, 0, 0, 0, "..."]
  },
  "tag_sum": {
    "A업체": [0, 1, 1, 0.5, 0, "..."],
    "B업체": [0, 0, 0, 0, 0, "..."]
  }
}