member360Cards, members 하위 컬렉션, dashboardSnapshots는 분석·검토용 read-model입니다. 현재 수강권, 재등록 후보, 외부 실행 대상 판단은 최신 memberProfiles를 우선합니다.
workLanes는 임시 작업 공간이며 외부 발송·쓰기 원천으로 사용하지 않습니다.
식별과 중복
회원 매칭은 memberId, 전화번호, 이름 순서로 확인합니다.
동명이인은 전화번호나 StudioMate ID 확인 전까지 합치지 않습니다.
예약 중복은 공통 canonical booking resolver를 사용해 판단합니다.
실제 StudioMate/API record가 있으면 usage_booking_, excel_booking_, excel_ fallback보다 우선합니다.
후보 생성, 설문, 리포트, 알림톡 발송 전에는 연결 booking이 active인지 확인합니다.
기록 형식
목적, 현재 구현 상태, 운영 규칙, 데이터 원천, 배포 상태, 검증, 차단점, 다음 액션을 함께 남깁니다.
새 운영 규칙은 Notion이 아니라 이 탭에 반영합니다.
직원 행동이나 회원 커뮤니케이션이 바뀌면 코드 배포와 운영규칙 업데이트를 같은 작업으로 봅니다.
운영 액션 수명주기
홈에는 canonicalActionKey 기준으로 중복을 제거한 미해결 액션만 표시합니다.
상태는 open, acknowledged, in_progress, blocked, resolved 순서로 관리합니다.
resolved 항목은 홈과 미해결 KPI에서 즉시 제외하고 이력 화면에서만 확인합니다.
운영자 판단이 필요한 액션에는 owner, dueAt, resolutionCode, resolvedBy, resolvedAt을 기록합니다.
자동 복구된 원본 중복, 정규화, 캐시 지연은 홈 액션으로 올리지 않고 진단 로그에만 남깁니다.
2. 데이터·동기화
StudioMate API가 아니라 Excel-first 운영을 현재 기본 모드로 사용합니다.
excel-first
StudioMate 동기화
ARCHIVE PILATES 자사 예약 시스템 운영 전까지 StudioMate API 모드는 사용하지 않습니다.
회원목록, 수업예약내역, 삭제된 수업 로그는 Mac mini Playwright Excel 다운로드로 수집합니다.
엑셀 다운로드와 Firestore 반영은 1시간 간격 LaunchAgent가 담당합니다.
운영자 수동 동기화 버튼도 API가 아니라 Excel 다운로드·반영 요청을 생성합니다.
수업예약내역 엑셀은 다운로드 기간의 최신 예약 스냅샷으로 보고 bookings를 reconcile합니다.
예약 회원 매칭은 StudioMate 예약 원천의 연락처만 1순위로 사용합니다. 엑셀에서 010 번호가 숫자형으로 바뀐 경우도 010 형식으로 복원한 뒤 매칭합니다. 같은 연락처 회원카드가 여러 개면 이름 일치, 활성 수강권, 실제 StudioMate ID 보유 여부로 대표 회원을 고릅니다. 연락처가 있지만 회원카드가 없으면 회차·예약 집계용 예약 전용 프로필을 만들고 외부 발송/쓰기 원천으로는 쓰지 않습니다.
회원목록·수업예약내역 엑셀이 Firestore memberProfiles/bookings에 성공 반영되면 Mac mini 로컬 원본 파일은 즉시 삭제합니다. Google Drive에서 직접 선택한 원본은 자동 삭제하지 않습니다.
같은 회원·시간·강사·수업으로 판단되는 예약은 canonicalBookingKey를 기준으로 1개만 active로 남기고, 과거 excel_booking_ 중복 문서는 superseded_by_latest_reservation_import로 회차와 알림톡 대상에서 제외합니다.
최신 예약 엑셀 범위에서 사라진 기존 예약은 missing_from_latest_reservation_import로 취소 처리하고 회차 집계에서 제외합니다.
다운로드 기간 밖의 과거 예약은 기존 상태를 확정 상태로 두되, 과거 미체크 예약은 프라이빗 확정 회차에 세지 않고 출석확인필요로 봅니다.
회원·수강권
memberProfiles는 화면과 후속 실행을 위한 정규화 뷰입니다.
현재 활성 수강권 판단은 memberProfiles.activeTickets를 우선합니다. member360Cards나 members 하위 summary가 더 오래된 경우 CORE 화면은 memberProfiles 값으로 덮어 표시합니다.
회원목록 Excel import는 활성 수강권 안에 결제금액, 결제일시, 결제방법을 함께 보존합니다. 새 엑셀 행의 결제 칼럼이 비어 있더라도 같은 수강권의 기존 결제 메타데이터를 지우지 않습니다.
CORE 데이터 검증은 audit:archive-core-data로 실행하며, 수강권 미러 지연·구매금액 미러 누락·회원 360 미러 누락을 운영자 액션 1건으로 요약합니다.
엑셀에만 있는 회원은 등록 3일 이내이고 활성 수강권이 있을 때만 임시 회원카드를 만듭니다.
수강권 없는 상담고객은 회원카드를 만들지 않고 연락처 후보로만 다룹니다.
같은 연락처의 회원카드는 대표 회원카드 1개만 유지합니다. 중복이 생기면 전화번호 병합 가드가 실제 StudioMate ID, 활성 수강권, 정식 프로필을 우선 대표로 고르고 나머지는 mergedInto로 표시한 뒤 예약, 회차, 알림톡, 메모, 주차 참조를 대표 카드로 이동합니다.
excel_ 임시 회원은 studiomateMemberIdLookupJobs로 실제 StudioMate ID를 찾은 뒤 후속 쓰기를 진행합니다.
수업·폐강
오늘부터 예약오픈 종료일, 즉 다음 주 일요일까지의 예약 데이터를 기본 범위로 봅니다.
수업예약내역 엑셀에는 신뢰 가능한 최대정원 원천이 없으므로 정원 기반 판단은 쓰지 않습니다.
삭제된 수업은 별도 야간 자동화가 아니라 1시간 Excel 동기화 안에서 함께 수집합니다.
폐강 집계는 그룹 수업 중 최소 수강인원 미달 또는 제한된 클래스 폐강 조건만 포함합니다.
월간 StudioMate 운영 세트
다음달 그룹수업 생성, 주제·기구 입력, 고정회원 예약은 하나의 월간 작업 세트로 실행합니다.
쓰기 전 프리플라이트에서 원본 시트 구조, StudioMate 로그인, 회원 검색, 일괄예약 화면 진입, 정확매칭 수업카드를 먼저 확인합니다.
일괄예약 화면을 못 열었을 때는 수강권 문제로 단정하지 않고 surface_failed로 분리해 재시도합니다.
예약 완료 판정은 StudioMate 성공 메시지가 아니라 수업상세 예약회원 목록에서 회원명·전화번호가 확인될 때만 확정합니다.
결과 시트에는 운영자가 확인해야 하는 실패·보류 건만 남기고, 성공 건은 요약 숫자로 관리합니다.
프리플라이트와 dry-run은 백그라운드 단일 큐에서 실행하고, 수업 생성·주제 입력·고정예약 apply는 운영자 승인 후 같은 큐에서 직렬 실행합니다.
자동화 관제
안정적인 정기 실행은 Mac mini LaunchAgent를 기본 주체로 둡니다.
Codex 앱 자동화는 테스트, 리뷰, 수동 fallback 용도이며 LaunchAgent와 같은 작업을 동시에 ACTIVE로 두지 않습니다.
ARCHIVE CORE 자동화 관제 탭은 Firestore automationStatus를 표시하므로, 새 자동화는 실행 주체와 상태를 automationStatus에 기록해야 합니다.
LaunchAgent와 Codex 자동화 정의는 sync:automation-observability로 점검해 CORE 관제에 반영합니다.
LaunchAgent는 로그 최신성뿐 아니라 실제 last exit code를 확인하며, 실행 실패를 최신 로그 생성으로 정상 처리하지 않습니다.
운영 LaunchAgent는 임시 worktree가 아니라 최신 main을 반영한 /Users/archivepilates/dev/archive-in-runtime만 실행합니다.
대기 작업이 없는 큐 폴러는 실행마다 보고서를 만들지 않고 15~30분 간격의 단일 idle heartbeat만 남깁니다.
종료된 승인 확인 heartbeat, 비활성 plist, 합성 E2E 데이터와 반영 완료 원본 파일은 검증 후 정리하고 실제 회원·예약·발송 원천은 보존합니다.
일반 자동복구 옵션은 Firestore 삭제 권한을 포함하지 않습니다. 만료 운영 데이터 정리는 주간 점검의 명시적 purge 플래그와 엄격한 보존 조건을 모두 통과할 때만 실행합니다.
시간별 StudioMate Excel 동기화는 이전 반영 해시와 비교해 변경된 회원·수강권·예약·수업 문서만 씁니다. 같은 원본을 다시 내려받아도 변경 문서가 없으면 Firestore 본문을 다시 쓰지 않습니다.
프라이빗 회차는 변경된 프라이빗 예약의 회원만 동기화 직후 보정합니다. 전체 월간 보정은 매일 23:30 안전 점검으로만 실행하며 시간별 동기화에서 다시 호출하지 않습니다.
설문 미제출 점검은 최근 프라이빗 설문 후보만 조회하고, 이미 확인 메일을 만든 요청은 회원 응답·예약을 다시 조회하지 않습니다.
superseded, 취소, 대기, 결석 및 sessionOrder.counted=false 예약은 프라이빗 회차 누락 대상으로 보지 않습니다.
dirty worktree는 개발 정리 대상으로 별도 기록하며 회원·운영 시스템 장애 점수에는 포함하지 않습니다.
worktree 정리는 macOS Documents 권한 때문에 LaunchAgent에서 실행하지 않고, Codex 사용자 세션에서 감사 후 수행합니다.
Google Contacts
기준 계정은 home@archivepilates.com입니다.
Google Contacts는 원천이 아니라 전화 발신·검색을 위한 보조 저장소입니다.
연락처는 memberContactIndex와 contactSyncJobs 기준으로 큐를 만들고, dry-run 후 반영합니다.
현재 근무 중인 강사·스텝 연락처는 이름 아카이브로 저장합니다.
현재 근무 스텝이 아니면서 StudioMate 등급이 강사회원인 연락처는 이름 강사회원 가입일로 저장합니다.
연락처 작업 실행 직전에 최신 회원등급을 다시 확인해 오래된 신규회원 작업이 강사회원 이름을 덮지 못하게 합니다.
같은 전화번호가 회원과 현재 근무 강사에 함께 등록되면 회원카드는 유지하고 Google 연락처 이름만 강사명을 우선합니다.
강사 우선 여부는 active staffs의 전화번호로 판단하며, 전화번호가 없는 경우에만 이름을 보조 기준으로 사용합니다.
강사 보호로 건너뛴 회원 연락처 작업은 synced가 아니라 skipped로 기록하고, 새 강사는 회원 연락처 동기화 전에 active staffs에 먼저 등록합니다.
Google-only 연락처 삭제, 연락처 병합, 대량 이동은 별도 승인 없이는 하지 않습니다.
원천 신선도와 화면 상태
CORE 수업 화면의 현재 원천은 bookings입니다. lessonOccurrences와 reservations는 전환기 보조 자료로만 사용합니다.
회원 최근 방문은 memberProfiles.emergencyLastAttendance, lastAttendanceAt, recentVisitAt과 member360Cards.recentVisitAt 중 가장 최신 값을 표시합니다.
모든 주요 화면은 정상, 빈 데이터, 원천 지연, 권한 오류를 서로 다른 상태로 표시합니다. 읽기 실패를 0건으로 표시하지 않습니다.
원천 갱신 시각과 현재 시각의 차이를 표시하고, 오래된 데이터는 운영 판단 전에 재동기화하도록 경고합니다.
강사 지표는 최근 2개월 자료만 현재 평가에 반영하고, 100%를 넘는 예약률처럼 해석이 불가능한 값은 원본 확인 상태로 둡니다.
배포 전 validate:archive-core-hosting과 live rollback guard로 bookings 원천, 상태 표시, 외부 도구 바로가기, 운영 액션 필터가 보존되는지 확인합니다.
현재 확인 위치CORE Imports, Automation, Members / Firestore memberProfiles, bookings, memberContactIndex, contactSyncJobs
3. 재등록 관리
회원이 끊기기 전에 운영자가 확인할 재등록 후보를 관리합니다.
operator action
관리 목적
재등록 관리는 기존 잔여횟수·기간만료 알림톡 자동발송과 운영자 상담을 함께 관리하는 세션입니다.
알림톡은 승인된 기존 템플릿과 30일 중복 차단을 유지하고, 개인화 계산값은 대상 검토와 상담 추천에만 사용합니다.
홈 미해결 액션에는 오늘 바로 확인해야 하는 긴급 후보만 더합니다.
30일 내 관리 후보는 홈 재등록 관리 섹션에 별도로 표시하고, 실패나 오류로 누적하지 않습니다.
후보 산정
기본 원천은 memberProfiles.activeTickets입니다. member360Cards.currentTicketsSummary는 매출·상세 검토용 미러로만 사용하며, 최신 memberProfiles와 다르면 CORE 화면은 memberProfiles 값을 우선 표시합니다.
수강권 만료 30일 이내, 잔여 횟수 부족, 최근 방문 후 활성 수강권 공백 회원을 후보로 봅니다.
최근 8주 출석·결석·당일취소의 실제 소진 속도를 계산해 예상 소진일이 30일 이내인 회원도 관리 후보로 봅니다.
그룹은 잔여 5회 이하, 프라이빗과 듀엣은 잔여 3회 이하를 기본 임계값으로 사용합니다.
7일 이내 만료·예상 소진 또는 매우 낮은 잔여 횟수는 오늘 확인 후보로 올립니다.
제외와 중복 방지
상담, 체험, 강사레슨, 직원용, 락커, 양말, 상품권처럼 재등록 상담 대상이 아닌 수강권은 제외합니다.
같은 유형의 정상 후속 수강권을 이미 보유한 회원은 만료·부족 알림톡 대상에서 제외합니다. 수강권 ID가 없거나 상품명이 같아도 별도 보유 행이면 재등록 후속권으로 판정하며, 보상 쿠폰·상품권은 재등록 대상이나 후속권으로 사용하지 않습니다.
전화번호가 없는 후보는 외부 발송 원천으로 쓰지 않고, 운영자 화면에서만 보조 확인 대상으로 봅니다.
재등록 알림톡 후보를 만들 때는 별도로 수강권 canonical key와 중복발송 방지 규칙을 다시 확인합니다.
같은 회원·수강유형의 renewalCases 장부는 하나만 유지하며, 새 수강권이 확인되면 기존 건은 자동 완료 처리합니다.
운영 단계
오늘 확인: 만료 또는 잔여가 임박해 당일 현장 상담·전화가 필요한 상태입니다.
이번 주 상담: 곧 만료되거나 잔여가 낮아 수업 전후 안내하면 좋은 상태입니다.
만료 전 관리: 30일 안에 미리 안내하면 이탈을 줄일 수 있는 상태입니다.
재등록 대기: 최근 방문 이력이 있지만 현재 활성 수강권이 없어 복귀 상담 대상입니다.
운영자는 연락완료, 고민중, 7일 후 재확인, 재등록완료, 재등록 의사 없음 상태를 기록합니다.
재등록완료는 실제 재등록이 확인된 건, 재등록 의사 없음은 회원이 재등록하지 않겠다고 확인한 건에만 사용하며 두 상태 모두 현재 목록에서 숨기고 이력은 유지합니다.
현재 확인 위치CORE Home > 재등록 관리 / 원천 memberProfiles + canonical bookings / 운영상태 renewalCases
4. 카카오 알림톡
대상자 선정, 승인, 발송, 로그를 분리해 오발송을 막습니다.
external send
발송 흐름
Excel 동기화가 회원, 수강권, 예약 상태를 갱신합니다.
Firebase가 canonical source 기준으로 후보를 만듭니다.
SOLAPI 템플릿 승인 상태와 변수 매칭을 확인합니다.
자동 기준 또는 운영자 승인 후 queued로 전환합니다.
SOLAPI 발송 결과를 alimtalkSends와 로그 문서, 메일로 남깁니다.
자동 발송 기준
일일 정기 발송 기준 시각은 11:30입니다.
월요일 예약오픈 안내는 12:30에 스튜디오메이트 예약 안내 v4로 발송하며, 동일 예약주차 기준 6일 동안 중복 발송하지 않습니다.
예약오픈 대량 발송 승인은 같은 날의 일일 알림톡 승인과 별도 승인 건으로 관리합니다.
대량 발송 가능 후보가 10건 이상이면 자동 발송하지 않고 승인 게이트로 보냅니다.
발송 전 중복, 제외 회원, 템플릿 승인, 전화번호를 다시 확인합니다.
운영자 화면의 일반 회원 태그에는 알림톡 상태 태그를 표시하지 않습니다.
제외 규칙
다른 유효 수업 수강권을 보유한 회원은 수강권 만료·부족 알림에서 제외합니다.
양말, 토삭스, 기간연장 등 수업권이 아닌 상품은 제외합니다.
전화번호 없음, 상담고객, 템플릿 미승인, 구 템플릿 코드는 발송하지 않습니다.
취소되거나 stale인 예약은 프라이빗/그룹 설문 알림 발송 직전에 다시 제외합니다.
중복 방지
수강권 알림은 회원, 템플릿, 수강권 식별자 기준으로 막습니다.
프라이빗 최초 사전설문은 회원별 영구 1회입니다. 그룹 첫 수업 설문은 같은 유형 제출 후 1년이 지나야 재후보가 됩니다.
수업자료와 회원 리포트는 같은 회원·수업·recordId 단위로 영구 1회만 발송합니다.
회원 리포트는 승인한 revision과 후보 ID를 고정해 수정본과 발송본이 섞이지 않게 합니다.
템플릿과 링크
템플릿별 대상/제외 규칙은 templateTargetRules.ts에서 관리합니다.
SOLAPI 버튼 URL은 변수 치환 후 100자 이하여야 합니다.
강사레슨 수업자료 안내는 수업자료 보기, 수업배정 안내, 방문안내 보기 버튼을 함께 검수합니다.
강사레슨 수업배정 안내는 StudioMate 예약 스케줄의 수업일, 시간, 강사, 기구, 예약자 기준으로 만들고 수기 이미지나 임의 명단을 원천으로 쓰지 않습니다.
긴 URL은 shortLinks를 만들고 버튼에는 pr-, ir- 같은 짧은 링크 ID를 넣습니다.
privateLessonChartRequests와 privateLessonChartRecords는 기존 설문 링크와 기록을 유지하는 호환 문서입니다.
2026.06.01 이후 프라이빗/세미프라이빗 수업은 자동 기록 페이지를 생성합니다.
회차·예약 보정
어제 이전 예약확정/출석미체크 수업은 확정 회차로 세지 않습니다. 오늘 이후 예약은 예정 회차로만 이어 세고, 출석 완료가 반영되면 확정 회차가 됩니다.
booking.sessionOrder.privateCumulativeRound는 privateSessionLedger에서 내려쓴 캐시입니다. 값이 없거나 원천과 다르면 즉시 재계산해 저장합니다.
삭제, 취소, 시간변경은 sessionOrder.counted=false와 제외 사유를 남기고 해당 수업 이후 회차까지 연쇄 재계산합니다.
usage_booking_ 같은 이용내역 fallback 예약은 실예약 장부와 회차 계산에서 제외합니다.
booking.lessonType=group인 수업은 수강권명이 프라이빗처럼 보여도 프라이빗 회차에서 제외합니다. 원본 분류가 틀렸다면 원본 보정 후 다시 반영합니다.
강사 설문 알림톡 발송, 설문 링크 열기, 설문 제출, Notion 차트 갱신은 연결된 booking이 active일 때만 진행합니다.
수업 시간이 변경되면 supersededByBookingId를 우선 따라 같은 수업 세션으로 이관하고, 연결이 불명확하면 자동 발송하지 않고 확인필요로 둡니다.
같은 회원, 강사, 날짜, 수강권에서 시간변경 중복이 생기면 출석/최신 예약을 대표 booking으로 두고 나머지는 rescheduled_duplicate로 제외합니다.
Notion 차트 동기화
운영규칙은 CORE가 기준이지만, 개인레슨 회차 차트는 강사별 회원 페이지 하위의 Notion 일반 페이지로 유지합니다.
Notion은 표시·열람용입니다. Private Session Records DB, 웹훅 승인, 예약 스케줄러는 사용하지 않습니다.
개인레슨 차트 상단은 현재 진행 흐름과 강사별 차트만 우선 표시합니다. 자동화 테스트 차트와 기타 자료는 접힌 보관 영역에 분리하고, 이전 DB 기반 운영 문서는 보관 처리합니다.
차트 상태와 발송 승인은 Firestore privateLessonChartRecords, 운영 진행상태는 privateLessonSessions가 원천입니다.
리포트가 없어도 실제 수업 회차는 Notion 일반 페이지로 남겨 누락을 확인할 수 있어야 합니다.
차트 제목에는 수업 준비, 수업 기록, 리포트 검수, 전달 완료 단계를 표시합니다.
리포트 생성완료는 수업 후 설문 제출, GPT 리포트 생성 상태, 회원용 리포트 URL 준비가 모두 확인된 경우에만 표시합니다.
회원용 리포트는 오늘의 핵심, 좋아진 점, 오늘 확인한 움직임, 다음 수업 방향, 홈워크, 다음 수업 전 체크 순서의 코칭 카드형 화면으로 제공합니다. 홈워크는 강사가 입력한 경우에만 노출합니다.
다음 수업 준비 메모는 내부 코칭 참고용으로 보관하고, 회원용 다음 수업 방향 문장에 그대로 노출하지 않습니다.
예약 시간이 바뀌거나 취소되면 Notion 제목, 날짜, 상태, 회차, 발송상태를 함께 갱신하고 취소 차트는 회원 발송 후보에서 제외합니다.
자동화가 관리하는 차트 본문은 갱신할 때 교체하며 같은 내용이 반복해서 쌓이지 않게 합니다.
강사 설문
회원 최초 프라이빗 사전설문은 예약별 토큰을 가진 ARCHIVE PILATES 자체 설문을 사용하며 회원별 영구 1회만 받습니다.
취소·변경되었거나 active 상태가 아닌 예약 링크는 열기와 제출을 모두 막습니다.
설문 알림톡은 후보 생성 때와 실제 발송 직전에 연결 예약을 다시 확인합니다. 자체설문 링크형 v2는 기존 ARCHIVE PILATES 로고 이미지형 양식을 유지하며, 승인 상태·버튼 URL·이미지 ID가 모두 일치하기 전에는 발송하지 않습니다.
회원 설문 제출 후 담당강사 확인 알림도 긴 설문ID·접근토큰 URL을 직접 넣지 않고 shortLinks의 sv- 링크만 사용합니다. v2가 승인되기 전에는 기존 v1로 되돌아가 발송하지 않습니다.
강사용 안내는 수업 전 계획, 수업 후 기록, 사진·영상 업로드 세 버튼을 ARCHIVE PILATES 자체 화면으로 연결합니다. v3도 기존 ARCHIVE PILATES 로고 이미지형 양식을 유지하며, 승인 상태·버튼 URL·이미지 ID가 모두 일치하기 전에는 발송하지 않습니다.
강사용 수업 전 화면은 회원 사전설문 요약과 지난 리포트 요약을 보여줍니다.
수업 후 설문은 점수, 평균, 등급, 1-5 평가 표현을 사용하지 않습니다.
수업 전/후 객관식 항목은 운영자가 미리 정한 보기와 함께 기타 서술형을 허용합니다.
오늘의 핵심과 다음 수업 방향은 강사가 입력한 키워드를 자연스럽게 포함해 회원용 문장으로 생성합니다.
다음 수업 방향은 수업 후 기록의 목표, 진행 부위, 관찰 변화, 주의사항, 강사 키워드를 바탕으로 회원용 문장으로 생성합니다.
목적 템플릿
회원은 최초 사전설문에서 체형교정/정렬, 다이어트/체력, 통증/회복, 산전·산후/컨디션 중 하나를 선택합니다.
회원 선택값을 우선 적용하고, 과거 서술형 응답은 키워드 기반 자동 분류로 보정합니다.
수업 전·후 질문과 리포트 문장 규칙은 목적 템플릿별로 달라집니다.
5회 단위 회차는 리뷰 회차로 보고 누적 변화와 다음 블록 방향을 더 의식해 작성합니다.
미디어
강사는 수업 후 기록 페이지에서 사진/영상을 첨부합니다.
강사용 알림톡의 사진·영상 업로드 버튼은 Notion이 아니라 ARCHIVE PILATES 프라이빗 기록 화면의 미디어 영역으로 연결합니다.
지원자 원본은 staffApplicantEvaluationSessions와 staffApplicantEvaluationSubmissions에 별도로 보관합니다.
현재 근무중 여부는 staffs.active와 staffRole 기준으로 판단합니다. active인 instructor/owner는 현재 근무중, manager/viewer는 운영자 계정, staffHrCards나 제출 기록만 있는 대상은 비근무/지원자 기록으로 보관합니다.
인사기록카드는 외부 발송, 정산, 예약, 회원 응대 자동화의 원천으로 사용하지 않습니다.
문항 관리
현재 문항은 공개 Google Form ARCHIVE 강사평가 퀴즈 A에서 확인한 22문항과 선택지 기준입니다.
객관식 18문항은 각 4점, 단답형 3문항은 각 6점, Q19 서술형은 10점으로 채점합니다.
Q19 서술형은 imprint 정의, 골반 후방경사, 요추/매트 정렬, 코어 안정, 사용 상황, 주의점을 기준으로 1차 자동 루브릭 채점합니다.
운영자가 Q19 점수를 수정하면 staffEvaluationSubmissions, staffApplicantEvaluationSubmissions, staffHrCards/{staffId}/quizResults, staffHrCards 최신 요약을 함께 갱신합니다.
기존 Google Form 응답은 새 Google Sheet ARCHIVE 강사평가 퀴즈 A Firebase 기록으로 이관해 보관합니다.
Firebase 제출은 새 Google Sheet의 원본 응답 탭과 참가자별 최종 결과 탭에도 보조 기록합니다. 실패해도 시험 제출은 유지하고 제출 문서에 googleSheetSync=failed로 남깁니다.
월별 그룹 예약률, 출석률, 평균인원, 수업매출은 dashboardSnapshots/current의 강사통계·강사별 데이터를 읽기 전용으로 표시합니다.
월 수업 개수, 회원만족도, 클레임 현황은 원천 컬렉션이 확정되기 전까지 연결 대기로 표시하고 인사 판단의 자동 원천으로 쓰지 않습니다.
종합 점수 v1은 평가 퀴즈 35%, 그룹 예약률 30%, 그룹 평균인원 25%, 그룹 출석률 10% 기준입니다. 아직 연결되지 않은 항목은 제외하고 연결된 항목의 가중치만 100점 기준으로 환산합니다.
그룹 평균인원은 4.5명을 100점 기준 목표치로 환산합니다. 월 수업수, 회원만족도, 클레임 현황은 원천이 확정되면 v2 산식에 반영합니다.
과거 Google Form 응답은 공식 점수를 보존해 staffHrCards로 이관하고, 새 Firebase 제출은 최신 정답키로 채점합니다.
기존 응답 시트에는 Q9 선택지 버전 차이와 Q20 정답키 입력 오류 흔적이 있어 과거 응답을 최신 키로 재채점하지 않습니다.
문항 변경 시 기존 제출 결과는 삭제하지 않고 quizVersion으로 구분합니다.
자동 채점 합격 기준은 80점 환산이며, 미달 시 CORE Staff 탭에서 검토 필요로 표시합니다.
차트와 이관
CORE Staff 탭은 staffEvaluationSubmissions와 staffHrCards의 최신 요약을 함께 읽어 강사별 점수 차트를 표시합니다.
공유된 응답 시트의 과거 결과는 import-staff-evaluation-google-results 스크립트로 dry-run 확인 후 이관합니다.
이관된 결과는 source=google_form_legacy_import로 표시해 새 Firebase 제출과 구분합니다.
지원자 제출 결과는 staffRole=applicant로 표시하고, 연락처는 채용 검토용으로만 사용합니다.
인사기록카드 차트는 최신 점수, 최고 점수, 제출 횟수, 검토 상태만 운영자가 빠르게 볼 수 있게 표시합니다.
현재 확인 위치CORE Staff / 공개 시험 https://in.archivepilates.com/instructor-evaluation/ / Firestore staffs, staffEvaluationSubmissions, staffApplicantEvaluationSubmissions, staffHrCards, auditLogs
6. 주차등록
ARCHIVE CORE 홈에서 회원, 강사, 방문 차량을 등록하고 주차권을 적용합니다.
active
운영 규칙
회원과 강사 차량은 이름 또는 연락처와 차량번호로 등록합니다. 방문 차량은 일회성 등록이므로 차량번호와 선택 메모만 입력하고 이름·연락처는 저장하지 않습니다.
차량 원천은 parkingVehicles 컬렉션입니다. 회원카드와 강사카드에는 기본 차량만 표시용으로 미러링하고, 방문 차량은 오늘 날짜 일회성 차량으로 보관합니다.
등록 차량의 삭제 버튼은 차량을 보관 상태로 전환하고 회원/강사 카드의 차량 미러를 함께 정리합니다. 이미 처리된 주차권 작업 이력은 감사용으로 유지합니다.
오늘 예약된 수업 시작 10분 뒤, 등록 차량이 있는 회원/강사를 대상으로 parkingDiscountJobs를 자동 생성합니다.
자동 후보 확인은 10분마다 Firestore에서 수업 시작 10분이 지난 최근 75분 구간만 읽습니다. 오늘 예약 전체를 반복 조회하지 않으며, 해당 구간에 수업이 없으면 차량 목록도 읽지 않습니다.
같은 작업은 고정 job id로 중복 차단하며 새 작업이 생길 때만 아이파킹을 호출합니다. 운영자의 오늘 자동적용 실행만 누락 복구를 위해 오늘 전체를 확인합니다.
방문 차량은 수업 예약과 매칭하지 않고, 오늘 자동적용 실행 버튼을 눌렀을 때 당일 방문 차량으로 parkingDiscountJobs를 생성합니다.
같은 날 같은 사람·차량은 하나의 안정적인 job id로 묶어 중복 주차권 생성을 막습니다.
아이파킹 적용
메인 계정은 704호와 705호이며, 2시간 할인권을 계정별 1개씩 우선 적용합니다.
서브 계정은 504호부터 508호이며, 메인 계정 적용이 불가능하거나 이미 사용된 경우에만 순서대로 사용합니다.
각 계정의 고유 상점 번호로 할인권 조회·적용·중복 확인을 수행합니다. 다른 계정의 상점 번호를 재사용하지 않습니다.
자동 적용 최대 시간은 4시간입니다. 기본 할인권명은 2시간 할인입니다.
강사 차량은 수업 종류와 수업 시간에 관계없이 2시간 할인권 2개, 총 4시간을 적용합니다.
차량 입차 기록이 없거나 후보가 여러 건이면 수동확인 상태로 남기고 자동 적용하지 않습니다.
적용 결과는 parkingDiscountJobs와 연결 bookings 문서의 parkingStatus에 기록합니다.
검증 위치
홈 주차등록 섹션에서 회원/강사/방문 등록 차량과 최근 주차권 작업을 확인합니다.
자동화는 scheduledCreateParkingDiscountJobs가 작업을 만들고 processParkingDiscountJob이 실제 아이파킹 적용을 수행합니다.
문제 발생 시 수동확인 또는 error job만 운영자가 확인합니다.
현재 확인 위치CORE Home / Firestore parkingVehicles, parkingDiscountJobs, bookings parkingStatus
7. 현장 웰컴·회원가입·연락처
회원가입서 제출과 StudioMate 반영을 분리해 실패 지점을 명확히 봅니다.
onsite
현장 웰컴 알림톡
StudioMate 단건 조회 후 수강권과 전화번호가 확인된 lookup_ready 상태에서만 발송 버튼을 활성화합니다.
같은 전화번호에 현장 웰컴 또는 신규회원 웰컴 성공 발송 이력이 있으면 중복 차단합니다.
삭제된 신규회원 웰컴 v3 템플릿은 사용하지 않습니다. 신규회원 안내는 현장 웰컴 v5 플로우로만 처리합니다.
CORE 홈탭은 alimtalkCandidates 실패, onsiteWelcomeRequests 오류, memberSignupContracts 후속 처리 오류를 함께 문제로 표시합니다.
지정 테스트 계정 예외는 테스트 목적과 기간을 남긴 뒤 운영에서 제거합니다.
가입서 제출
회원 제출은 먼저 memberSignupContracts에 저장합니다.
서명 완료 PDF는 home@archivepilates.com Google Drive 가입서 PDF 폴더에 저장합니다.
PDF 저장 실패는 회원 제출을 실패시키지 않고 재처리 상태로 남깁니다.
현장 웰컴 사이트에는 가입서 PDF 폴더 버튼을 제공합니다.
StudioMate 반영
주소, 생년월일, 성별은 StudioMate 회원정보란에 반영해야 합니다.
회원가입 정보는 StudioMate 메모란에 자동으로 쓰지 않습니다.
반영은 studiomateMemberProfileWriteJobs 큐를 통해 Mac mini Playwright가 처리합니다.
기존 memo write queue에 회원가입서 메모 작업이 남아 있으면 skipped로 처리합니다.
8. 정산·비즈니스 지표
대시보드는 정산 자동화 결과를 참조하고 중복 계산을 줄입니다.
finance
원본 폴더
Google Drive 아카이브 정산 폴더의 수업매출원본데이터와 수강권매출원본데이터를 사용합니다.
정산 자동화는 파일 수정일이 아니라 파일명 날짜 범위로 대상 파일을 고릅니다.
닫힌 월은 전체월 파일을 우선 사용하고, 없을 때만 최신 누적 파일을 사용하며 경고를 남깁니다.
자동화 결과
Google Apps Script 정산 자동화가 월별 정산 파일과 강사별 HTML 명세서를 만듭니다.
노쇼는 수업료 50%, 지급 50% 규칙을 적용합니다.
대시보드 DB 동기화는 정산 자동화의 대시보드_EXPORT 탭을 우선 읽어 Firestore에 쓰는 ETL로 축소합니다.
대시보드_EXPORT가 없거나 지원 형식이 아니면 기존 Master 시트 계산으로 임시 fallback하고 경고 로그를 남깁니다.
수업매출과 수강권매출은 서로 다른 지표이므로 화면 라벨을 명확히 구분합니다.
회원수는 단일 유효회원으로 표시하지 않습니다. 수강권 보유회원은 정산 시트 기준, 예약 이용회원과 출석 회원은 Firestore bookings 예약 원천 기준으로 분리합니다.
월별 보관
매월 1일 전월 정산월 폴더를 생성합니다.
강사별 정산명세서에는 총 합계, 전월대비, 그룹 합계, 프라이빗 합계, 총 수업 수, 월 그룹 평균을 표시합니다.
정규직과 프리랜서 보수를 함께 받는 강사는 전체 수업 보수에서 정규직 세전 급여를 먼저 공제한 금액만 프리랜서 보수로 계산하고, 정규직 실지급액은 한 번만 합산합니다.
이전 달 정산 데이터는 헤더 이름으로 연결하며, 정규직 실지급액이 있는데 세전 공제액을 확인할 수 없으면 이중계상 방지를 위해 명세서 생성을 중단합니다.
보수기준표에 없는 강사는 기본 요율을 추정하지 않습니다. 누락 강사명과 필요한 그룹/프라이빗 탭을 메일로 보고하고 정산 생성을 중단합니다.
일 단위 누적 파일은 최종 월 파일이 만들어진 뒤 휴지통으로 보냅니다.
수강권 잔여금액
Mac mini LaunchAgent는 매일 22:00에 기동하고 KST 월말인 날에만 집계를 게시합니다.
최신 적용 완료 StudioMate 회원목록과 memberProfiles.activeTickets를 사용하며, 3시간보다 오래된 원천이면 게시를 중단합니다.
횟수권은 잔여횟수, 기간권은 잔여일수와 주당횟수를 이용해 환산 잔여횟수를 계산합니다.
결제금액은 회원·수강권·이용기간이 같은 결제이력을 합산하고, 미수금·분할결제·임시 프로필·가격 이상치는 동일 권종 기준가로 보정합니다.
평균 회당가격은 그룹·1:1 프라이빗·듀엣을 분리하고, 0원 수강권과 강사레슨은 평균에서 제외합니다.
수강권별 상세표는 가격 커버리지 대신 해당 수강권 잔여금액이 전체 잔여금액에서 차지하는 비율을 표시합니다.
HTML 보고서는 home 계정 Google Drive의 아카이브 정산/잔여수강권에 YYMM 잔여수강권.html 이름으로 저장합니다.
결과는 ticketLiabilityReports/current와 월별 문서에 보관하고 CORE Business 고정 링크에서 확인합니다.
잔여금액은 경영 검토용 계산값이며 알림톡, 예약, 결제, 환불 등 외부 실행 원천으로 사용하지 않습니다.
현재 확인 위치CORE Business / Google Drive 아카이브 정산 자동화 / Firestore businessSnapshots / ticketLiabilityReports
9. 클라우드 비용
운영 기능을 유지하면서 사용하지 않는 상시 자원과 반복 읽기를 먼저 줄입니다.
optimized
현재 운영 기준
ARCHIVE PILATES 운영 데이터는 Firestore와 Google Drive 원천을 사용하며 Firebase Data Connect와 Cloud SQL은 사용하지 않습니다.
사용 목적, 데이터 소유자, 종료 기준이 없는 유료 상시 자원은 만들지 않습니다.
새 Cloud SQL, Data Connect, 최소 인스턴스, CPU 상시 할당은 비용 추정과 종료 계획을 먼저 남긴 뒤 승인합니다.
채용 사이트 Cloud Run은 최소 인스턴스 0, 요청 처리 중 CPU 할당 방식으로 운영합니다.
반복 작업 기준
Firestore 예약·연락처·설문 작업은 전체 문서 폴링보다 상태와 dueAt/nextRunAt 조건 쿼리를 우선합니다.
프라이빗 리포트는 수업 후 기록이 들어오기 전에는 waiting_post로 보관하고 정기 생성 대상에서 제외합니다.
운영 영향이 작은 누락 설문 확인은 시간 단위, Notion 백필은 하루 3회로 제한합니다.
월별 비용은 프로젝트, 서비스, SKU, 리전 순으로 확인하고 전월 같은 날짜 대비 급증 항목부터 원인을 찾습니다.
비용 절감 변경도 기능 배포와 동일하게 빌드, 라이브 URL, Scheduler 상태, Firestore 상태를 함께 검증합니다.
운영 기능을 줄여야 하는 경우에는 자동으로 중단하지 않고 운영자 확인 대상으로 올립니다.
현재 확인 위치Google Cloud Billing / BigQuery archive_billing_export / Cloud Run Careers / Firebase Functions Scheduler
10. 배포·검증·보고
배포 요청은 검증, commit, deploy, live check, GitHub push를 한 세트로 처리합니다.
release gate
배포세트
배포, 반영, publish, release 요청은 scoped commit, 필요한 target 배포, 라이브 확인, push까지 포함합니다.
UI/static-only 변경은 Hosting만, Functions 변경은 해당 codebase만 우선 배포합니다. CORE는 scripts/deploy-archive-core-live.sh 또는 npm run deploy:archive-core-live를 사용합니다.
배포 전 변경 범위, 테스트, 롤백 기준을 확인합니다.
CORE Hosting은 최신 CORE 작업 기준에서만 배포합니다. 배포 전 validate:archive-core-hosting이 수강료 문의 카드, 최근 발송/메모 패널, KPI 카드 높이 CSS를 확인하고, 빠진 항목이 있으면 배포를 중단합니다.
라이브 배포 커밋은 origin/main으로 fast-forward 승격합니다. 배포 완료 보고 전 npm run release:promote-main:dry로 승격 가능성을 확인하고, 검증이 끝나면 npm run release:promote-main을 실행합니다.
기능 브랜치만 라이브에 배포되고 main으로 승격되지 않은 상태는 rollback/다른 스레드 덮어쓰기 위험으로 봅니다. 승격이 막히면 차단 원인을 보고하고 별도 정리합니다.
ARCHIVE METHOD 강사레슨 큐카드 하단은 별점 제출 대신 수업촬영영상 시청을 위한 ARCHIVE PILATES 아임웹 가입 CTA로 안내합니다. 배포 전 롤백 가드와 배포 후 라이브 canary는 페이지 응답, CTA 문구, 가입 링크를 확인합니다.
4-1. Instagram 콘텐츠 운영
ARCHIVE PILATES 공식 계정의 초안, 승인, 예약 발행과 성과를 한곳에서 관리합니다.
계정 방향
발행 흐름
운영 리듬
안전 규칙
현재 상태