change_requests 스키마 (근로자 현장 변경 요청)
이미 특정 현장(
from_site_id)에 소속된 근로자가 같은 회사 내 다른 현장(to_site_id)으로 이동 요청하는 문서. 승인되면 출발 현장 members는resign=True(reason="site_change")로 마킹되고 도착 현장에 새 members 문서가 생성됩니다.
저장 위치
주의: 변경 요청 문서는 도착 현장(
to_site_id) 하위에 저장됩니다. 출발 현장(from_site_id)이 아닙니다.
request_id: Firestore 자동 생성 ID- 요청자 UID의
users/{uid}/requests문서와 1:1 쌍으로 연결 (user_notification_id)
상태 흐름
pending ──(관리자 승인)──► approved → from 현장 resign + to 현장 members 생성 + membership 갱신
│
├──(관리자 거절)──────► rejected
│
└──(요청자 취소)──────► rejected (approvalUID = 요청자 본인)
| 상태 | 설명 | 영향 |
|---|---|---|
pending |
요청 등록 직후 | 같은 사용자의 site_change pending 요청은 1개만 허용 |
approved |
관리자 승인 | 출발 members resign=True, 도착 members 생성/복구, users/{uid}/membership/{cid}_{sid} 문서의 site_id/site_name 업데이트, FCM 승인 알림 |
rejected |
관리자 거절 또는 요청자 취소 | members 변경 없음. 거절 시 FCM 거절 알림 |
문서 필드
| 필드 | 타입 | 설명 |
|---|---|---|
UID |
string | 요청자(근로자) UID |
status |
string | pending | approved | rejected |
company_id |
string | 회사 ID |
from_site_id |
string | 출발 현장 ID (현재 소속) |
to_site_id |
string | 도착 현장 ID (이동 희망) — 요청 문서가 저장되는 사이트 |
requester_name |
string | 요청자 이름 (스냅샷) |
requester_phone_masked |
string | 마스킹된 전화번호 |
requester_phone_enc |
string | 암호화된 전화번호 |
requester_email_enc |
string | 암호화된 이메일 |
main_address |
string | 주소 |
sub_address_enc |
string | 암호화된 상세 주소 |
requester_birth |
timestamp | 생년월일 |
requester_sex |
string | "male" | "female" |
requester_wage_rate |
number | 출발 현장 당시의 단가 (참고용 스냅샷) |
user_notification_id |
string | 사용자 쪽 users/{uid}/requests/{id} 문서 ID |
created_at |
timestamp | 요청 생성 시각 |
approved_at |
timestamp | null | 승인/거절/취소 시각 |
approvalUID |
string | null | 처리자 UID (요청자 취소 시 요청자 본인) |
모든 requester_* / main_address / sub_address_enc 필드는 출발 현장의 members 문서에서 복사된 스냅샷입니다.
요청 생성 시 선검사
_site_change_request는 다음을 검사 후 실패 시 거부합니다:
- 요청자가
from_site_id의 members에 존재해야 함 (PERMISSION_006) to_site_id현장이 존재하고status="activate"이어야 함 (SITE_001/SITE_003)- 동일 사용자의
site_changepending 요청이 이미 있으면 중복 거부 (REQUEST_003) - 출발 현장에서 이미 퇴사(
resign=True) 상태면 거부 (MEMBER_008) - 출발 현장에서 현재 출근 상태(
check_in)면 거부 (SITE_006) - 출발 현장 출석 요청(
site_attendance) pending이 있으면 거부 (SITE_007)
승인 시 생성/갱신되는 문서
- 출발 현장
members/{uid}업데이트 — members.md resign: True,resign_at,resign_UID=관리자UID,resign_reason="site_change"세팅- 도착 현장
members/{uid}생성 또는 복구 - 기존 문서가 있으면 스냅샷으로 업데이트(복구)
- 없으면
database.write(doc_id=UID)로 신규 생성 field/labor_supplier/wage_rate는 출발 현장의 값을 그대로 이관users/{uid}/membership/{cid}_{from_site_id}업데이트 — common/_schema/membership.mdsite_id→to_site_id,site_name→ 도착 현장명으로 갱신 (문서 ID는 유지)users/{uid}/requests/{notification_id}갱신status: "approved"— common/_schema/requests.md- FCM 알림 전송
- 제목:
[현장변경] 현장 변경 승인 notification_type: "site_change_approved"
거절/취소 시 동작
| 경우 | 처리 |
|---|---|
| 관리자 거절 | status="rejected" + approvalUID=관리자UID. 사용자 쪽 requests도 rejected. FCM 거절 알림 (notification_type: "site_change_rejected") |
| 요청자 취소 | status="rejected" + approvalUID=요청자UID. 사용자 쪽 requests도 rejected. FCM 알림 없음 |
관리자 강제 변경 (요청 없이 이동)
관리자용 _site_change는 change_requests 문서를 만들지 않고 곧바로 members/membership을 업데이트합니다 (승인 단계 스킵). 이 경우 이 컬렉션에는 아무 문서도 생성되지 않습니다.
예시 문서 (pending)
{
"UID": "uid_worker",
"status": "pending",
"company_id": "company_abc",
"from_site_id": "site_old",
"to_site_id": "site_new",
"requester_name": "홍길동",
"requester_phone_masked": "010-****-1234",
"requester_phone_enc": "base64...",
"requester_email_enc": "base64...",
"main_address": "서울시 강남구",
"sub_address_enc": "base64...",
"requester_birth": "1990-01-15T00:00:00Z",
"requester_sex": "male",
"requester_wage_rate": 180000,
"user_notification_id": "notif_abc",
"created_at": "2026-04-20T09:00:00Z",
"approved_at": null,
"approvalUID": null
}
관련 엔드포인트
_site_change_request(con24/site/HR/worker_site_change.py) — 요청 생성_site_change_request_cancel— 요청자 취소_site_change_request_approval— 관리자 승인/거절 (모든 사이트 change_requests를 순회하며 request_id 검색)_site_change— 관리자 강제 변경 (요청 없이 즉시 처리)
관련 스키마
- members.md — 출발 현장 resign, 도착 현장 신규 생성
- common/_schema/requests.md — 사용자 쪽 요청 미러 (
request_type: "site_change") - common/_schema/membership.md —
site_id/site_name이 갱신되는 사용자 멤버십 - membership_requests.md — 최초 입사 요청 (변경이 아닌 신규)