고객 관계 관리
@roumit.com 계정만 접속 가능합니다
허브 — BP 연동 예정
CRM이 다루는 대상을 접촉 이력과 계약 상태를 기준으로 세 단계로 구분한다.
| 구분 | 정의 | 유입 경로 |
|---|---|---|
| 잠재 | 아직 접촉이 한 번도 없는 고객. 시장에 존재하는 세무사무소 · 회계사무소 전체가 모집단 | 외부 수집 후 등록 (카카오 POI) |
| 문의 | 문의 또는 가입 내용이 접수된 고객 · 문의 — 가입 검토 중 · 가입 — 가입 완료 | Flow 협업툴 태스크 연동 |
| 고객 | 가입이 완료되어 실제 서비스를 이용 중인 고객 | 고객원장 DB 업로드 또는 연동 |
세 구분은 배타적 분류가 아니라 동일 사무소가 시간에 따라 이동하는 상태다. 하나의 세무사무소는 잠재로 등록되어 문의를 거쳐 고객이 된다. 따라서 세 데이터는 서로 다른 테이블에 있더라도 동일 사무소를 가리키는 키로 연결되어야 하며, 이 키가 없으면 전환율 · 파이프라인 집계가 불가능하다.
kakaoid)를 1순위 키로 사용한다. 한국 세무사무소는 동일 주소 · 동일 전화번호를 여러 사업자가 공유하는 경우가 많아 주소나 전화번호는 고유키로 쓸 수 없다. 폴백은 nm:{정규화상호}|{시군구}.그룹 4개와 그 안의 세부 단계로 구성한다. DB 에는 step_group · step_detail 두 컴럼으로 저장한다.
가입완료 컬럼을 두고 온보딩에도 같은 고객을 높는 구조였다. 그러면 집계가 이중으로 되고, 어느 쪽에서 상태를 바꿔야 하는지 모호해지며, 컬럼이 비워지지 않아 대기열 역할을 잃는다.| 상황 | 카드의 행방 |
|---|---|
| 가입 확인 | 컨설팅에서 빠져 온보딩 / 대기 로 |
| 가입 무산 | 컨설팅 안에서 가입실패 로. 다음 단계가 없으므로 종착지 |
| 가입완료 확인 | 칸반의 컬럼이 아니라 통계에서 세는 숫자 |
| 이벤트 | 결과 | 비고 |
|---|---|---|
| Flow 온라인 문의 등록 | 문의 / 신규접수 | 자동 |
| 담당자 배정 | 컨설팅 / 대기 | 자동. 배정이 곳 그룹을 가르는 관문이다 |
| 통화 · 방문 활동 기록 | 컨설팅 / 접촉 | 자동 |
| 가입 확인 | 온보딩 / 대기 | 고객원장 반영 시 |
| 그 외 컬럼 이동 | — | 수동. 담당자가 드래그 |
assignee 가 비었는지로 판정한다. 배정되는 순간 컨설팅 대기로 넘어가고, 배정 담당자가 이후 진행을 맡는다.문의 그룹에 들어오는 경로가 여럿이다. 그래서 칸반 컬럼명을 문의/타겟으로 두었다.
| 경로 | 등록 주체 |
|---|---|
| 온라인 문의 | 고객이 Flow 에 직접 등록 |
| 상담 등록 | 상담자가 통화 후 등록 |
| 타겟 선정 | 영업 담당자가 직접 발굴 |
| MGM 추천 | 기존 고객 소개 |
crm_inquiries 에 inflow_path · inflow_code 가 있으나 실제 값이 위 분류와 대응하는지 미확인이다. 대응하지 않으면 별도 컴럼이 필요하다.가입예정을 컬럼으로 두었는데, 그러면 “무엇을 했나(진행 상태)”와 “얼마나 유망한가(담당자 판단)”가 한 축에 섮인다. 컨설팅 예약을 잡았는데 가능성도 높은 경우 어느 컬럼에 두어야 할지 정할 수 없다.| 값 | 표시 | 적용 그룹 |
|---|---|---|
| 높음 | ● | 컨설팅. 접촉 이후부터 입력받는다 |
| 보통 | ◐ | |
| 낮음 | ○ |
가입 이후에는 “가능성”이 안 맞는다. 그 자리를 위험도가 대신한다 — 10번 섹션 참조.
| 항목 | 내용 |
|---|---|
| 부여 조건 | 마지막 문의일로부터 3개월 경과 · 가입 미전환 |
| 기산 그룹 | 사업자번호 + 문의서비스 단위. 세모R 문의와 링크패스 문의는 별개 파이프라인이므로 각각 기산한다 |
| 재문의 처리 | 같은 그룹에 새 문의가 들어오면 그 일자를 기준으로 단계가 문의부터 다시 시작한다. 이전 건을 완료로 닫지 않는다 (v0.259 확정) |
| 가입 판정 기준 | 고객 데이터 업로드가 소스다 (v0.263 확정). 업로드된 고객 데이터의 서비스명 + 가입일자 로 해당 문의의 성공 · 실패를 갱신한다.신청(가입) 태스크나 join_* 문자열은 기준으로 쓰지 않는다 — 링크패스 · 위멤버스는 가입 태스크가 없어 전부 실패로 찍힌다 |
| 미확인 건 처리 | 지금은 판정하지 않는다 (v0.272 정정). 단계가 비어 있던 건은 일단 문의 / 신규접수 로 두고, 고객 데이터가 올라온 뒤 그 기준으로 실패 · 가입 둘 중 하나로 확정한다.기준 없이 완료로 닫으면 전환율 통계가 왜곡되고 되돌리기 어렵다 |
| 기산점 | 마지막 문의일 (최초 문의일 아님) |
| 해제 | 재문의 시 기산점 갱신 → 자동 해제 |
| 상태 | 부여 조건 | 처리 |
|---|---|---|
| 휴폐업 | 고객원장 업로드 시 휴폐업 정보 포함 | 외부 데이터 반영. 내부 지정 안 함 |
| 경쟁사 | 미정의 — 9번 섹션 D1 | |
단계 값이 두 컬럼에 나뉘어 있는데 화면 드롭다운이 어느 쪽도 아닌 목록을 쓰고 있었다. 값이 멀쩡한데도 단계 미설정 으로 보이던 원인이다.
| 컬럼 | 실제 값 | 쓰이는 곳 |
|---|---|---|
step_group | 문의 · 컨설팅 · 온보딩 · 활성화 종료계 — 완료 · 정지 · 해지 | 칸반 컬럼 · 사이드바 건수 · 단계 필터 · 드롭다운 |
step_detail | 신규접수 · 대기 · 접촉 · 예정 · 가입완료 · 문의종료 · 실패 · 정상 … | 리스트 배지. 그룹 안의 진행 상태 |
step_group 을 쓴다문의 · 접촉 · 가입 · 셋업 · 실패 · 완료 · 정지 · 해지 였는데 DB 값과 겹치는 것이 완료 하나뿐이었다. 칸반 · 사이드바 · 필터가 모두 step_group 기준이므로 드롭다운도 같은 축으로 맞춘다.문의→신규접수(담당자 있으면 담당자배정) · 컨설팅→대기 · 온보딩→대기 · 활성화→정상.
같은 그룹 안에서는 기존 세부단계를 유지해, 담당자배정 상태가 신규접수로 되돌아가지 않는다.| 원칙 | 이유 |
|---|---|
완료 대단계 폐지 | 칸반 신규고객 섹션은 원장 가입일을 세고 완료/완료 40건은 어디에도 쓰이지 않아 이름만 남아 있었다 |
담당자배정 제거 | 배정하면 컨설팅/대기 로 자동 이동하므로 이 상태에 머무는 건이 없다. 도달할 수 없는 값을 목록에 두면 항상 0 으로 보인다 |
| 저장값에 공백 없음 | 접촉 실패 가 아니라 접촉실패. 공백이 들어가면 비교 · 필터에서 실수가 생긴다. 화면에서만 공백을 넣는다 |
| 문의도 진행이다 | 담당자 배정 전이라 컨설팅 대기 와 성격이 같다. 컨설팅 화면에서 바로 처리할 수 있어야 한다 |
데이터가 없습니다 가 된다 —
대기 14 를 고른 상태에서 문의종료 167 을 누르면 0건이 나왔다.| 값 | 뜻 |
|---|---|
| 대기 | 담당자가 배정됐으나 아직 접촉 전 |
| 접촉 | 통화 · 방문 등으로 연결됨 |
| 접촉실패 | 연결되지 않음 |
| 컨설팅예약 | 방문 · 상담 일정이 잡힘 |
| 예정 | 가입하기로 했으나 처리 전. 가능성을 함께 매긴다 |
| 완료 | 가입 확정 → 온보딩으로 이어진다 |
| 실패 | 가입하지 않음 |
접촉 실패 가 아니라 접촉실패 로 저장한다. 공백이 들어가면 비교 · 필터에서 실수가 생긴다. 화면에서만 공백을 넣어 보여준다.possibility 컬럼에 높음 · 보통 · 낮음 을 담는다. step_detail 에 예정 높음 처럼 합치지 않는다 — 접촉 중에도 매길 수 있어야 가능성별 파이프라인 예측이 성립한다.접촉실패 건에 가능성 높음 이 남으면 통계가 왜곡된다.고객원장이 들어와 실제 가입 사실로 단계를 다시 계산했다. 이전 판정은 접수구분만 보았다.
| 문의서비스 | 가입 판정 |
|---|---|
| 세모R | 인사이트 가입일자 없음 + status |
| 세모R+ | 인사이트 가입일자 있음 + insight_status |
| 위멤버스 | wm_plan 존재 + status |
| 링크패스 | 별도 가입 경로가 없다. 플러스 이용 시 무료 제공이라 요금제로 판정 |
2024-07-11 12:05:52) 날짜만으로 비교해야 한다.
시각까지 비교하면 가입일 00:00 < 문의일 12:05 가 되어 문의 후 당일 가입이 “이미 고객” 으로 잘못 잡힌다.
실제로 이 차이로 280여 건이 뒤집혔다 — 신청(가입) 791건 대부분이 같은 날 가입이다.실패 는 단순한 결과 기록이 아니다. 나중에 방문할 대상이다. 그래서 미가입 고객만 남아야 한다.
| 서비스 | 가입 판정 기준 |
|---|---|
| 세모R | status · 인사이트 가입 여부는 보지 않는다 (업그레이드 고객도 세모R 가입자다) |
| 세모R+ | insight_status · insight_joined_at |
| 위멤버스 | wm_plan 존재 |
| 링크패스 | plan = 플러스 · 별도 가입 경로가 없다 |
joined_at_manual = true 인 건은 사람이 판단한 것이므로 자동 전환에서 제외한다.세모R = 인사이트 미가입 이라는 판정 때문에, 세모R 로 시작해 나중에 세모R+ 로 올라간 고객의
과거 세모R 문의가 “미가입” 으로 잡혀 실패가 됐다. 실측 125건이다.
문의종료 로 둔다. 세 갈래를 놓고 보면 답이 하나다.joined_at 을 서비스 구분 없이 채우면 가입한 적 없는 서비스에 날짜가 붙는다.
실측 — 링크패스 실패 39건에 세모R 가입일이 들어갔다. 링크패스는 플러스 요금제 이용 시 무료 제공이라
플러스가 아니면 쓰지 않는다. 근거 없는 날짜는 비운다 — 남겨두면 문의종료 로 잘못 바꿀 수 있는 상태가 된다.crm_step_backup_v300 을 쓴다. possibility 는 함께 비웠다 — 단계가 새로 계산되면 이전 가능성은 근거를 잃는다.문의 레코드의 단계는 접수구분만으로 결정한다. 날짜 · 최신 여부 · 가입 여부는 쓰지 않는다.
| 접수구분 | 단계 | 이유 |
|---|---|---|
| 요금변경 | 활성화 / 정상 | 이미 서비스를 이용 중인 고객의 계약 변경이다. 영업 대기열이 아니다 |
| 문의 · 신청(가입) 담당자 없음 | 문의 / 신규접수 | 파이프라인 진입점. 가입 여부는 고객 데이터로만 판정하므로 접수 기록이 활성화를 주장하지 않는다 |
| 문의 · 신청(가입) 담당자 있음 | 컨설팅 / 대기 | 배정은 담당자가 맡아 컨설팅에서 확인하고 방문을 진행한다는 뜻이다 |
문의 / 신규접수 1,599 · 문의 / 담당자배정 47 · 활성화 / 정상 6 = 1,652활성화 / 정상 1,428 · 컨설팅 / 대기 61 · 온보딩 / 대기 11 은 모두 초기화됐다.
되돌리려면 crm_step_backup_v274 를 쓴다.컨설팅 / 대기 로 자동 이동한다. 배정은 그 담당자가 맡아 컨설팅에서 확인하고 방문을 진행한다는 뜻이기 때문이다.문의 / 담당자배정 으로 잠시 바꿨다가 되돌렸다. 담당자배정 세부단계는 쓰지 않는다.한 고객이 복수 서비스에 가입할 수 있으므로 고객과 서비스는 1:N 관계다.
| 서비스 | 구분 | 단계관리 | 비고 |
|---|---|---|---|
| 세모R | 기본 상품 | ● 대상 | 세모리포트 기본 |
| 세모R+ | 기본 상품 | ● 대상 | 상위 상품. 아래 2개 속성을 가짐 |
| └ 홈페이지 유형 | 속성 (필수) | ○ 유형값 | 세모제공 또는 자체제작 중 택일 |
| └ 링크패스 | 속성 (부가) | ○ 사용여부 | 단독 가입 불가. 세모R+ 가입 시 무료 제공 |
| 위멤버스 | 참조 정보 | ✕ 안 함 | 사용 여부만 참조. 별도 팀이 운영 |
| 필드 | 저장 위치 | 의미 |
|---|---|---|
inquiry_service | crm_inquiries | 문의 서비스 — 접수시점 기준 스냅샷. 링크패스 · 세모R · 세모R+ · 위멤버스 |
inquiry_promo | crm_inquiries | 문의 프로모션 — 성장패키지 | null |
request_kind | crm_inquiries | 접수구분 — 문의 · 신청(가입) · 요금변경 |
current_service | 고객원장 (향후) | 현재 이용 서비스 — 고객당 1개 |
current_plan | 고객원장 (향후) | 정확한 요금제는 여기서만 관리 |
crm_inquiries 에 두지 않는 이유 — 문의 본문의 요금제 문자열은 신청 희망값이라 실제 계약과 어긋난다. 실제 값의 소스는 가입고객현황이다.
| 필드 | 출처 | 용도 |
|---|---|---|
flow_assignee | Flow 동기화 | 임시담당자. 참고 표시만 한다. 화면 · 필터 · 통계에 쓰지 않는다 |
assignee | CRM 에서만 | 실제 담당자. 리스트 · 필터 · 칸반 · 배정 자동이동이 모두 이 값을 쓴다 |
flow_assignee 에만 쓴다. assignee 를 덮어쓰지 않는다assignee 에만 쓴다assignee 로만 만든다 — Flow 값이 섞이면 배정되지 않은 건이 배정된 것처럼 보인다Flow 임시담당자 로 따로 표시해 혼동을 막는다
같은 사업자의 문의 · 신청(가입) · 요금변경을 사업자번호로 묶는다. 리스트는 개별 문의별로 보여주고, 고객을 클릭하면 해당 사업자의 접수 이력이 시간순으로 묶여 보인다.
| 접수일 | 접수구분 | 문의서비스 | 제목 |
|---|---|---|---|
| 23.11.13 | 신청(가입) | 세모R | [신규가입] 칠도세무회계 |
| 25.09.15 | 문의 | 세모R | [세모R 재신청] 칠도세무회계 |
| 26.07.31 | 문의 | 세모R+ | [세모R 플러스 신청] 칠도세무회계 가산디지털점 |
| 26.07.31 | 요금변경 | 세모R+(성장) | [개업성장패키지_요금변경] 칠도세무회계 |
실측 고유 사업자 1,094개 · 2건 이상 보유 425개 · 최다 9건
| 유형값 | 의미 | 확정 시점 |
|---|---|---|
| 세모제공 | 세모리포트가 제작한 홈페이지를 사용 | 가입 시 |
| 자체제작 | 고객이 자체 제작한 홈페이지에 인사이트를 적용 | 가입 시 |
| 미확인 | 세모R+ 신청은 들어왔으나 홈페이지 방식이 아직 정해지지 않은 상태 | 문의 단계 기본값 |
Flow에서 “인사이트” 표기로 들어오는 건은 모두 세모R+ 신청으로 처리하고, 홈페이지 유형은 미확인으로 둔다.
| 유입 표기 | 서비스 | 홈페이지 유형 |
|---|---|---|
| 인사이트 신청 | 세모R+ | 미확인 |
| 세모R & 인사이트 신청 | 세모R+ | 미확인 |
| 세모R & 인사이트 재신청 | 세모R+ | 미확인 |
| 세모인사이트 상담 요청 | 세모R+ | 미확인 |
| 세모R 플러스 신청 · 재신청 | 세모R+ | 미확인 |
crm_inquiries.join_insight 값이 있다고 해서 homepage_type = '자체제작' 으로 이관하지 않는다. 문의 단계 데이터는 전부 미확인으로 두고, 홈페이지 유형은 고객원장(3계층)이 붙을 때 확정한다.| 구분 | 대상 | 표시 값 |
|---|---|---|
| 단계 관리 | 세모R, 세모R+ | 셋업 · 완료 · 정지 · 해지 |
| 유형값 | 홈페이지 유형 | 세모제공 · 자체제작 · 미확인 |
| 사용 여부 | 링크패스 | 사용중 · 미사용 |
| 참조만 | 위멤버스 | 사용중 · 미사용 (집계 제외) |
유입 경로와 갱신 주기가 달라 세 개의 독립 저장소로 구성한다.
| # | 저장소 | 유입 | 내용 |
|---|---|---|---|
| 1 | 잠재crm_prospects | 외부 수집 및 직접 등록 | 전국 세무 · 회계사무소 마스터. 좌표 보유. 현재 12,637건 |
| 2 | 문의내역crm_inquiries | 온라인 및 플로우 유입 연동 | 문의 · 가입 신청 접수 이력. 현재 DB 1,652건 (v0.234 동기화 완료) 기간 2023.06.01 ~ 2026.08.04 |
| 4 | 사람 · 기록 | 앱에서 생성 | crm_contacts 담당자 1,280명 · crm_notes 메모 이력 · crm_note_edits 수정 이력모두 사업자 단위다 — 한 사업자에 계정이 여럿이어도(지점 · 재가입) 사람과 방문 기록은 그 사무소의 것이다. 계정마다 나뉘면 흩어져 못 찾는다 |
| 5 | 보조 테이블 | 앱에서 생성 | crm_feedback 개선의견 (BP 와 분리) · crm_list_prefs 사용자별 목록 컬럼 설정첨부는 menu-files 버킷의 crm/feedback/ 경로 — 파일명을 키로 쓰지 않는다 (한글 · 공백이 있으면 Storage 키로 못 쓴다) |
| 3 | 고객현황crm_customers | 세무사무소목록 엑셀 Data 등록 › 고객 Data | 실제 계약 · 이용 중 고객. 현재 900건 (사업자 886 · 이용기관 900) 키는 utlz_id(이용기관아이디) — 한 사업자에 지점 · 재가입이 붙는다 |
crm_stage is null 인 12,135건만 집계한다.1번은 모집단이고 2번 · 3번은 그 부분집합이다. 따라서 2번과 3번의 레코드는 원칙적으로 1번에 대응 항목이 존재해야 한다. 대응되지 않는 건은 신규 등록 대상이거나 매칭 규칙 보완 대상으로 분리 관리한다.
엑셀 93컬럼 중 33개 항목만 담는다. 나머지는 원본 파일에 남아 있으므로 필요해지면 그때 추가한다.
| 묶음 | 항목 |
|---|---|
| 사업자 | 사업자번호 · 이용기관코드 · 대표이사 · 휴대폰 · 대표전화 · 주소 · 사업자구분 · 휴폐업 |
| 서비스 | 상태 · 요금제 · 가입일 · 재가입일 · 해지일 · 사유 · 정지일 · 사유 · 정지해제일 |
| 거래처 | 위멤버스 총 · 정상 · 정지 · 휴폐업 · 세모 총 · 가입 |
| 인사이트 | 상태 · 가입일 · 정지일 · 사유 · 해지일 · 사유 · 홈페이지 신청 |
| 셋업 | 실시간 · 자동수집 인증서 · 부서사용자 2종 · 신고프로그램 |
| 보고서 | 대기 · 완료 · 보류 · 부가세 대기 · 완료 · 읽음 · 에러 |
| 카카오채널 | 보고서 발송 · 채팅 연동 · 신청 상태 |
- 를 쓴다. 그대로 넣으면 날짜 · 숫자 컬럼이 전부 문자열이 되어 정렬 · 비교 · 판정이 성립하지 않는다. - 는 NULL 로 바꾼다.2023-10-24 · 20231024 · 25-04-01(정지일시). 세 형식을 모두 받는다.주 소 처럼 공백이 여러 칸이라 주 ?소 로는 못 잡았다 — 주[ \t]*소 로 고쳐 누락 1,633 → 83건. 실측 900행 전부 파싱 성공.biz_no 를 키로 쓰면 이 이력이 사라지고 upsert 도 21000 으로 실패한다 — 같은 요청에 같은 키가 두 번 들어갈 수 없다.정상 > 정지 > 해지, 같으면 가입일 최신 순으로 고른다.crm_inquiries 에 저장한다. 원장에 넣으면 다음 고객 파일 업로드가 덮어쓴다.팀 → 채널 → 담당자의 3계층. 헤더 필터(팀 · 채널 · 담당자 · 상품)와 직접 대응한다.
| 계층 | 설명 |
|---|---|
| 팀 | 로움 · 위멤버스 · 외부 3개. 조직 최상위 구분 |
| 채널 | 각 팀 내부의 영업 · 유입 채널 단위 |
| 담당자 | 채널에 소속된 실제 사용자. 고객 · 문의 배정 단위 |
auth.uid() → 담당자 → 채널 → 팀 조회 후 필터CRM 과 BP 는 같은 Supabase 프로젝트를 쓴다. 사용자를 두 곳에서 관리하지 않는다.
| 테이블 | 주인 | 용도 |
|---|---|---|
employees | BP | 사용자 명부. 승인 · 닉네임 · 접속 이력 |
teams | BP | 부서 목록 — 00_공통 · 10_마케팅팀 · 20_UX팀 … |
admins | BP | 관리자 |
crm_companies | CRM | 회사 — 로움 · 위멤버스 · 외부1팀 |
employees.company_id → 회사 · employees.team_id → 부서.teams 에 회사를 넣지 않는다 — 넣으면 BP 메뉴 분류에 섞여 보인다.ON DELETE SET NULL 이라 회사를 지우면 소속자가 자동으로 미지정이 된다. 앱이 일일이 옮기지 않으니 중간에 실패해 일부만 옮겨지는 일이 없다.employees 에 행이 생기는데 company_id 가 비어 미지정으로 들어온다.
crm_auto_company() 트리거가 이메일 도메인으로 자동 배정한다 (@roumit.com → 로움).nickname 이다 (v0.289)헤나 처럼 명부에 없는 표기가 굳어졌다. 그 결과 회사 필터가 모두 0 으로 나왔다.이혜미 henna 처럼 이름을 함께 보여준다.
배정할 수 없는 사람은 뺀다 — 승인 대기 · 거절 · 외부 기간 만료 · 시작 전.팀 을 회사 로 바꿨고 crm_companies 에서 목록을 만든다. 채널 은 아직 비어 있다 (8번 미확정 #4).Flow 문의 내역을 잠재 고객과 대조하여 동일 사무소를 판정하고 단계를 부여한다. 2026-08 실행 완료.
세무사무소는 동일 상호를 여러 곳이 쓴다. 실측 결과 우리세무회계 24곳, 바른세무회계 20곳, 미래세무회계 19곳이 전국에 흔어져 있다. 상호명만으로 매칭하면 서초구 문의가 대전 지점에 붙는다.
similarity()는 업종 표기에 속아 고유명을 놓친다. 진짜 매칭과 오매칭의 유사도 구간이 겹쳐 어느 값으로 끊어도 한쪽이 틀린다.
| 문의 | 잠재 | 유사도 | 실제 |
|---|---|---|---|
| 지엠지 | 지엠지세무회계 | 0.33 | 같은 곳 |
| 위즈 | 위즈택스 | 0.33 | 같은 곳 |
| 세무회계 서우 | 세무회계 굿피플 | 0.36 | 다른 곳 |
| 칠도세무회계 | 칠도세무회계 가산지점 | 0.38 | 같은 곳 |
| 세무회계도율 | 세무회계 온결 | 0.40 | 다른 곳 |
세무 · 회계 관련 문구만 제거한다. 택스 · tax 는 한국에서 고유명사로 쓰이므로 제거하지 않는다.
지점 · 지사 · 본부 · 본사 · 센터를 지우려 했으나, 정규식이 고유명사까지 삼켜 세무법인 세이브택스 인천부평지점이 세 한 글자로 남는 사고가 있었다. 접두 포함 판정을 쓰면 지점명을 남겨도 매칭되고, 오히려 서로 다른 지점을 정확히 구분한다.| 구분 | 건수 | 비고 |
|---|---|---|
| 문의 전체 | 1,652 | 기간 2023.06.01 ~ 2026.08.04 · is_deleted 37건 제외 |
| 전환 대상 문의 | 659 | 세 조건 모두 통과 |
| 전환된 잠재 | 495 | 같은 사무소의 복수 문의는 최근 건으로 통합 |
| 다중 매칭 제외 | 24 | 한 건물에 지점 여러 곳. 신규 등록으로 |
| 신규 등록 대상 | 929 | 잠재에 없던 사무소 |
| 순수 잠재 잔존 | 12,135 | 전체 12,630 − 전환 495 |
| 부여 단계 | 건수 | Flow step 매핑 |
|---|---|---|
| 가입 | 311 | Flow step 값을 그대로 사용문의 → 문의 · 접촉 → 접촉 가입 → 가입 · 완료 → 완료 |
| 완료 | 140 | |
| 접촉 | 27 | |
| 문의 | 17 |
컨설팅 화면 상단에서 골라 본다. 모집단을 복제하지 않는다 — 원본에서 그때그때 계산한다.
| 구분 | 출처 | 실측 | 뜻 |
|---|---|---|---|
| 위멤 | crm_customers | 496 | 위멤버스를 쓰는데 세모R 은 안 쓰는 곳 |
| 해지 | crm_customers · status = 해지 | 305 | 세모R 을 쓰다 해지한 곳 |
| DB | crm_prospects · crm_stage IS NULL | 12,135 | 지도에서 수집한 명단 · 아직 접촉 전 |
| 기타 | 수기 등록 | 0 | 직접 입력한 대상 |
status 는 세모리포트 기준이다. 위멤버스 행에 쓰거나 정상 으로 단정하면 안 된다.
상품명이 있다는 사실만 이용 으로 표시한다. 위멤버스 DB 를 받으면 그 자료로 정의한다.| 원칙 | 이유 |
|---|---|
| 배정만으로 즉시 전환 | 다른 사람이 같은 곳을 접촉하는 것을 막는다. 배정과 전환을 나누면 그 사이에 중복이 생긴다 |
| 목록에서 완전히 빼기 | 표시만 바꾸면 다른 담당자가 또 접촉한다 |
| 출처를 활동으로 남기기 | 목록에서는 사라지지만 어디서 왔는지는 이력에 남는다 |
match_method='manual' | 자동 전환분(addr_core_v4) 과 구분해 롤백 시 수동 작업을 보존한다 |
| 보기만 해도 문의를 만들지 않는다 | 목록을 훑는 경우가 훨씬 많다. 클릭마다 문의가 생기면 데이터가 지저분해진다 |
crm_prospects.assignee 는 누가 맡았는지만 표시한다.상태만 덮어쓰면 잘못 매칭된 건을 골라낼 수 없다. 전환 근거를 함께 기록한다.
| 컴럼 | 용도 |
|---|---|
crm_stage | null 이면 순수 잠재. 값이 있으면 전환된 고객 |
linked_inquiry_id | 전환 근거가 된 문의 |
converted_at | 전환 시각 |
match_method | addr_core_v4 — 자동 전환분만 이 값을 갖는다.수동 변경과 구분되므로 롤백 시 손으로 고친 내용은 보존된다 |
| 함수 | 위치 | 역할 |
|---|---|---|
crm_norm_name() | SQL | 상호명 정규화 — 접두어 · 접미어 · 공백 제거 |
crm_core_name() | SQL | 업종 표기 제거 → 고유명사 추출 |
crm_addr_key() | SQL | 도로명 + 건물번호 추출 |
_normBizName() | JS | 앞 둘과 동일 규칙. 지오코딩 시 좌표 복사용 |
문의 데이터에는 좌표가 없었으므로 기존 잠재 지오코딩 배치에 2단계를 추가했다.
| 결과 | 건수 | 비고 |
|---|---|---|
| 좌표 확보 | 1,489 | 93.8%. 잠재에서 복사한 건이 상당수 |
| 주소 없음 | 95 | 원본 데이터에 주소가 비어 있음 |
| 형식 문제 | 4 | 지번 주소만 있거나 표기 이례적 |
| 조건 | 분류 | 처리 |
|---|---|---|
f_parent_task 비어있음 | 문의 | 새로운 문의 건 |
f_parent_task 있음 | 활동 | 기존 문의의 추가 업무 이력 |
f_task_noFlow export 를 정답으로 본다. export 에 없는 건은 CRM 에서 유효하지 않은 것으로 처리한다.
| 상태 | 처리 | 이유 |
|---|---|---|
| export 有 · DB 有 | UPDATE | f_task_no 기준 갱신 |
| export 有 · DB 無 | INSERT | NOT EXISTS 가드로 재실행 안전 |
| export 無 · DB 有 | is_deleted = true | 물리 삭제 금지 — 하위 활동의 inquiry_id 가 끊긴다 |
crm_inquiries 를 지우면 crm_inquiry_activities.inquiry_id 가 고아가 된다. v0.233 동기화 중 부모 문의 1건을 제외했더니 하위 활동 2건이 고아가 되는 상황이 실제로 발생했다.is_deleted(default false) 컬럼이 이미 있으므로 이를 쓴다. CASCADE 는 어떤 경우에도 쓰지 않는다 — crm_prospects FK 로 전체 유실 사고가 2회 있었다.
_x000D_ 제거 (확정)Flow 엑셀 export 는 셀 안의 줄바꿈을 _x000D_ 라는 문자열로 내보낸다. 이전 이관이 이를 걷어내지 않아 주소 · 유입경로 · 유입코드 · 가입내역 끝에 그대로 붙어 화면에 노출됐다.
crm_strip_x000d() 트리거 함수를 crm_inquiries · crm_inquiry_activities 에 BEFORE INSERT OR UPDATE 로 걸었다.to_jsonb → 오염된 문자열 값만 선별 → jsonb_populate_record 방식이라 컬럼이 추가돼도 코드를 고칠 필요가 없다. 손대지 않은 컬럼은 jsonb 왕복을 거치지 않아 timestamptz · numeric 정밀도에 영향이 없다.
| 처리 | 내용 |
|---|---|
| 제거 | regexp_replace(v, '_x000d_', '', 'gi') — 대소문자 무시 (_x000D_ · _x000d_) |
| 공백 정리 | btrim — 홍보ㆍ광고_x000D_ → 홍보ㆍ광고 |
| 빈 값 | NULLIF(…, '') — 값이 통째로 _x000D_ 였으면 NULL |
| 범위 | 오염된 문자열 값만. 정상 값은 손대지 않아 빈 문자열이 NULL 로 바뀌는 부작용이 없다 |
f_task_no 로 건다 — crm_inquiries 에는 제목 컬럼이 없다.v0.191 ~ v0.206 구간에서 확인 · 수정된 사항.
데이터가 화면에 안 보일 때 원인이 세 곳으로 갈리며, 실패 방식이 서로 달라 구분이 가능하다.
| 관문 | 실패 증상 | 대응 |
|---|---|---|
| ① 테이블 GRANT | 401 + 42501 | 명시적 GRANT 부여 |
| ② RLS 정책 | 200 + 빈 배열 | 정책의 롤과 실제 접속 롤 일치 |
| ③ 앱 에러 처리 | 화면 무반응 | 에러 코드를 UI 에 노출 |
GRANT ALL 이 자동 부여된다. SQL Editor 로 CREATE TABLE 하면 아무 권한도 안 붙는다.crm_prospects(SQL Editor)는 401, crm_inquiries(Table Editor)는 200 빈 배열로 증상이 갈렸다. 같은 “데이터가 안 보임”인데 원인이 달랐다.role_table_grants 로 확인할 것.crm_inquiries 등은 GRANT ALL 상태였다. anon 키는 HTML 에 평문 노출되므로 키를 아는 누구나 문의 1,588건을 지울 수 있는 상태였다. v0.026 으로 전체 회수 후 SELECT 만 재부여했다.crm_* 테이블 SELECT 만. 예외로 배치 지오코딩을 위해 컴럼 단위 권한만 보유한다.crm_prospects (lat, lng, geocoded_at) · crm_inquiries (lat, lng)REVOKE 가 반드시 선행해야 한다.024a, 024b 처럼 파일로 분리rollback · begin 절대 포함 금지 — Supabase SQL Editor 는 스크립트 전체를 한 트랜잭션으로 실행한다. 검증용 rollback 이 앞의 DDL 까지 되돌렸다TRUNCATE ... CASCADE 금지 — FK 연쇄로 crm_prospects 가 전삭제된 사고 발생. 개별 DELETE FROM 사용DROP TRIGGER IF EXISTS; CREATE TRIGGER; 처럼 교체가 목적인 쌍은 분리하면 순서가 어긋나 42710 trigger already exists 가 난다. 실제로 발생했다.DROP CONSTRAINT IF EXISTS; ADD CONSTRAINT; 도 한 문장(ALTER TABLE 다중 절) 으로 묶는다.| 함정 | 증상 · 대응 |
|---|---|
VALUES 첫 행 NULL 타입 추론 | column "customer_count" is of type integer but expression is of type text. 첫 행이 NULL 이면 Postgres 가 text 로 추론한다. SELECT v.* 대신 v.col::integer 처럼 명시적 캐스트를 쓴다 |
| 정규식 공백류가 개행 통과 | - 유입코드 : 처럼 값이 빈 줄에서 공백 패턴이 개행을 넘어 다음 줄 값을 캡처한다. 같은 줄로 한정하려면 탭 · 스페이스만 허용하고 캡처는 개행 제외 문자류로 쓴다 |
| 자동 명명 CHECK 제약 중복 | 테이블 생성 시 붙은 {table}_{col}_check 가 별도로 남아 있다. 새 제약을 추가해도 둘이 AND 로 걸려 교집합만 통과한다. pg_constraint 로 전수 확인 후 구 제약을 DROP 한다 |
Failed to fetch (api.supabase.com) | SQL 오류가 아니다. Studio 통신 실패이므로 쿼리는 서버에 도달하지 않았다. 재실행 · 새로고침으로 해결 |
트리거 42710 | trigger "..." for relation "..." already exists. DROP 과 CREATE 를 파일로 쪼개면 순서가 어긋날 때 발생한다. 교체는 한 파일에 둔다 (SQL 운영 원칙 예외 참조). 이미 있으면 그 자체가 생성 성공 상태이므로 건너뛰면 된다 |
| 화면 이상 ≠ DB 이상 | 화면에 이상값이 보이면 DB 를 먼저 실측한다. join_* 오염으로 판단해 정리 SQL 을 만들었으나 실제 DB 는 정상이었고 브라우저의 오래된 데이터였다. 하드 리프레시가 첫 확인 절차다 |
Postgres \s 는 nbsp 를 공백으로 보지 않는다 | 값이 nbsp(U+00A0) 로 시작하면 ^\s* 가 매칭하지 않아 오염 탐지 쿼리가 0 을 반환한다. 문자열 실측은 encode(convert_to(v,'UTF8'),'hex') 로 바이트를 직접 본다 |
엑셀 _x000D_ 오염 | 셀 내 줄바꿈이 문자열로 적재된다. 로더마다 처리하면 반드시 새는 곳이 생기므로 DB 트리거(crm_strip_x000d()) 로 일괄 차단한다 (6번 참조) |
| 제약 걸기 전 실측 필수 | 기존 데이터가 허용값 밖이면 23514 로 실패한다. 반드시 값 분포를 먼저 조회하고 필요하면 NOT VALID 로 추가한 뒤 VALIDATE 로 승격한다 |
| 버전 | 내용 |
|---|---|
| v0.192 | 잠재고객 로드 시 error 와 빈 데이터 분리. 오류 코드별 메시지 UI 노출. 빈 결과는 IndexedDB 캐싱 안 함 (실패 상태 고착 방지) |
| v0.192 | EXTRA 칩(잠재 · 휴폐업 · 경쟁사)에 카운트 span 추가. 색상 문자열 비교를 dataset.stageId 조회로 교체 — 브라우저가 rgb() 로 정규화해 절대 일치하지 않았다 |
| v0.192 | _custStage 우선순위 배열 보강. indexOf 가 -1 을 반환해 미정의 단계가 최우선 정렬되던 버그 |
| v0.193 | 권한 · 인증 실패는 재시도 무의미 → _prospectLoadBlocked 차단. _checkProspectUpdate 가 에러 시 count=null 을 “변경됨”으로 오인해 전체 재로드를 유발 |
| v0.194 | _loadAllProspects in-flight 가드. 세 곳에서 동시 호출되어 같은 요청이 3번 나가던 문제 |
| v0.195 | 문의 탭에 동일 에러 처리 · in-flight 가드 적용 |
| v0.196 | 본 기획서 화면 추가 (kevin 드롭다운) |
| v0.201 | 배치 지오코딩 2단계 추가 — 문의 유입분. 잠재에 동일 상호가 있으면 API 호출 없이 좌표 복사 |
| v0.202 | 전환 건을 단계별 색상으로 표시. 잠재 칩은 crm_stage is null 만 집계 |
| v0.203 | 검색 범위를 토글 버튼 → 지도 N · 전국 N 칩 2개로. 응답 순서 역전 방지 처리 포함 |
| v0.204 | 잠재 0건이면 조기 종료되어 2단계까지 가지 못하던 버그 수정. 페이징 오류도 함께 — 성공 건은 lat is null 조건에서 빠지므로 offset 을 페이지 크기만큼 올리면 중간을 건너뛴다 |
| v0.205 | 주소 정제 + 3단계 폴백. 실패 건을 콘솔에 표로 출력 |
| v0.206 | 기획서 갱신 — 매칭 규칙 · 전환 결과 · 권한 원칙 반영 |
| v0.209 | 기획서를 레이어 팝업에서 새 창으로 전환. document.write 로 HTML 문자열을 조립했다가 스크립트 블록 안의 닫는 태그 리터럴이 HTML 파서와 충돌 |
| v0.210 | DOM API 로만 구성하도록 재작성. 문법 검증만으로는 이 유형을 못 잡는다 — 스크립트 블록 내 닫는 태그 리터럴 검사를 배포 전 점검에 추가 |
| v0.211~213 | 칸반 컬럼명 · id 재정리. lead→target, contact→consulting, won→onboarding, setup→active. 저장된 사용자 설정 키를 _v2 로 올려 구 값 무효화 |
| v0.214 | 메뉴탭 재편 — 가입 탭 제거, 컨설팅 · 온보딩 · 활성화 탭 추가 |
| v0.215 | 칸반을 그룹 구조로 시도 후 원래 형태로 되돌림(v0.216). DB 작업은 유지 |
| v0.217 | 칸반 컬럼 기본을 리스트형으로 변경 |
| v0.218~223 | 활성화 위험 필터 · 기준 설정 인라인화. 완료 · 정지 · 해지를 통계 패널로 교체 |
| v0.224 | 기획서 갱신 — 단계 체계 재편 · 화면 구성 섹션 추가 |
| v0.225~226 | 칸반을 목업에서 실데이터로 전환. 카드 이동 시 DB 반영 + 이력 기록. 교진 중 상수 선언 부가 삭제되어 RISK_FILTERS is not defined 발생 |
| v0.227 | Supabase 1,000행 제한 해소. 컬럼당 50장 + 더보기 버튼 |
| v0.228~231 | 통계형 컬럼 폭 50%로 줄이기. 스톤러 버그 수정(calc(100vh) 제거). 활성화 · 완료 패널 서식 통일 |
| v0.232 | 기획서 갱신 — 요건 목록 섹션 추가 |
| v0.233 | Flow 유형 매핑 확정 — 제목 대신 본문 필드 판정으로 전환. 행종류 7단계 · 접수구분 3종 · 문의서비스 7단계 규칙 수록 (9-C). 정확도 99.94% |
| v0.233 | 사업자번호 추출 규칙 보강 — 하이픈 없는 10자리 파싱 추가로 1,159 → 1,652건 (99.0%) |
| v0.233 | crm_inquiries 에 inquiry_service · inquiry_promo · request_kind · plan_prev 추가. crm_inquiry_activities 에 f_parent_title · activity_type 추가 |
| v0.234 | DB 동기화 실행 완료 — 문의 1,588 → 1,652 · 활동 58 → 59 · 링크패스 16 → 72 · biz_no 공백 757 → 0 |
| v0.234 | 동기화 원칙 확정 (6번) — export = 정답, is_deleted soft delete, 물리 삭제 · CASCADE 금지, 문의 → 활동 순서 |
| v0.234 | SQL 작성 함정 5종 수록 (7번) — VALUES NULL 타입 추론 · 정규식 개행 통과 · 자동 명명 CHECK 중복 등 |
| v0.234 | 활동유형 10종 확정 (7번) — 방문 우선. inquiry_type 레거시 판정 수록 (9-D) |
| v0.234 | plan · plan_promo 컬럼 제거 — 실측 0건 미사용 |
| v0.235 | 리스트 필터 교체 — listTypeFilter(레거시 inquiry_type 기반) 를 서비스 + 접수 2단(listServiceFilter · listKindFilter) 으로 대체. 각 옵션에 건수 표시 |
| v0.235 | loadInquiries COLS 에 inquiry_service · inquiry_promo · request_kind · plan_prev 추가 — 없으면 필터가 전부 빈 값으로 걸린다 |
| v0.235 | 리스트 컬럼 유형 → 서비스 + 접수 분리. _serviceBadge(성장패키지 부배지 포함) · _kindBadge 추가 |
| v0.235 | INQUIRY_TYPES · INQUIRY_TYPE_COLOR · _inquiryTypeBadge 제거. 상세 패널에 Flow 유형 (레거시) 로 참고 표시만 남김 |
| v0.236 | 필터를 헤더로 통합 — 상품(문의서비스) · 단계 · 담당자 · 검색을 상단 필터바에서 처리. 로컬 필터바에는 접수구분만 남김 |
| v0.236 | stageSel 신설 — 상품 우측. 문의 데이터를 쓰는 뷰(deal · consulting · onboarding · active)에서만 노출 |
| v0.236 | assigneeSel 에 onchange 누락 수정. 담당자 목록에 문의 담당자 합집합 반영 — 문의 뷰에서 비어 있던 문제 |
| v0.236 | applyFilters() 도입 — 필터 변경 시 _inquiryPage = 1. 5페이지에서 결과가 1페이지가 되면 빈 화면이 뜨던 문제 |
| v0.236 | _dealProduct() 가드 — productSel 값이 문의서비스로 바뀌어 지도 · 칸반의 crmDeals.product 와 매칭되지 않으면 필터를 걸지 않는다 |
| v0.236 | 리스트 상단에 적용 중인 헤더 필터 표시(_renderFilterHint) — 필터가 헤더로 옮겨가 어디서 걸렸는지 보이지 않는 문제 보완 |
| v0.237 | 접수구분도 헤더로 이동(kindSel) — 로컬 필터바 완전 제거. 필터는 헤더 한 곳에서만 관리한다 |
| v0.237 | 하단 푸터 3분할 신설 — 좌측 페이지당 건수(20 · 50 · 100 · 200 · 전체) · 중앙 페이저 · 우측 건수 |
| v0.237 | 건수 표시 개선 — 필터 적용 시 1–20 · 72건 / 1,652 형태로 현재 구간 · 필터 결과 · 전체를 함께 보여준다 |
| v0.237 | 페이지당 건수를 localStorage 에 저장해 재접속 시 복원. 변경 시 1페이지로 되돌린다 |
| v0.237 | _renderFilterHint 제거 — 필터가 모두 헤더에 보이므로 중복 표시가 불필요해졌다 |
| v0.238 | _x000D_ 제거를 연동 규칙으로 고정 — crm_strip_x000d() 트리거 함수를 crm_inquiries · crm_inquiry_activities 에 BEFORE INSERT OR UPDATE 등록. 로더 무관하게 저장 전 정리된다 |
| v0.238 | 기존 오염분 일괄 정리 (46 · 47) — 주소 · 유입경로 · 유입코드 · 가입내역 끝에 붙어 화면에 노출되던 문제 |
| v0.239 | SQL 운영 원칙에 예외 조항 추가 — DROP+CREATE 처럼 교체가 목적인 쌍은 한 파일에 둔다. 분리하면 42710 이 난다 (실제 발생) |
| v0.240 | 문의 상세를 우측 도킹 패널 600px 로 재작성 — 리스트 위에 덮이며(position:absolute) 바깥 클릭 · ESC 로 닫힌다. 리스트 컬럼 7개 유지 |
| v0.240 | 탭 2개 — 문의/신청(좌 200 타임라인 + 우 400 상세) · 활동이력(평면 시간순 + 단계그룹 · 유형 칩) |
| v0.240 | 좌측 타임라인 최신 → 과거 정렬. 서비스 전환 배너는 시간순으로 계산해 해당 카드에 부착. 접수 1건이면 타임라인을 숨기고 상세만 전체 폭 |
| v0.240 | 활동 조회를 eq('inquiry_id', id) → in('inquiry_id', ids) 1회로 변경. 같은 사업자 안에서 카드를 옮기면 재조회하지 않는다 |
| v0.240 | 활동 추가는 문의/신청 탭에서만 — 선택된 문의가 곧 부모라 선택 단계가 없다. 수정 · 삭제는 두 탭 모두. 유형 10종 · stage_group 3종 입력값 검증 추가 |
| v0.240 | 리스트 사무소명 옆 다건 배지(_bizCount) — 클릭 전에 다건 사업자를 알 수 있다. 클라이언트 계산이라 추가 쿼리 없음 |
| v0.240 | updateInquiryStep 이 존재하지 않는 step 컬럼에 저장하던 버그 수정 → step_detail |
| v0.241 | 타임라인 카드 — 날짜를 배지 줄 우측에 진하게 이동. 시간 흐름이 먼저 읽히도록 |
| v0.241 | 카드 요약에서 서비스명 중복 제거 — inquiry_type 접두어를 떼면 배지와 같은 값이 남았다. 요금변경은 변경 전 → 플러스, 그 외는 거래처수만 표시 |
| v0.241 | _inqNarrative() 신설 — 문의내용에서 상단 표에 이미 나온 필드와 가입내역 블록을 제거하고 실제 문의 · 요금제변경 신청 내용만 남긴다. 남는 게 없으면 섹션을 숨긴다 |
| v0.242 | _parseJoin() 신설 — 정상 (231113, 스페셜요금제, 113개) 를 상태 · 가입일 · 요금제 · 거래처수로 분해. 8번 미확정 #10 의 부분 해결(표시 전용, 컬럼 분해는 미실시) |
| v0.242 | 거래처 표시를 서비스별로 분리 — 세모 113개(스페셜요금제) · 위멤 164개(프리미엄). 가입내역에 수치가 없으면 customer_count 로 폴백 |
| v0.243 | 거래처 표시에서 세모R 요금제 제거 — 서비스 배지(세모R · 세모R+)가 이미 등급을 나타내 중복이었다. 위멤버스 요금제는 별개 축이라 유지 |
| v0.244 | _cleanOffice() 신설 — 사무소명에 붙어 있던 유입코드 · 등록일 · 거래처수 접미어를 제거한다. 칠도세무회계_TAX_SEMO_UXM → 칠도세무회계, 선율회계법인(972개,5명)_250616_HP_LP → 선율회계법인. 앞쪽 접두어(로직지점_) 는 사무소명의 일부이므로 보존 |
| v0.244 | _officeLabel() — 사무소명 (인물명) 형태로 표시. 문의는 신청자명, 신청(가입) 은 대표자명을 쓴다. 리스트 · 패널 헤더 · 상세 표에 적용 |
| v0.245 | 접수가 1건일 때도 좌측 타임라인을 표시 — 이전에는 숨기고 상세만 전체 폭으로 썼다. 레이아웃이 건수에 따라 바뀌지 않는 편이 읽기 쉽다 |
| v0.246 | 상품 필터에서 성장패키지를 세모R+ 바로 아래로 이동 — 세모R+ 의 하위 프로모션이므로 목록 끝이 아니라 부모 옆에 둔다 |
| v0.247 | 기획서 10번 확장 — 헤더 단일 소스 필터 · 하단 푸터 · 문의 상세 패널 · 활동이력 탭 설계를 수록. 문의 건수 1,588 → 1,652 정정 |
| v0.247 | 11-A 전제 갱신 — 상세 패널이 생겨 남은 다섯 개는 입력 UI 추가로 범위가 좁아졌다. 9-D 활동 기록 출처(D10) 확정 반영 |
| v0.248 | 타임라인 카드에 활동 요약 노출 — 활동 2 대신 25.09.22 방문 컨설팅 형태로. 실측 문의 1건당 최대 3건(1건 25 · 2건 14 · 3건 2)이라 길어지지 않는다. 3건 초과는 +N 더 로 접는다 |
| v0.248 | join_* 오염 발견 — 이전 이관이 다음 줄 라벨을 값으로 잡았다 |
| v0.249 | 활동 입력 · 수정을 패널 안 인라인 폼으로 교체 — prompt 연속 호출 방식을 없앴다. 활동 종류(선택) + 내용(여러 줄) 두 필드 |
| v0.249 | 기존 활동도 수정 을 누르면 그 자리에서 폼으로 바뀐다. 삭제 버튼 포함. 저장 후 활동만 다시 읽고(_actReload) 패널을 재렌더한다 |
| v0.249 | 수정 시 일자 · 단계그룹은 기존 값을 유지한다. 신규는 오늘 · 문의 로 들어간다 |
| v0.250 | 활동 일자 수정 권한을 출처로 가른다 — Flow 유입(f_task_no 有) 은 날짜 고정 + Flow 표시, CRM 직접 입력(f_task_no 없음) 은 날짜 입력란 제공 |
| v0.250 | Flow 활동의 날짜를 고치면 동기화 때 되돌아가고 원본과 어긋나 추적이 깨진다. 그래서 UPDATE 에서 activity_date 를 아예 제외한다 |
| v0.250 | 활동 행 메타에 출처(Flow · CRM 입력) 표시 — 수정 가능 범위를 열기 전에 알 수 있다 |
| v0.251 | v0.248 의 join_* 오염 진단을 철회한다. 화면에 위멤버스 = "- 링크패스 :" 로 보였으나 실측 결과 DB 는 정상이었다 — 브라우저의 오래된 데이터였다 |
| v0.251 | 실제 이상값은 자유입력 변형 8건 — () 3 · 미가입 1 · 가입 2 · 장기미사용정지 1 · 위멤버스 스탠다드 1. SQL 69 로 () · 미가입 · 해지 () 만 정리하고 의미 있는 값은 보존 |
| v0.252 | 상세 패널을 15% 확대 — 600 → 690px (좌 200 → 230 · 우 400 → 460). 문의내용 본문과 가입내역이 한 줄에 더 들어간다 |
| v0.253 | 리스트 배지를 문의 N · 활동 N 두 개로 분리 — 라벨은 작게, 숫자는 굵게. 1건인 사업자도 표시한다 (이전에는 2건 이상만 숫자 하나) |
| v0.253 | 활동 전체(crmAllActs) 를 문의와 함께 로드 — 리스트에 활동 수를 쓰려면 미리 있어야 한다. 59건 규모라 부담이 없다 |
| v0.253 | _bizStats() 집계 캐시 — 행마다 전체를 훑으면 전체보기(1,652행) 에서 2.7M 회 순회가 된다. 렌더 1회당 Map 을 한 번만 만든다 |
| v0.254 | 활동 배지를 활동 1/2 형태로 — 분자는 이번 항목의 활동, 분모는 이 고객과의 모든 활동. 같은 사업자의 다른 접수에 활동이 있는지 리스트에서 바로 보인다 |
| v0.255 | 메뉴탭을 좌측 세로 사이드바로 이동 — 헤더가 필터 전용이 된다. 기본 접힘 56px(아이콘 + 라벨), 펼침 152px. 접기 상태는 localStorage 에 저장 |
| v0.255 | 펼친 상태에서만 탭별 건수 표시 — 문의 1,652 · 컨설팅 63 처럼. crmInquiries 클라이언트 집계라 추가 쿼리가 없다. 접힌 상태에는 표시할 자리가 없다 |
| v0.255 | 본문을 #mainWrap(사이드바 + #contentWrap) 으로 감쌌다. 사이드바 토글 시 지도는 resize 를 트리거해 타일이 깨지지 않게 한다 |
| v0.256 | 헤더에 [전체 | 중복제외] 세그먼트 추가 (팀 앞) — 다건 사업자가 425개라 전체 목록에서 같은 사무소가 여러 줄 반복돼 혼란스럽다 |
| v0.256 | 중복제외는 필터를 먼저 걸고 적용한다 — 걸린 조건 안에서 최신 접수 1건만 남는다. 등록일 내림차순 배열의 첫 등장만 취해 최신 건이 남는다 |
| v0.256 | 건수 분모도 모드에 따라 바뀐다 — 전체는 1,652, 중복제외는 고유 사업자 1,094. 상태는 localStorage 에 저장 |
| v0.257 | 사용자 노출 문구에서 접수 → 문의 통일 — 패널 헤더 배지(접수 2건 → 문의 2건) · 리스트 배지 툴팁 · 중복제외 툴팁 |
| v0.257 | 접수구분 필터 라벨과 리스트 컬럼명은 그대로 둔다 — 이 카테고리의 값이 문의 · 신청(가입) · 요금변경 이라, 라벨을 문의 로 바꾸면 값과 같은 이름이 되어 모호해진다 |
| v0.258 | 타임라인 카드 우측에 단계 · 담당자 셀렉트 추가 — 상세로 들어가지 않고 목록을 보며 완료 처리하거나 담당자를 부여할 수 있다. 패널 690 → 840px (좌 230 → 380) |
| v0.258 | 담당자 배정은 기존 assignInquiry() 를 재사용 — 배정 시 컨설팅 대기로 자동 이동하는 규칙이 그대로 적용된다. 빈 값 선택은 배정 해제 |
| v0.258 | 셀렉트 영역에 stopPropagation — 카드 클릭(문의 전환) 과 겹치지 않게 한다 |
| v0.259 | 중복제외 키를 biz_no → biz_no + 문의서비스 로 변경. 다건 사업자 425개 중 109개가 서비스 2종 이상이라 기존 키는 살아있는 기회를 가렸다. 기준 조합 1,094 → 1,207 |
| v0.259 | 칸반에도 중복제외 적용 — 전체 집합에 먼저 적용한다. 컬럼별로 적용하면 같은 고객이 여러 컬럼에 남는다. 활성화 위험 패널도 같은 소스를 쓴다 |
| v0.259 | 자동 실패 규칙 보강 (D2) — 기산 단위는 사업자번호 + 문의서비스. 재문의 시 그 일자부터 단계가 문의로 재시작하며 이전 건을 완료로 닫지 않는다 |
| v0.259 | _dedupRows 가 입력 정렬에 의존하지 않도록 내부 정렬 추가 — 칸반은 등록일 순서가 보장되지 않는다 |
| v0.260 | 타임라인 단계 · 담당자 셀렉트를 글씨 폭만큼만 축소 — 고정 132px → width:auto (최대 96px). 남는 공간은 카드가 가져가 활동 요약이 더 잘 보인다 |
| v0.260 | 기본 화살표를 appearance:none + 인라인 SVG 캐럿으로 교체 — 브라우저 기본 화살표가 차지하는 여백을 없애기 위해서다. 담당자명이 잘릴 수 있어 툴팁에 전체 값을 노출 |
| v0.261 | 중복제외 키를 모드별로 분리 — 전체 = biz_no + 문의서비스(1,207) · 중복제외 = biz_no(1,094). 두 모드 모두 그룹 최신 1건만 표시하며 전체 이력은 상세 패널 타임라인에서 본다 |
| v0.261 | 리스트 · 칸반 · 활성화 위험 패널이 모두 같은 기준을 쓴다 |
| v0.262 | 담당자 표시 규칙 확정 — Flow 값이 한글이름/영어닉 형태면 로움 직원이므로 닉네임만(박승현/kevin → kevin), 슬래시가 없으면 외부이므로 한글 이름을 그대로 쓴다 |
| v0.262 | 복수 담당자는 각각 변환해 이어붙인다 — 정상균/Tony, 김성기, 박원덕 → Tony, 김성기, 박원덕. 실측 44종 전부 정상 변환 |
| v0.262 | 저장값은 원본을 유지한다. 표시만 바꾼다 — Flow 동기화 값과 어긋나면 담당자 매칭이 깨진다. 셀렉트 option value 도 원본이며 라벨만 표시명이다. 리스트 담당자 칸에 마우스를 올리면 원본이 툴팁으로 나온다 |
| v0.263 | 담당자가 여러 명이면 김성기+2 형태로 축약 — 첫 사람 + 나머지 수. 마우스를 올리면 전체가 툴팁으로 나온다. 리스트 · 상세 · 활동 메타에 적용 |
| v0.263 | 가입 판정 기준 확정 — 고객 데이터 업로드의 서비스명 + 가입일자가 소스다. 자동 실패 구현은 업로드 기능 이후로 미룬다 (2번 표 반영) |
| v0.264 | Data 등록 신설 (kevin 메뉴) — 파일 4종을 올려 CRM 에 반영한다. 화면에 표시하는 일자는 업로드 일자가 아니라 파일 내용의 최신 일자(data_max_date) 다. 그래야 “이 일자부터 다시 받으면 된다” 가 성립한다 |
| v0.264 | 1단계 — 플로우 Data 파싱 · 반영 연결. 9-C 판정 규칙을 JS 로 포팅했고 실측 1,745행에서 SQL 결과와 완전히 일치(문의 1,652 · 활동 59 · 제외 28) |
| v0.264 | 고객 · 정산(자동이체 · 카드) · 상담 Data 는 파일 선택 시 행수 · 컬럼 · 기간만 미리보기. 파싱 규칙 확정 후 연결한다 (2단계) |
| v0.264 | 엑셀 파싱에 SheetJS CDN 추가. 반영은 f_task_no 기준 upsert 이며 200행씩 나눠 보낸다 — Supabase 요청당 행 수 제한 때문이다 |
| v0.265 | 미리보기가 사라지던 버그 수정 — _duPick 이 DOM 에 직접 쓴 뒤 _duRender 가 전체를 다시 그려 지워졌다. 미리보기 HTML 을 상태에 담고 렌더 함수가 그리도록 변경 |
| v0.265 | 반영 결과를 카드에 남긴다 — 토스트는 사라져서 실패 원인을 놓친다. code · message · details · hint 를 모두 표시하고, 이력 저장 실패도 따로 보여준다 |
| v0.265 | 미연결 3종 미리보기에 컬럼 전체를 표시 — 8개까지만 보여 매핑 확정에 필요한 정보가 잘렸다 |
| v0.266 | Data 등록 카드 높이 축소 — 제목과 설명을 한 줄로 합치고 여백 · 버튼 크기를 줄였다. 카드당 약 40% 낮아져 4종이 스크롤 없이 들어온다 |
| v0.267 | Data 등록에 쓰기 권한 진단 배너 추가 — DEV_MODE = true 라 로그인을 건너뛰고 anon 롤로 접속하는데, anon 은 SELECT 만 가능해 반영 · 단계 변경 · 활동 저장이 모두 조용히 실패한다 |
| v0.267 | 반영 전 세션을 확인해 미리 차단한다 — 1,652건을 전송하고 전부 실패하는 낭비를 막는다 |
| v0.267 | 실측 확인 — 업로드 이력 0건 · 최근 2시간 갱신 0건 · last_registered 가 파일(08-11) 이 아닌 08-03 에 머물러 반영이 되지 않았음이 확정됐다 |
| v0.268 | DEV_MODE = false 적용 — 구글 OAuth 로그인 후 authenticated 롤이 되어 쓰기 권한이 열린다. 8번 미확정 #8 해소 |
| v0.268 | ?dev=1 비상 우회 유지 — OAuth 설정 전 잠기는 것을 막는다. 우회 상태에서는 상단에 읽기 전용 경고 띠가 뜬다 |
| v0.268 | 로그인 도메인 제한 — @roumit.com 이 아니면 즉시 로그아웃. Supabase 는 누구나 구글로 가입할 수 있어 제한이 없으면 외부인이 고객 데이터에 접근한다 |
| v0.268 | 서버측 방어 — RLS 정책을 authenticated full access 에서 roumit members full access 로 교체 (SQL 93~95). 화면단 검사는 우회 가능하므로 이것이 실제 방어선이다 |
| v0.269 | 임시 조치 — anon 쓰기로 전환. 로그인은 나중에 적용한다. DEV_MODE 기본값을 true 로 되돌리고, 전환 시험용으로 ?login=1 스위치를 남겼다 |
| v0.269 | SQL 86 · 88 · 89 · 90 · 91 · 92 로 anon 에 문의 · 활동 · 업로드이력 쓰기 권한과 정책 부여. 되돌리기는 87 · 96 · 97 |
| v0.269 | 8번 #8 과 보안 경고를 현재 상태로 갱신 — anon 키로 고객 데이터 조회 · 수정이 가능한 상태임을 명시. 공개 호스팅 전 필수 조치 3단계를 적었다 |
| v0.270 | 활동 내용이 두 번 나오던 버그 수정 — f_title 이 없으면 제목 자리에 content 를 쓰는데 아래에서 content 를 또 출력했다. CRM 직접 입력 활동은 f_title 이 없어 항상 중복됐다 |
| v0.270 | 담당자가 이메일이면 @ 앞부분만 표시 — kevin.park@roumit.com → kevin.park. CRM 직접 입력은 로그인 이메일이 담당자로 들어간다 |
| v0.271 | 문의 탭 진입 시 단계를 문의 로 설정 — 컨설팅 · 온보딩 · 활성화는 뷰가 step_group 을 자동으로 거는데 문의 탭만 전체가 나와 일관성이 없었다. 지울 수 있는 소프트 필터라 전체 조회도 그대로 가능하다 |
| v0.271 | 탭을 옮길 때만 값을 손댄다 — 들어온 뒤 사용자가 바꾼 단계는 재렌더에도 유지된다. 다른 문의 뷰로 가면 단계 필터를 비워 뷰의 그룹 조건과 충돌하지 않게 한다 |
| v0.272 | 담당자 이원화 원칙 기록 (3번 · 8번 #21) — Flow 담당자는 임시담당자이고 CRM 담당자와 성격이 다르다. flow_assignee 와 assignee 를 매핑하지 않는다. 코드는 이미 분리돼 있어 원칙만 명문화 |
| v0.272 | 상세 패널에 Flow 임시담당자 행 추가 — 값이 있을 때만 표시한다. CRM 담당자와 나란히 보여 혼동을 막는다 |
| v0.272 | 미확인 건 처리 정정 — 3개월 경과분을 완료로 닫으려던 것을 취소. 단계가 비어 있던 건은 문의 / 신규접수 로 두고, 고객 데이터 업로드 후 실패 · 가입 중 하나로 확정한다 (2번 표 반영) |
| v0.273 | 페이지당 건수에 자동 추가 — 화면 높이에서 헤더 · 푸터를 뺀 뒤 실제 행 높이로 나눠 한 화면에 딱 맞는 수를 쓴다. 행 높이는 렌더 후 측정해 갱신하고, 창 크기가 바뀌면 다시 계산한다. 기본값을 자동으로 했다 |
| v0.273 | 드롭다운 건수와 하단 건수가 어긋나던 문제 수정 — 드롭다운은 중복제외 전을 세고 하단은 중복제외 후를 세서 문의 (150) vs 141건 이 됐다 |
| v0.273 | _facetCount() 신설 — 드롭다운 건수를 패싯 방식으로 계산한다. 다른 필터는 적용하고 세려는 필터 자신만 뺀 뒤 _dedupRows 를 통과시킨다. 상단 [전체 | 중복제외] 선택값이 그대로 반영되며, 이제 드롭다운 숫자가 곧 선택 시 보일 건수다 |
| v0.274 | 단계 드롭다운을 step_group 기준으로 교체 — 이전 목록(문의 · 접촉 · 가입 · 셋업…)은 DB 실제값(신규접수 · 담당자배정 · 대기 · 정상)과 겹치는 것이 완료 하나뿐이라, 값이 있어도 “단계 미설정”으로 보였다 |
| v0.274 | updateInquiryStep 이 step_group 과 step_detail 을 함께 저장하도록 변경. 같은 그룹 안에서는 기존 세부단계를 유지해 담당자배정이 신규접수로 되돌아가지 않는다. 실패 시 이전 값으로 되돌린다 |
| v0.274 | STEP_COLOR 에 세부단계 색 추가 — 신규접수 · 담당자배정 · 대기 · 정상 이 회색으로만 보이던 문제 |
| v0.275 | Flow 유형 (레거시) 행에 불일치 경고 추가 — 현행 inquiry_service 와 어긋나면 ⚠ 서비스와 불일치 · 참고용 을 붙인다. 라벨도 흐리게 처리해 배지와 구분한다 |
| v0.275 | 18962 오인 사례 — 배지는 세모R 로 정상인데 레거시 행의 신규 세모R+ 를 서비스로 오해했다. 이 값은 신규가입 · 재가입 구간에서 780건이 틀리다 (9-D) |
| v0.276 | 단계 전면 재계산 완료 — 문의/신규접수 1,599 · 문의/담당자배정 47 · 활성화/정상 6. 판정 규칙을 2번 · 8번 #22 에 명문화 |
| v0.276 | 담당자 배정 시 컨설팅 자동이동 제거 — 문의 / 담당자배정 까지만 간다. 배정만으로 컨설팅에 넣으면 아직 접촉도 안 한 건이 쌓인다. 재계산 규칙과도 어긋났다 |
| v0.277 | v0.276 을 되돌린다 — 담당자 배정 시 컨설팅 / 대기 로 자동 이동한다. 배정은 담당자가 맡아 컨설팅에서 확인하고 방문을 진행한다는 뜻이므로, 문의 컬럼에는 아직 아무도 잡지 않은 건만 남는 편이 대기열로서 분명하다 |
| v0.277 | 판정 규칙에 담당자 축 추가 — 요금변경 → 활성화/정상 · 담당자 있음 → 컨설팅/대기 · 그 외 → 문의/신규접수. 담당자배정 세부단계는 쓰지 않는다 |
| v0.278 | 전체 는 묶지 않는다 — 이전에는 전체 모드도 biz_no + 문의서비스 로 묶어 1,652 중 445건이 어디에서도 보이지 않았다. 전체 는 그 메뉴 안의 모든 건을 뜻한다 |
| v0.278 | 중복제외 키를 biz_no 로 단순화. 하단 분모도 뷰 조건만 적용한 수로 바꿨다 — 사용자 필터를 뺀 “해당 메뉴에서의 전체” |
| v0.279 | 좌측 탭을 옮기면 헤더 단계 필터가 따라간다 — 문의→문의 · 컨설팅→컨설팅 · 온보딩→온보딩 · 활성화→활성화 · 상담/고객→전체. VIEW_STAGE 로 한 곳에서 관리한다 |
| v0.279 | 고객 탭 재작성 — 데모 데이터를 버리고 crm_inquiries 기반으로 바꿨다. 사업자당 한 줄(최신 접수가 대표) 이며 사무소명 가나다순. 중복제외 세그먼트와 무관하게 항상 묶는다 — 고객 목록이라는 성격 자체가 그렇다 |
| v0.279 | 고객 탭에서 접수구분 필터를 숨긴다 — 고객당 한 줄이라 접수 단위 필터가 맞지 않는다. 분모도 고유 사업자 수(1,094) 를 쓴다 |
| v0.280 | inquiry_type 화면 표시 전부 제거 — 상세 패널 Flow 유형 행 · 칸반 카드 부제 · 활동 메타. 신규가입 · 재가입 구간이 실제 서비스와 무관하게 세모R+ 로 찍혀 780건이 틀렸고, 실제로 두 번 오인을 일으켰다 |
| v0.280 | 값을 재생성하지 않은 이유 — {접수구분} {서비스} 로 다시 만들면 request_kind + inquiry_service 의 복사본이 된다. 배지가 이미 정확하므로 표시를 없애는 편이 맞다. 컬럼은 DB 에 남긴다 |
| v0.280 | COLS 에서 inquiry_type 제외 — 읽지 않는 컬럼을 매번 실어 나를 이유가 없다 |
| v0.281 | Data 등록 반영이 핵심 필드만 보내던 누락 수정 — 사무소명 · 대표자 · 신청자 · 연락처 · 이메일 · 주소 · 거래처수 · 담당자수 · 유입경로 · 유입코드 · 가입내역 4종을 모두 채운다. 이전 반영 건은 사무소명이 비어 있었다 |
| v0.281 | 주소 라벨이 주 소 처럼 공백 여러 칸이라 주 ?소 로는 못 잡았다. 주[ \t]*소 로 고쳐 누락 1,633 → 83건 |
| v0.281 | step_group · step_detail · assignee 는 일부러 보내지 않는다 — 기존 행의 진행 상태와 CRM 담당자를 덮어쓰지 않기 위해서다. 신규 행은 DB 기본값이 채운다 |
| v0.282 | 새로고침 시 단계 필터가 안 걸리던 문제 수정 — setView 는 탭을 옮길 때만 돌아서 첫 로드에는 적용되지 않았다. _initInquiryFilters 에서 뷰가 바뀔 때 한 번만 적용하도록 보완. 사용자가 바꾼 값은 그대로 유지된다 |
| v0.283 | 상세 패널 하단에 삭제 추가 — is_deleted 플래그만 세우는 휴지통 방식이다. 물리 삭제하지 않는다. 활동이 inquiry_id 로 물려 있어 고아가 생긴다 (6번 원칙) |
| v0.283 | 설정 화면 신설 — BP 환경설정과 같은 5탭 구성(히스토리 · 휴지통 · 사용자 · 관리자 · 감사로그). 휴지통부터 동작하며 되돌리기를 지원한다. 나머지는 사용자 · 팀 · 권한 테이블 설계 확정 후 붙인다 |
| v0.283 | 삭제 후 같은 사업자에 남은 건이 있으면 패널을 유지하고 없으면 닫는다 — 여러 건을 연속으로 정리할 때 매번 다시 열지 않아도 된다 |
| v0.284 | 설정 › 사용자 탭 구현 — BP 와 같은 테이블(employees · teams · admins)을 공유한다. 사람을 두 곳에서 관리하지 않는다. 승인 대기자는 상단에 별도 섹션으로 분리 |
| v0.284 | 회사 · 부서 2단 구조 — 회사(crm_companies) 아래에 부서(teams, BP 기존 목록). BP 의 teams 에 회사를 넣지 않는다 — 넣으면 BP 메뉴 분류에 섞인다 |
| v0.284 | 설정 › 회사 탭 — 추가 · 이름변경 · 삭제. 삭제 처리는 DB 가 한다 — ON DELETE SET NULL 이라 소속자가 자동으로 미지정이 된다. 앱이 일일이 옮기지 않는다 |
| v0.284 | 사용자 목록에서 회사 · 부서를 인라인 셀렉트로 바로 바꾼다. 상단 회사 필터에 각 회사별 인원수를 함께 표시 |
| v0.285 | 헤더 검색을 돋보기 아이콘으로 접었다 — 누르면 입력창이 펼쳐지고 자동으로 포커스가 간다. 필터가 늘어 헤더가 빽빽해진 것을 덜어낸다 |
| v0.285 | 검색어가 있으면 접지 않는다 — 걸린 조건이 숨으면 왜 결과가 적은지 알 수 없다. 바깥을 눌러도 검색 중이면 열린 채 유지되고, 지우기를 누르면 접힌다 |
| v0.285 | 접힌 상태에서도 검색 중이면 아이콘을 파랗게 표시 — 조건이 걸려 있다는 신호를 남긴다 |
| v0.286 | 설정 › 히스토리 탭 구현 — 누가 · 언제 · 무엇을 시간순으로 본다. crm_stage_history(단계 변경) 와 crm_inquiry_activities(활동) 를 각각 읽어 클라이언트에서 병합한다. 조인하면 한쪽이 없을 때 행이 사라진다 |
| v0.286 | 드롭다운 단계 변경도 이력에 남긴다 — 지금까지 칸반 드래그(_applyStageMove) 만 기록해 절반이 비어 있었다. _logStage() 로 한 곳을 지나게 했다 |
| v0.286 | 삭제 · 복구도 기록한다. 이력 기록 실패가 본 작업을 막지 않도록 예외를 삼킨다 — 부수 기록이 주 작업을 되돌리면 안 된다 |
| v0.286 | 같은 값으로 단계를 다시 지정하면 이력을 남기지 않는다 — 실수로 같은 항목을 눌러도 기록이 더럽혀지지 않는다 |
| v0.287 | 설정에서 회사 추가 · 삭제가 즉시 반영되지 않던 버그 수정 — _stUsersLoad 가 사용자 탭일 때만 다시 그려서, 회사 탭에서는 아무 일도 없는 것처럼 보였다 |
| v0.287 | 부서를 회사별로 나눈다 — teams.company_id 로 소속을 정하고, 회사를 바꾸면 그 회사의 부서만 목록에 나온다. company_id 가 없는 부서는 공통으로 보고 어디서나 표시 |
| v0.287 | 회사를 옮길 때 새 회사에 없는 부서면 자동 해제 — 목록에 없는 값이 저장된 채로 남지 않게 한다 |
| v0.287 | 헤더 팀 → 회사. crm_companies 에서 목록을 만들고 회사별 문의 건수를 함께 표시한다. 필터는 담당자의 소속 회사로 건다 — 문의 자체에는 회사가 없기 때문이다 |
| v0.288 | 설정에서 사용자가 안 보이던 문제 — Promise.all 로 네 테이블을 묶어 읽어서 하나라도 실패하면 전부 비었다. 테이블별로 성공 · 실패를 따로 잡도록 바꿨다 |
| v0.288 | 조회 오류를 화면에 표시한다 — 어느 테이블이 어떤 코드로 막혔는지 보여준다. 이전에는 토스트로 한 번 스치고 사라져 원인을 알 수 없었다 |
| v0.288 | teams.company_id 가 아직 없어도 동작하도록 보완 — 컬럼이 없으면 부서를 전부 공통으로 본다. SQL 127 실행 전에도 화면이 비지 않는다 |
| v0.289 | 담당자 목록을 직원 명부(employees) 기준으로 교체 — 이전에는 문의에 적힌 문자열을 모아 써서 헤나 처럼 명부에 없는 표기가 굳어졌다. 그 결과 회사 필터가 모두 0 으로 나왔다 |
| v0.289 | 저장값은 nickname 으로 통일. 목록에는 이혜미 henna 처럼 이름을 함께 보여주되 저장은 닉네임 그대로다 |
| v0.289 | 명부를 못 읽으면 기존 값으로 대체한다 — 권한 문제로 employees 가 비어도 배정 기능이 멈추지 않게 |
| v0.290 | 담당자 필터에 건수 표시 — 상품 · 단계와 같은 패싯 방식이다. 다른 필터를 적용한 뒤 자기 자신만 빼고 세므로, 드롭다운 숫자가 곧 그것을 골랐을 때 보일 건수다 |
| v0.290 | 담당자 목록을 명부 + 실제 배정값 합집합으로 — 명부에 없는 표기가 남아 있으면 ⚠ 를 붙여 함께 보여준다. 목록에서 빠지면 그 건들을 걸러낼 방법이 사라진다 |
| v0.291 | 담당자 목록에서 배정할 수 없는 사람을 뺀다 — 승인 대기(approved=false) · 거절(rejected_at) · 외부 기간 만료(access_until) · 시작 전(access_from). 승인되지 않은 사람에게 일을 맡길 수 없다 |
| v0.291 | 이미 배정된 값은 계속 보여준다 — 나중에 퇴사 · 만료되어도 그 건들을 걸러낼 방법이 남아야 한다 (⚠ 표시) |
| v0.292 | 담당자 셀렉트에 추천 구획 추가 — 같은 서비스 · 같은 단계에서 실제로 많이 배정된 사람을 위로 올린다. 배정 횟수를 함께 표시한다 |
| v0.292 | 조합이 맞는 이력이 없으면 단계만으로 다시 센다. 그것도 없으면 추천을 내지 않는다 — 근거 없는 추천은 방해가 된다. 추천 구획 이름에 근거를 적는다(추천 · 세모R+ 컨설팅) |
| v0.292 | 추천에는 배정 가능한 사람만 넣는다 (v0.291 기준). 배정할 때마다 색인을 비워 순위가 곧바로 반영된다 |
| v0.293 | 필터를 바꿔도 드롭다운 건수가 갱신되지 않던 버그 수정 — _initInquiryFilters() 가 데이터 로드 직후에만 돌았다. 중복제외를 켜면 하단은 1,076 인데 드롭다운은 1,606 그대로였다 |
| v0.293 | applyFilters() 가 건수 재계산까지 맡는다. 회사 · 채널 필터도 같은 경로를 타게 해 모든 필터가 한 곳을 지나간다 |
| v0.293 | 탭을 옮기면 _stageInitView 를 비운다 — 단계 기본값이 다시 적용되도록 |
| v0.294 | 고객원장 신설 — crm_customers (49컬럼). 세무사무소목록 엑셀 93컬럼 중 화면에 쓰는 33개 항목을 담는다. 키는 biz_no 이며 재업로드 시 upsert 로 갱신된다 |
| v0.294 | Data 등록 › 고객 Data 파싱 · 반영 연결. 실측 900행 전부 파싱 성공 (제외 0). 엑셀의 - 를 NULL 로 바꾸고 날짜 · 숫자를 형변환한다 — 문자열로 두면 정렬 · 비교 · 판정이 성립하지 않는다 |
| v0.294 | 날짜 형식 3종을 모두 받는다 — 2023-10-24 · 20231024 · 25-04-01(정지일시). 한 파일 안에서도 컬럼마다 표기가 다르다 |
| v0.294 | 고객 반영과 단계 판정을 분리한다 — 원장을 먼저 정확히 채우고 판정은 별도로 실행한다. 한 번에 하면 잘못됐을 때 되돌리기 어렵다 |
| v0.295 | 고객원장 키를 biz_no → 이용기관아이디 로 변경. 실측 900행 중 사업자번호는 886개(중복 12) 이고 이용기관아이디는 900개 전부 고유하다 |
| v0.295 | 한 사업자에 여러 이용기관이 붙는다 — 지점 · 팀 분리(세무법인송촌 본점/4팀/5팀) 와 재가입(위너세무회계 24-08 가입 → 24-10 해지 → 26-03 재가입). biz_no 를 키로 쓰면 이 이력이 사라지고 upsert 도 21000 으로 실패한다 |
| v0.295 | 고객 색인을 사업자당 배열로 바꿨다. 정상 > 정지 > 해지, 같으면 가입일 최신 순으로 정렬해 첫 번째를 대표로 삼는다. 지점이 여럿이어도 현재 상태를 정확히 고른다 |
| v0.296 | 상세 패널에 고객 탭 신설 — 사업자 · 서비스 이용 · 보고서 · 거래처 · 셋업 · 카카오채널 · 판정 근거 7구획. 탭 순서는 고객 → 문의/신청 → 활동이력 |
| v0.296 | 지점 · 재가입이 여러 건이면 상단에서 골라 본다. 기본은 대표 1건(정상 > 정지 > 해지 · 가입일 최신). 사업자가 바뀌면 선택을 처음으로 되돌린다 |
| v0.296 | 좌측 고객 탭에서 들어오면 상세도 고객 탭부터 연다 — 고객 목록을 보다 한 줄을 눌렀는데 문의 이력이 먼저 뜨면 맥락이 끊긴다 |
| v0.296 | 고객원장에 없는 사업자는 탭을 흐리게 표시. 여러 건이면 고객 3 처럼 수를 붙인다. 인사이트 요금제 칸에는 홈피신청 · 자체홈피 를 쓴다 — 인사이트 가입자만 값이 생긴다 |
| v0.297 | 컨설팅 세부단계 7종 — 대기 · 접촉 · 접촉실패 · 컨설팅예약 · 예정 · 완료 · 실패. 저장값에 공백을 넣지 않고 화면에서만 넣는다 — 공백이 들어가면 비교 · 필터에서 실수가 생긴다 |
| v0.297 | 가능성은 단계와 별개 축(possibility) — 높음 · 보통 · 낮음. step_detail 에 예정 높음 처럼 합치지 않는다. 접촉 중에도 매길 수 있어야 파이프라인 예측이 성립한다. 예정에서 벗어나면 자동으로 비운다 |
| v0.297 | 컨설팅 화면에 세부단계 필터 줄 — 세부단계 7종 · 예정 가능성 3종 · 잠재 4종. 예정 · 잠재는 라벨로 묶고 색을 달리해 성격을 구분한다 |
| v0.297 | 잠재 목록 · 상세 · 배정 — 잠재를 누르면 목록 구성 자체가 바뀐다(문의가 아닌 다른 테이블). 잠재-DB 12,135건은 누를 때 한 번만 읽는다 |
| v0.297 | 배정 = 문의 생성 + 잠재 전환. match_method = manual 로 남겨 자동 전환분(addr_core_v4) 과 구분한다. 출처를 활동으로 기록해 전환 후에도 어디서 왔는지 알 수 있다 |
| v0.298 | 잠재 DB 건수가 0 으로 보이던 버그 수정 — 목록을 누를 때 읽는 배열의 길이를 쓰고 있었다. head 조회로 건수만 미리 받는다. 12,135행을 내려받지 않으므로 즉시 끝난다 |
| v0.298 | 잠재 위멤 · 해지 는 사업자당 대표 1건만 센다 — SQL 로 900행을 세면 318 이지만 지점 · 재가입이 섞인다. 접촉 대상으로 같은 사무소를 두 번 넣으면 안 되므로 대표 기준 305 가 맞다 |
| v0.299 | 줄 수를 줄이는 배치로 전환 — 구획 제목을 없애고 라벨을 왼쪽으로 뺐다. 값은 가로로 늘어놓는다. 고객 탭이 약 32줄 → 11줄 로 줄어 스크롤 없이 한 화면에 들어온다 |
| v0.299 | 현재 단계를 패널 헤더 우측에 상시 표시 — 탭을 옮겨도 남는다. 판정 근거도 함께 담아 아래쪽 단계 판정 근거 구획을 없앴다. 단계 · 세부단계 · 가능성을 바꾸면 즉시 갱신된다 |
| v0.299 | 보고서 · 부가세 · 거래처를 라벨 + 가로 카드로 — 보고서 3줄 + 부가세 4줄이 2줄, 거래처 6줄이 2줄이 됐다. 거래처는 위멤버스 · 세모 로 분리해 라벨에 표기 |
| v0.300 | 주소 옆에 복사 버튼 — 지도에 붙여넣어 쓴다. clipboard 가 막히면 옛 방식으로 넘어가고, 그것도 실패하면 안내한다. 누르면 복사됨 으로 1.4초간 바뀐다 |
| v0.300 | 모바일에서는 공유 버튼도 함께 — navigator.share 가 있을 때만 표시한다. 없는 곳에 두면 눌러도 아무 일이 없어 고장으로 보인다. 제목에 사무소명을 넣어 어디 주소인지 알 수 있게 한다 |
| v0.300 | viewport 를 width=1600 으로 고정 — 모바일에서도 축소된 PC 화면을 보여준다. 칸반 · 리스트 · 상세 패널이 넓은 폭을 전제로 설계돼 있어 반응형으로 다시 짜는 대신 확대해 보는 방식을 택했다 |
| v0.300 | onclick 에 주소를 넣을 때 JS 문자열 + HTML 속성 두 단계로 이스케이프한다. 따옴표 · 개행 · & 가 섞이면 속성이 잘려 버튼이 죽는다 |
| v0.301 | 문의 좌표 보완 추가 (kevin 메뉴) — 주소가 있고 좌표가 없는 건을 지오코딩한다. 기존 _geocodeSmart 의 3단 폴백(원본 → 괄호 · 호수 제거 → 도로명만) 을 그대로 쓴다 |
| v0.301 | 실측 — 좌표 없는 문의 198건 중 주소가 있는 것은 53건. 나머지 145건은 주소가 없어 어떤 방법으로도 좌표를 구할 수 없다 (8번 미확정 #12 주소 필수화 필요) |
| v0.301 | 잠재 좌표를 옮기는 방법은 쓸 수 없다 — linked_inquiry_id 로 연결된 495건은 이미 좌표가 채워져 남은 건과 겹치지 않는다. 그래서 주소를 직접 변환한다 |
| v0.301 | 실패분은 콘솔에 console.table 로 남긴다 — 주소 표기를 손으로 고쳐야 하는 건들이라 목록이 필요하다 |
| v0.302 | 칸반 실패 컬럼이 비어 있던 버그 수정 — 판정 규칙은 세부단계를 실패 로 저장하는데 KB_LOST_DETAILS 에는 접촉실패 · 가입실패 만 있었다. 511건이 어디에도 보이지 않았다 |
| v0.302 | 칸반 활성화 전수를 항상 표시 — 이전에는 위험 항목이 모두 - 일 때 헤더 숫자까지 숨겼다. 400건이 있는데 컬럼이 비어 보여 반영이 안 된 것으로 읽혔다 |
| v0.302 | 활성화 컬럼에 전체 목록 줄 추가 — 위험 집계가 비어 있어도 400건을 목록으로 볼 수 있다. 위험 기준은 고객원장 연동 후에 채워진다 |
| v0.303 | 위험 집계 3종 구현 — 고객원장이 들어와 계산이 가능해졌다. 거래처 위험(semo_joined) · 발송수 위험(report_done) · 인증서 위험(cert_realtime · cert_auto 미등록 · 만료) |
| v0.303 | 발송 감소는 null 로 둔다 — 전월 대비 비교가 필요한데 고객원장에 월별 데이터가 없다. 값을 억지로 만들지 않는다. 계산 못 하는 것과 0 은 다르다 |
| v0.303 | 위험 줄을 눌렀을 때 목록이 실제로 걸러지지 않던 문제 수정 — _riskFilter 를 설정하기만 하고 필터링에 쓰지 않았다. 활성화를 벗어나면 자동 해제된다 |
| v0.303 | 인증서 위험에서 자동수집 인증서를 제외한다 — 실측 정상 고객 390건 중 자동수집이 만료 226 · 미등록 152 로 애초에 쓰지 않는 고객이 대부분이다. 포함하면 378/390 이 위험이 되어 지표가 무의미해진다. 실시간만 보면 25건이고 그게 실제 조치 대상이다 |
| v0.304 | 위험 판정 대상을 현재 이용 중인 고객으로 바꿨다 — 문의 단계(활성화 400건) 가 아니라 고객원장 상태(정상 390건) 를 쓴다. 활성화는 “문의가 전환된 건” 이고 위험 관리는 “지금 쓰고 있는 고객” 을 봐야 한다 |
| v0.304 | 위험 있음 · 정상 두 줄 추가 — 항목별 건수는 서로 겹쳐 합계가 전체와 맞지 않는다. 한 고객이 셋에 동시에 걸릴 수 있다. 실제 조치 대상은 합집합이고 안심할 수 있는 수는 여집합이다 |
| v0.304 | 실측 (기준값 20) — 전체 390 · 위험 있음 123 · 정상 267. 위험 1개 56 · 2개 56 · 3개 11건으로 겹침이 상당하다 |
| v0.304 | 활성화 목록도 같은 기준으로 걸러 헤더 · 항목 숫자와 어긋나지 않게 했다. 문의 단계가 활성화여도 원장에서 해지 · 정지면 대상이 아니다 |
| v0.305 | 고객 탭을 고객원장 기준으로 바꿨다 — 가입 이력이 있는 고객만 나온다. 이전에는 문의 목록을 사업자별로 묶어 보여주어 가입한 적 없는 사업자도 섞여 있었다 |
| v0.305 | 상단에 상태 필터 추가 — 전체 · 정상 · 해지 · 정지. 기본은 정상이다. 지금 쓰고 있는 고객이 먼저 보여야 한다 |
| v0.305 | 검색 중에는 상태 필터를 무시한다 — 필터를 잊고 검색해 “없다” 고 오해하는 일을 막는다. 검색어가 있으면 필터 줄에 검색 중 — 상태 무관 전체에서 찾습니다 를 표시한다 |
| v0.305 | 컬럼을 사무소명 · 상태 · 서비스 · 거래처 · 최근 접수 · 가입일 로 바꿨다. 이용 서비스는 원장에서 계산해 여러 개를 함께 표시한다. 문의가 없는 고객은 문의 없음 으로 표시하고 클릭을 막는다 |
| v0.306 | 고객 탭을 편집 가능하게 — 사무소명 · 대표자 · 신청자 · 연락처 · 이메일 · 거래처 · 주소 · 방문메모 8개 항목. 가입 이력이 없어도 열리며 문의 값을 채워 보여준다 |
| v0.306 | 저장 위치는 crm_inquiries 다 — crm_customers 는 엑셀이 주인이라 손으로 고쳐도 다음 고객 파일 업로드가 덮어쓴다. 원장 값(상태 · 요금제 · 보고서 · 인증서) 은 읽기 전용으로 둔다 |
| v0.306 | 고친 칸은 노랗게 표시하고 저장 버튼은 수정이 있을 때만 나온다. 무엇을 고쳤는지 사무소명 · 연락처 수정됨 처럼 함께 보여준다 |
| v0.306 | 저장 없이 닫기 · 탭 이동 · 다른 고객 선택 시 확인을 띄운다 — 입력 계속 · 저장 안 함 · 저장 세 갈래. 무엇을 잃는지 항목명을 적는다 — “저장하지 않은 내용이 있습니다” 만으로는 판단할 수 없다 |
| v0.307 | 활성화 위험 패널 발송 감소 아래에 중복 안내 한 줄 — 위험 대상 합계는 중복 대상이 있어 다를 수 있습니다. 한 고객이 세 항목에 동시에 걸릴 수 있어 합이 전체와 맞지 않는데, 적어두지 않으면 숫자가 틀린 것으로 읽힌다 |
| v0.308 | 목록으로 보기 버튼 제거 — 완료 · 정지 · 해지 통계와 활성화 위험 패널 양쪽에서 없앴다. 건수를 누르면 그 조건으로 목록이 열린다. 숫자를 보고 바로 누르는 것이 자연스럽고 줄도 하나 줄어든다 |
| v0.308 | 통계 행을 누르면 단계 + 기간으로 걸러 본다 — 이번 달 · 최근 3개월 · 올해 · 누적. 건수가 0 인 행은 누를 수 없고, 선택된 행은 파랗게 표시된다 |
| v0.308 | 기간 판정에 updated_at 을 쓴다 — SQL 로 일괄 판정한 건들은 crm_stage_history 에 기록이 없어 이력만으로는 기간을 가릴 수 없다 |
| v0.308 | 이전 _listStageJump 는 선언만 있고 실제 필터에 쓰이지 않았다 — 버튼을 눌러도 활성화 전체가 나왔다. _stageJump 로 바꾸며 위험 필터와 서로 배타적으로 동작하게 했다 |
| v0.309 | 완료 → 신규고객 으로 바꾸고 가입 실적을 보여준다. 기준 날짜는 고객원장의 joined_at 이다 |
| v0.309 | 기간 집계를 고객원장 날짜로 바꿨다 — 신규고객 joined_at · 정지 paused_at · 해지 canceled_at. crm_stage_history 는 SQL 일괄 판정분이 없어 기간 집계에 쓸 수 없고, 원장 날짜는 외부 시스템이 확정한 사실이라 더 정확하다 |
| v0.309 | 정지 · 해지는 현재 그 상태인 고객만 센다 — 과거에 정지했다 정상으로 돌아온 건 제외한다. 사업자당 대표 1건만 보아 지점 · 재가입을 두 번 세지 않는다 |
| v0.309 | 건수를 눌렀을 때 목록도 같은 기준으로 걸러 숫자와 어긋나지 않게 했다. 같은 사업자의 문의가 여럿이면 최신 1건만 남긴다 — 집계가 고객 수이므로 맞춰야 한다 |
| v0.310 | 신규고객 섹션에 인사이트 · 성장패키지 두 줄 추가 (최근 3개월 아래 · 26년 위). 실측 인사이트 106 · 성장패키지 10건 |
| v0.310 | 기준이 서로 다르다 — 인사이트는 원장 insight_joined_at, 성장패키지는 문의 inquiry_promo 다. 프로모션은 원장에 컬럼이 없다 |
| v0.310 | 성장패키지는 사업자 단위로 센다 — 같은 사업자의 문의가 여럿이면 한 명으로 봐야 실적이 부풀지 않는다. 가입일이 있는 고객만 포함한다 |
| v0.311 | 신규고객 최근 3개월 · 26년 아래에 서비스별 분해 3줄씩 — 세모R · 세모R+ · 성장패키지. 들여쓰고 흐리게 표시해 상위 항목과 구분한다 |
| v0.311 | 세모R + 세모R+ = 그 기간 합계다 (26년 42+27=69 · 3개월 10+2=12). 인사이트 가입일이 있으면 세모R+, 없으면 세모R (v0.297 규칙). 성장패키지는 그중 일부라 합계에 더해지지 않는다 — 프로모션이라 겹친다 |
| v0.311 | 줄이 6 → 12 로 늘어 통계 행 상하 여백을 줄였다. 하위 줄은 더 작은 글씨를 쓴다 |
| v0.311 | 하위 줄도 눌러 목록으로 볼 수 있다 — period 를 기간:서비스 형태(year:plus)로 두어 한 값으로 처리한다 |
| v0.312 | 첫 렌더에서 Cannot read properties of undefined (reading 'base') 로 칸반이 죽던 버그 수정 — 고객원장 로드보다 첫 렌더가 먼저 돌아 하위 행의 분해 값이 없었다. 값이 없으면 null 을 넘겨 - 로 표시한다 |
| v0.312 | 고객원장이 도착하면 칸반을 다시 그린다 — 신규고객 · 정지 · 해지 통계와 위험 집계가 모두 원장에 의존한다. 안 그리면 새로고침할 때까지 - 로 남는다 |
| v0.313 | 신규고객 · 정지 · 해지 세 섹션을 내용 높이만큼 쓰게 했다 — 이전에는 flex:1 로 균등 분할해 12줄인 신규고객은 잘리고 4줄인 정지 · 해지는 빈 공간이 남았다. 넘치면 컬럼 전체가 스크롤된다 |
| v0.313 | 통계 본문 여백을 줄였다 (gap 4 → 2 · padding 10 → 7/9) — 줄이 늘어난 만큼 밀도를 높여 세 섹션이 한 화면에 들어오게 한다 |
| v0.314 | 이번 달 아래에도 서비스별 3줄을 넣어 세 기간이 같은 구조가 됐다 — 이번 달 · 최근 3개월 · 26년 모두 세모R · 세모R+ · 성장패키지로 나뉜다 |
| v0.315 | 고객 탭 상태 필터가 걸리지 않던 버그 수정 — 정상 390 을 눌러도 정지 · 해지 고객이 함께 나왔다. v0.305 에서 고객 뷰를 원장 기준으로 바꾼 패치 중 data 부분만 저장되지 않아, 여전히 문의 목록을 읽고 있었다 |
| v0.315 | 같은 이유로 컬럼도 이전 것(서비스 · 단계 · 담당자) 이 남아 row 가 그리는 값과 어긋났다. 사무소명 · 상태 · 서비스 · 거래처 · 최근 접수 · 가입일 로 맞췄다 |
| v0.316 | 고객 탭 위멤버스 상태를 정상 → 이용 으로 — 고객원장의 status 는 세모R 기준이라 위멤버스 행에 쓰면 안 된다. 상품명이 있다는 사실만 표시하고, 색도 상태 계열이 아닌 정보 계열로 구분한다 |
| v0.316 | 잠재 위멤 정의는 그대로 유지 — 위멤버스를 쓰는데 세모R 은 안 쓰는 곳. 이름이 오해를 부르므로 버튼 툴팁에 뜻을 적었다. 위멤버스 DB 를 받으면 그 자료로 다시 정의한다 |
| v0.317 | 기획서에 오늘 작업 반영 — 확정 항목 23~28 추가(위멤버스 상태 미확정 · 위험 판정 대상 · 잠재 4종 · 컨설팅 세부단계 · 고객원장 기준 판정 · 고객원장 신설) |
| v0.317 | 4번에 고객원장 절 신설 — 33개 항목 · 형변환 필수 근거 · 키가 사업자번호가 아닌 이유(지점 · 재가입) · 원장은 외부가 주인 |
| v0.317 | 2번에 컨설팅 세부단계 7종과 고객원장 기준 재판정 절 신설. 같은 날 가입은 전환 성공이라는 근거를 남겼다 — 시각까지 비교해 280여 건이 뒤집힌 것을 기록 |
| v0.317 | 5번에 BP 사용자 공유 · 회사 · 부서 2단 구조 · 자동 배정 트리거 · 담당자 저장값 규칙 반영. 6번에 잠재 4종과 배정 흐름 추가 |
| v0.317 | 10번에 고객 탭 · 컨설팅 필터 줄 · 고객 상태 필터 · 실적 패널 4개 화면 반영. 줄 수를 줄이는 배치 원칙도 함께 적었다 |
| v0.317 | 단계 관련 절이 6번에 흩어져 있던 것을 2번으로 모았다 — 단계 체계 섹션에 있어야 찾을 수 있다 |
| v0.318 | STEP 에서 카드를 눌러도 상세가 보이지 않던 문제 수정 — 패널이 listArea 안에 있어 STEP 화면에서는 부모가 display:none 이었다. 클릭은 되고 있었지만 화면에 나타날 수 없었다 |
| v0.318 | 패널을 contentWrap 으로 옮겨 STEP · 리스트 양쪽에서 덮이게 했다. contentWrap 에 position:relative 를 주어 위치 기준이 되게 한다 |
| v0.318 | 상세를 연 카드를 파랗게 강조한다 — 리스트에서는 행을 강조하고 있었는데 카드에는 표시가 없어 무엇을 보고 있는지 알 수 없었다. 닫으면 해제된다 |
| v0.319 | 위험 칩을 눌러도 색이 바뀌지 않던 문제 수정 — _riskFilter 만 바꾸고 renderRiskBar() 를 다시 부르지 않아 선택 표시가 갱신되지 않았다 |
| v0.319 | 상단 숫자와 하단 건수가 어긋나던 문제 수정 — 위험 건수는 고객 수인데 목록은 문의 건수였다. 한 고객에 문의가 여럿이면 목록이 더 많아진다. 목록도 사업자당 1건으로 줄였다 |
| v0.319 | 상단에 위험 있음 · 정상 칩을 추가 — 칸반에서 그것으로 들어왔을 때 표시할 자리가 없어 무엇을 보고 있는지 알 수 없었다 |
| v0.320 | 칸반 카드 제목을 회사명 (대표자명) 으로 — office_name 원본을 그대로 써서 유입코드가 붙어 나왔다 (태인_TAX_SEMO_HOME). 리스트는 _officeLabel 로 정리하고 있었는데 카드만 빠져 있었다 |
| v0.320 | 카드 우측에 등록일 추가 (26-08-10). 카드 · 목록형 양쪽에 넣었다 |
| v0.320 | 목록형 담당자도 _dispAssigneeShort 를 쓴다 — 박승현/kevin 이 아니라 kevin 으로 나온다 |
| v0.321 | 상세 패널에 유입코드 행을 등록일 아래에 분리했다 — 이전에는 유입 한 줄에 경로와 코드를 · 로 붙여 놓아 어느 쪽이 코드인지 구분되지 않았다. 카드 제목에서 유입코드를 떼어낸(v0.320) 뒤로는 볼 곳이 아예 없었다 |
| v0.322 | 고객 탭 방문메모 를 메모 한 줄로 — 라벨이 두 줄을 차지해 그만큼 높이가 늘었다. 칸 안의 중복 라벨도 없앴다 (왼쪽에 이미 있다). 라벨이 빈 칸은 span 을 아예 그리지 않아 여백이 남지 않는다 |
| v0.323 | 개선의견 기능 — kevin › 개선 의견 메뉴는 있었으나 준비 중입니다 만 뜨고 있었다. 등록 · 수정 · 삭제 · 상태 변경 · 댓글 · 공감 · 첨부를 붙였다 |
| v0.323 | BP 와 분리한다 (crm_feedback) — 같은 프로젝트라 공유할 수도 있지만 쌓이면 어느 제품 얘기인지 헷갈린다 |
| v0.323 | 첨부는 menu-files 버킷(public) 에 crm/feedback/ 경로로 올린다 — BP 파일과 섞이지 않게 나눈다. public 이라 서명 URL 이 필요 없다.파일명을 키로 쓰지 않는다 — 한글 · 공백이 있으면 Storage 키로 못 쓴다. 확장자만 살리고 시각_난수 로 만든다. 원래 이름은 DB 에 남겨 화면에 보여준다 |
| v0.323 | 파일은 건당 5개 · 10MB 까지. 넘는 파일은 이름을 알려주고 제외한다 — 조용히 빠지면 올라간 줄 안다 |
| v0.323 | 삭제는 is_deleted 를 세운다 — 잘못 지웠을 때 되살릴 수 있다. 수정은 그 자리에서 한다 — 창을 하나 더 띄우면 원문이 안 보여 무엇을 고치는지 알기 어렵다 |
| v0.324 | 컨설팅 세부단계 완료 → 가입완료. 종료계 step_group = 완료 의 세부단계도 완료 라서 이름이 겹쳤다 |
| v0.324 | 상세 패널에 가입일자 추가 (등록일 아래) — crm_inquiries.joined_at. crm_customers.joined_at 에 넣지 않는다 — 원장은 외부 시스템이 주인이라 다음 고객 파일 업로드가 덮어쓴다 |
| v0.324 | joined_at_manual 로 수기 입력을 표시한다 — 원장 동기화가 손으로 넣은 값을 덮어써도 되는지 판단할 근거가 필요하다. 없으면 매번 어느 쪽이 최신인지 알 수 없다.화면에 원장 · 수기 출처를 적고, 두 값이 다르면 원장과 다름 을 표시한다 (툴팁에 원장 값) |
| v0.324 | 가입일자를 비우면 manual 이 해제돼 다음 동기화가 원장 값을 넣는다 — 잘못 넣었을 때 원장으로 되돌릴 방법이 있어야 한다 |
| v0.325 | 완료 대단계 폐지 (7 → 6종) — 칸반 신규고객 섹션은 원장 가입일을 세고 완료/완료 40건은 어디에도 쓰이지 않아 이름만 남아 있었다. 한 문의의 결말은 컨설팅 안에서 정한다 |
| v0.325 | 컨설팅 세부단계에 문의종료 추가 — 결말이 네 갈래가 됐다. 실패 와 다르다 — 문의종료는 가입 실적이 있는 고객의 문의를 닫는 것이고, 실패는 가입하지 않은 상태로 끝나는 것이다 |
| v0.325 | 미가입 고객은 문의종료 를 고를 수 없게 막는다 — 드롭다운에서 (가입 후 가능) 으로 표시하고 비활성화한다. 목록에서 아예 빼지 않는다 — 왜 없는지 알 수 없다.저장 직전에 한 번 더 검증한다 — 그 사이 가입 정보가 바뀔 수 있다 |
| v0.325 | 가입 판정은 원장과 CRM 양쪽을 본다 (_hasJoined) — 원장에 없어도 손으로 가입일자를 넣은 건은 실제로 가입한 것이다 |
| v0.325 | 칸반 컨설팅 컬럼에서 결말 4종을 제외한다 — 끝난 건이 쌓이면 대기열이 비워지지 않아 칸반의 역할을 잃는다. 문의종료 는 종료 컬럼에도 넣지 않는다 — 이미 가입한 고객이라 영업 대기열에 있을 이유가 없다 |
| v0.326 | 컨설팅 필터 줄을 그룹 알약으로 — 버튼 15개에 각각 테두리를 두면 화면이 시끄럽다. 그룹 하나를 알약으로 묶고 안쪽은 글과 숫자만 둔다. 라벨은 알약 밖에 둬 그룹 이름이 분명해진다 |
| v0.326 | 5개 그룹 — 진행(대기 · 접촉 · 예약) · 예정(높음 · 보통 · 낮음) · 가입(완료 · 종료) · 실패(접촉실패 · 가입실패) · 잠재(위멤 · 해지 · 주소 · 기타) |
| v0.326 | 클릭 가능함은 밑줄로 알린다 — 평소 투명이고 올렸을 때만 보인다. 항상 밑줄이 있으면 화면이 시끄러워진다. 색은 단색으로 통일했다 |
| v0.326 | 0건인 항목은 흐리게 하고 클릭을 막는다 — 눌러도 빈 목록이라 헛걸음이 된다 |
| v0.326 | 잠재 DB 를 화면에서 주소 로 표기 — 출처가 지도 수집이라 주소가 알기 쉽다. 저장값은 DB 그대로 두어 기존 코드가 깨지지 않게 한다 |
| v0.326 | 고객 탭 상태 필터도 같은 형태로 맞췄다 — 화면마다 다르면 같은 자리인데 다르게 읽힌다 |
| v0.327 | 칸반 카드에서 컬럼 전체가 같은 값인 항목을 지웠다 — 문의 컬럼은 전부 신규접수 · 미배정 이라 적어도 아무것도 구분해 주지 않는다 |
| v0.327 | 세부단계는 컬럼 기본값과 다를 때만 보여준다 (KB_COL_DROP 비교). 담당자도 배정된 건만 표시한다 — 배정되면 그것은 실제 정보다 |
| v0.327 | 카드형에서 등록일이 두 번 나오던 것을 정리했다 (제목 우측 · 하단). 하단이 비면 그 줄을 아예 그리지 않아 카드가 짧아진다 |
| v0.328 | 기획서 2번에 업그레이드 고객을 실패로 잡던 문제를 기록 — 세모R = 인사이트 미가입 판정 때문에 세모R 로 시작해 세모R+ 로 올라간 고객의 과거 성공이 실패로 뒤집혔다 (125건) |
| v0.328 | 그 125건을 문의종료 로 둔다 — 실패로 두면 방문 대상이 되는데 이미 상위 상품 가입이라 필요 없고, 가입완료로 두면 이 문의의 성과가 아니라 실적이 왜곡된다 |
| v0.328 | 서비스별로 가입일을 채워야 한다는 원칙을 기록 — 구분 없이 채우면 가입한 적 없는 서비스에 날짜가 붙는다. 링크패스 실패 39건이 그랬다. 근거 없는 날짜는 비운다 — 남겨두면 문의종료 로 잘못 바꿀 수 있다 |
| v0.329 | 기획서 2번에 실패는 방문 대기열 절 신설 — 실패 는 결과 기록이 아니라 나중에 방문할 대상이다. 그래서 미가입만 남아야 한다 |
| v0.329 | 고객원장이 갱신되면 실패 → 문의종료 자동 전환이 함께 일어나야 한다는 원칙을 기록. 담당자가 매번 원장을 대조할 수는 없고, 이미 가입한 곳이 섞이면 헛걸음이 된다. 반대 방향은 없다 — 가입 이력은 사라지지 않는다 |
| v0.329 | 서비스별 가입 판정 기준을 표로 정리. 세모R 은 인사이트 가입 여부를 보지 않는다 — 업그레이드 고객도 세모R 가입자다 |
| v0.329 | 8번 확정 항목 29번 추가. 고객 Data 반영 후 안내에도 다음에 할 일을 적었다 — 업로드만 하고 전환을 잊으면 방문 목록이 어긋난다 |
| v0.330 | 실패 → 문의종료 자동 전환 구현 — 고객 Data 반영이 끝나면 이어서 돈다. 실패는 방문 대기열이라 이미 가입한 곳이 섞이면 헛걸음이 된다 (기획서 2번) |
| v0.330 | 서비스별로 판정 컬럼이 다르다 (_svcJoined) — 구분 없이 보면 가입한 적 없는 서비스가 가입으로 잡힌다.세모R 은 status 만 본다 — 인사이트 가입 여부는 보지 않는다. 업그레이드 고객도 세모R 가입자다.링크패스는 plan = 플러스 일 때만 — 별도 가입 경로가 없다 |
| v0.330 | 원장을 다시 읽은 뒤에 전환한다 — 새 원장 값을 봐야 가입 여부를 판정할 수 있다. joined_at_manual 인 건은 건드리지 않는다 |
| v0.330 | 가입일이 서로 달라 한 번에 못 묶는다. 같은 날짜끼리 모아 요청 수를 줄인다 — 100건 단위로 나누고 그 안에서 날짜별로 묶는다 |
| v0.331 | 고객 탭 글자가 깨지던 문제 수정 — v0.326 에서 필터 줄 CSS 를 교체할 때 범위를 잘못 잡아 고객 탭 CSS 15개 클래스를 함께 지웠다 (cu-row · cu-k · cu-g · cu-c · cu-svc 등). 표와 배치가 모두 무너져 값이 줄바꿈 없이 이어졌다 |
| v0.331 | CSS 블록을 시작과 끝 주석으로 잡아 통째로 교체하면 그 사이의 다른 블록이 함께 사라진다. 앞으로는 교체 후 클래스 정의 유무를 대조한다 — 문법 검증만으로는 이 유형을 못 잡는다 (v0.210 과 같은 교훈) |
| v0.332 | 신규고객 · 정지 · 해지 섹션이 커 보이던 문제 수정 — 행마다 테두리가 있어 15줄에서 그만큼 높이가 늘었다. 테두리를 없애고 여백을 줄여 목록처럼 읽히게 했다. 구분은 배경으로 충분하다 |
| v0.332 | v0.313 의 압축 규칙이 먹지 않고 있었다 — 원본 padding:7px 10px 정의가 뒤에 있어 앞의 규칙을 덮어썼다. !important 로 상하 여백만 이겼고 좌우 여백과 border 는 그대로였다.원본 정의를 직접 고쳤다 — 뒤에 규칙을 덧붙여 이기려 하면 무엇이 실제로 적용되는지 알기 어려워진다 |
| v0.333 | 실패 를 정식 대단계로 넣었다 (6 → 7종) — DB 에 step_group = 실패 384건이 있는데 목록에 없어 드롭다운에서 고를 수도, 헤더 필터로 걸러낼 수도 없었다. 칸반에도 이미 실패 컬럼이 있으니 대단계로 두는 것이 실제 구조와 맞는다 |
| v0.333 | 헤더 단계 드롭다운에 세부단계를 함께 넣었다 — 컨설팅 (167) 아래에 대기 · 접촉 · 예정 · 가입완료 · 문의종료 가 들여쓰기로 붙는다. 「컨설팅 중 예정만」 같은 조회가 실제로 많다.세부단계가 하나뿐인 대단계는 하위를 만들지 않는다 — 같은 값이 두 번 나온다 |
| v0.333 | 컨설팅 화면이 실패 대단계까지 함께 본다 — 결말이 두 대단계에 걸쳐 있어 한쪽만 세면 실패 그룹이 항상 0 이 된다. 필터 줄과 목록이 같은 범위를 써야 숫자를 눌렀을 때 그 수가 그대로 나온다 |
| v0.333 | 필터 없이 컨설팅에 들어오면 진행 중인 건만 보여준다 — 결말이 섞이면 대기열이 아니다. 전체 숫자도 같은 기준으로 센다 |
| v0.334 | 활성화 목록을 고객원장 기준으로 바꿨다 — 문의를 나열하고 있어 위험 있음 123명 중 71명만 나왔다. 문의가 없는 고객 16명, 문의가 활성화 가 아닌 고객 36명이 빠졌다 |
| v0.334 | 빠진 36명은 가입일이 문의일보다 앞서 그 문의가 문의종료 로 판정된 건들이다. 이미 고객이었으니 활성화가 아니지만, 지금 위험한 고객임은 변하지 않는다 |
| v0.334 | 컬럼을 위험 관리에 맞게 바꿨다 — 사무소명 · 서비스 · 거래처 · 보고서 · 인증서 · 담당자. 기준 미달 값은 붉게 표시해 어느 항목이 위험한지 바로 보인다. 접수 · 단계 · 등록일은 뺐다 — 고객 관점에서 부수적이다. 문의가 있으면 행을 눌러 상세로 가고, 없으면 문의 없음 으로 표시한다 |
| v0.335 | STEP 화면에도 단계 · 접수 필터를 노출했다 — 카드가 문의 데이터라 같은 필터가 성립한다 |
| v0.335 | 칸반이 헤더 필터를 반영하지 않던 문제 수정 — 담당자만 걸고 있어 상품 · 단계 · 접수 · 회사 · 검색을 바꿔도 카드가 그대로였다. 필터가 있는데 듣지 않으면 고장으로 보인다 |
| v0.335 | 단계 필터는 대단계 · 세부단계 둘 다 받는다 — 드롭다운에 함께 들어 있다 (v0.333) |
| v0.335 | 빈 컬럼에 필터 적용 중 을 표시한다 — 단계를 걸면 다른 컬럼이 모두 비는데 그 이유를 모르면 고장으로 보인다. 칸반에서도 드롭다운 건수를 채운다 |
| v0.336 | 단계 드롭다운의 세부단계 건수가 틀렸던 문제 수정 — 대기 가 컨설팅과 온보딩에 모두 있는데 구분 없이 세어 「컨설팅 > 대기 36」 으로 보였지만 그 36건은 온보딩/대기 였다. 건수를 그 대단계 안에서 센다 |
| v0.336 | 옵션 값에 대단계를 담는다 (컨설팅|대기) — 세부단계 이름만으로는 어느 대단계인지 알 수 없어 눌렀을 때 어디로 갈지 정할 수 없었다 |
| v0.336 | 단계를 고르면 그 대단계의 탭으로 옮긴다 — 다른 탭에서 골라도 목록이 보이지 않았다. 뷰가 자기 step_group 을 먼저 걸어 다른 대단계는 애초에 들어오지 않는다. 전용 탭이 없는 대단계(실패 · 정지 · 해지)는 문의 탭에서 본다 |
| v0.336 | 단계 판정을 _stageHit 한 곳으로 모았다 — 네 곳에 흩어져 있어 값 형식이 바뀌면 일부만 고쳐질 위험이 있었다.컨설팅 뷰에서 단계 필터가 걸리면 그것이 우선이다 — 사용자가 명시적으로 고른 값이 기본 동작보다 앞선다 |
| v0.337 | 문의 건을 컨설팅 대기 에서 함께 본다 — 담당자 배정 전이라 성격이 같다. 컨설팅 화면에서 바로 배정하고 처리할 수 있어야 한다. 배정하면 컨설팅 / 대기 로 자동 이동한다 (기존 동작) |
| v0.337 | 헤더 컨설팅 숫자를 진행 건수로 바꿨다 — 결말(가입완료 · 문의종료) 까지 세면 처리할 일이 몇 건인지 알 수 없다. 167건이 보이는데 실제 처리 대상은 0건이었다 |
| v0.337 | 진행 판정을 _isConsultingOpen 한 곳으로 모았다 — 집계 · 목록 · 헤더 드롭다운 · 단계 필터 네 곳이 같은 기준을 쓴다. 흩어져 있으면 한 곳만 고쳐질 위험이 있다 |
| v0.337 | 컨설팅|대기 필터는 문의도 잡고, 컨설팅 대단계 필터는 진행 건만 남긴다 — 결말은 각자 하위 항목으로 고른다 |
| v0.338 | STEP 에 단계 · 접수 필터가 여전히 안 보이던 문제 수정 — v0.335 에서 한 곳만 고쳤는데 setView 에 같은 요소를 숨기는 코드가 또 있었다. 뷰를 옮길 때마다 다시 숨기고 값까지 지웠다 |
| v0.338 | 같은 요소를 두 곳에서 조작하면 나중에 도는 쪽이 이긴다 — 한 곳을 고쳐 화면에서 확인했는데 뷰를 옮기는 순간 되돌아갔다. 다음에 display 를 다룰 때는 그 요소를 건드리는 코드가 몇 곳인지 먼저 센다 |
| v0.339 | 여전히 안 보이던 진짜 원인 — init 은 switchTab 도 setView 도 부르지 않는다. renderAll 만 불러서 마크업의 인라인 display:none 이 그대로 남았다. 탭을 옮기면 보이고 새로고침하면 사라졌다 |
| v0.339 | 판단을 syncHeaderFilters 한 곳으로 모았다 — 세 곳(switchTab · setView · 초기 로드) 에서 각자 판단하고 있어 한 곳이 빠지면 안 보였다. 이제 렌더할 때마다 함께 맞춘다 |
| v0.339 | 같은 판단을 여러 곳에서 반복하지 않는다 — 두 번 고쳐도 세 번째가 남아 있었다. 화면 상태를 정하는 규칙은 한 함수에 두고 필요한 곳에서 부른다 |
| v0.340 | 단계 필터를 마지막에 누른 것이 이기게 했다 — 두 필터를 동시에 걸면 교집합이 비어 데이터가 없습니다 가 됐다. 대기 14 를 고른 상태에서 문의종료 167 을 누르면 0건이 나왔다 |
| v0.340 | 상단 단계를 고르면 필터 줄 선택을, 필터 줄을 누르면 상단 단계를 자동으로 푼다 — 어느 쪽을 눌러도 누른 것이 항상 보인다. 위험 · 실적 필터도 함께 푼다 |
| v0.340 | 상단 단계로 들어오면 필터 줄에서 그 항목이 눌린 것처럼 표시된다 — 어느 조건으로 걸러졌는지 화면에 드러나야 한다 |
| v0.341 | 실패 를 고르면 컨설팅 탭으로 간다 — 문의 탭으로 보내고 있었는데 거기에는 그 목록이 없다. 실패는 결말이라 컨설팅의 일부이고, 컨설팅 뷰가 이미 실패 대단계를 범위에 넣고 있다 |
| v0.341 | 실패 저장값을 화면에서 문의실패 로 부른다 — 접촉실패 와 나란히 놓으면 무엇이 실패했는지 구분된다. 접촉실패는 연결 자체가 안 된 것, 문의실패는 만났으나 가입하지 않은 것이다 |
| v0.341 | 필터 줄 라벨을 _stepLabel 로 통일했다 — 하드코딩(가입실패) 이라 드롭다운과 이름이 어긋났다 |
| v0.341 | 대단계만 골랐어도 건수가 한 세부단계에 몰려 있으면 그것을 선택 표시한다 — 실패 384 를 고르면 문의실패 384 가 눌린 것으로 보여야 어느 조건인지 알 수 있다 |
| v0.342 | 활성화 헤더 숫자를 위험 있음 123 으로 바꿨다 — 다른 컬럼의 숫자는 “여기 쌓인 일” 을 뜻하는데 활성화만 전체 고객 수를 보여 400 이 처리 대상처럼 읽혔다. 실제 손댈 곳은 123 이다 |
| v0.342 | 분모를 작게 함께 적는다 (123 / 390) — 위험 수만 있으면 전체가 몇인지 알 수 없다 |
| v0.342 | RISK_SUMMARY 가 이 함수보다 뒤에 선언돼 있어 방어를 넣었다 — 실행 시점에는 있지만 첫 렌더가 앞서면 ReferenceError 로 칸반이 죽는다 (v0.311 과 같은 유형) |
| v0.343 | 문의실패 를 가입실패 로 되돌렸다 — v0.341 에서 확인 없이 이름을 바꿨다. 저장값은 실패 그대로이고 화면 표기만이라 데이터에는 영향이 없다 |
| v0.343 | 상단 드롭다운에서 실패 를 컨설팅 하위로 넣었다 — 대단계로 나란히 두면 별개 흐름처럼 보이는데, 실제로는 컨설팅에서 끝난 건이고 컨설팅 화면에서 함께 본다 |
| v0.343 | 값에는 실제 대단계를 유지한다 (실패|접촉실패) — 화면에서만 컨설팅 아래로 보이고 필터는 step_group = 실패 로 걸린다. 상세 패널 드롭다운에는 실패 가 대단계로 남아 카드를 그쪽으로 옮길 수 있다 |
| v0.344 | 문의 하위 담당자배정 을 제거했다 — 배정하면 컨설팅/대기 로 자동 이동하므로 이 상태에 머무는 건이 없다. 도달할 수 없는 값을 목록에 두면 항상 0 으로 보인다 |
| v0.344 | 부여하던 곳 두 군데도 함께 정리했다 — 칸반에서 문의로 되돌릴 때와 단계 드롭다운으로 문의를 고를 때 담당자가 있으면 담당자배정 을 붙이고 있었다. 이제 항상 신규접수 다 |
| v0.345 | 상단 드롭다운 활성화 건수를 위험 있음 123 으로 — 이름은 그대로 두고 숫자만 바꿨다. 400 은 전체 고객 수라 손댈 곳이 몇 건인지 알 수 없었다 |
| v0.345 | 칸반 헤더(v0.342) 와 같은 기준을 쓴다 — 같은 항목이 자리마다 다른 수를 보이면 어느 쪽을 믿을지 알 수 없다. 컨설팅도 이미 진행 건만 세고 있다 |
| v0.346 | 상단에서 활성화 를 고르면 위험 있음 칩이 함께 선택된다 — 건수가 위험 있음을 세므로(v0.345) 필터도 같이 걸어야 목록이 맞는다. 걸지 않으면 드롭다운은 123 인데 목록은 390 이 나와 어긋난다 |
| v0.346 | 위험 칩을 누르면 상단 단계를 푼다 — 활성화로 들어오면 위험 필터가 자동으로 걸리는데, 그 상태에서 다른 위험 항목을 누르면 두 값이 겹쳐 결과가 예측하기 어려워진다 (v0.340 「마지막 누른 것이 이긴다」) |
| v0.347 | 문의 목록 컬럼을 요청 순서로 — 등록일 · 사무소명 · 사업자번호 · 신청자 · 핸드폰 · 문의서비스 · 담당자 · 주소 · 유입코드 · 문의내용 |
| v0.347 | 컬럼 제목을 눌러 정렬한다. 같은 컬럼을 다시 누르면 방향이 바뀌고 ▲▼ 로 표시된다.숫자 컬럼은 숫자로, 나머지는 한국어 사전순으로 비교한다 — 문자열로 비교하면 10 이 9 보다 앞에 오고, 한국어를 코드값으로 비교하면 순서가 어긋난다. 빈 값은 방향과 무관하게 뒤로 보낸다 — 위에 몰리면 목록이 비어 보인다 |
| v0.347 | 컬럼을 추가 · 제거 · 순서 변경할 수 있다 (헤더 우측 ⚙). 18개 항목 중 골라 쓴다 — 대표자 · 이메일 · 접수 · 단계 · 거래처 · 유입 · 가입일자 · 가능성이 추가 가능하다 |
| v0.347 | 구성을 사용자별 · 뷰별로 저장한다 (crm_list_prefs) — 영업 담당자는 연락처와 주소를 보고 관리자는 담당자와 단계를 본다. 한 벌로 맞추면 누군가는 늘 필요 없는 컬럼을 본다.값은 jsonb 한 덩어리다 — 컬럼 목록 · 순서 · 정렬이 함께 바뀌므로 나눠 두면 일부만 저장돼 어긋난 상태가 남는다 |
| v0.347 | 정렬은 페이지를 자르기 전에 적용한다 — 나중에 하면 1페이지 안에서만 정렬돼 진짜 첫 건이 오지 않는다. 정렬 컬럼을 껐으면 첫 컬럼으로 옮긴다 — 없는 컬럼으로 정렬하면 순서가 뒤죽박죽이 된다 |
| v0.348 | 목록 담당자 셀에서 바로 배정한다 — 상세를 열지 않아도 되게 한다. 상세 패널과 같은 추천 규칙을 쓴다 (서비스 · 단계 조합별 배정 이력 상위 3명) |
| v0.348 | 셀렉트에서 이벤트를 멈춘다 — 행 클릭이 상세를 열므로, 안 멈추면 고르는 순간 상세가 함께 열려 목록에서 처리하는 의미가 없다 |
| v0.348 | 배정 이력이 없으면 나 자신을 추천한다 — 셀 것이 없으면 추천이 비는데, 목록에서 바로 배정하는 경우 대부분 자기가 맡는다 |
| v0.348 | 배정 건수가 0 이면 괄호를 숨긴다 — (0) 은 정보가 아니다 |
| v0.349 | 잘려 보이는 칸(문의내용 · 주소 · 이메일) 에 마우스를 올리면 전체 내용을 보여준다. 브라우저 기본 title 은 뜨는 데 1초 넘게 걸리고 줄바꿈이 안 되며 길면 잘린다 |
| v0.349 | 값을 DOM 속성에 담지 않는다 — 문의 id 로 그때 읽는다. 1,600건 × 긴 본문을 속성에 넣으면 HTML 이 그만큼 무거워진다 |
| v0.349 | 화면 밖으로 나가면 반대쪽에 붙인다 — 잘리면 읽을 수 없다. 우측 · 하단 · 모서리를 모두 확인했다. 스크롤하면 숨긴다 — 남아 떠 있으면 화면을 가린다 |
| v0.350 | 추가할 수 있는 컬럼을 18 → 31개로 늘렸다 — 상세 패널에만 있던 값을 목록에서도 볼 수 있게 한다. 가입내역 4종(세모R · 위멤버스 · 링크패스 · 인사이트) · 프로모션 · 변경 전 요금제 · Flow 임시담당자 · 직원수 · 다음 액션 · 액션 기한 · 메모 · 대단계 · Flow 번호 |
| v0.350 | 설정 창에서 묶음별로 보여준다 (기본 · 문의 · 단계 · 담당 · 규모 · 가입내역) — 31개를 한 줄로 늘어놓으면 찾기 어렵다 |
| v0.350 | 가입내역은 Flow 본문에서 파싱한 문자열이라 접수 당시 기록으로만 본다 — 요금제 · 거래처수의 정확한 값은 고객원장이 주인이다 |
| v0.350 | 마우스 미리보기가 컬럼 정의의 get 을 쓴다 — 원본 필드를 그대로 읽으면 가공한 값(담당자 표시 등) 과 어긋난다 |
| v0.351 | 사무소명 옆 문의 · 활동 건수 배지를 되돌렸다 — v0.347 에서 컬럼을 교체하며 빠졌다. 같은 사업자에 문의가 여럿인지, 활동이 남아 있는지가 목록에서 바로 보여야 한다 |
| v0.351 | 정렬 · 미리보기는 배지 없는 이름을 쓴다 (get 과 html 분리) — 배지가 섞이면 가나다순이 어긋난다 |
| v0.352 | 고객 목록 컬럼을 요청 순서로 — 가입일 · 사무소명(대표 · 문의 · 활동) · 상태 · 서비스 · 고객(전체) · 세모(전체) · 세모(사용) · 요금제 · 최근문의 · 주소 · 핸드폰 |
| v0.352 | 고객 탭에도 정렬 · 컬럼 설정을 넣었다 (29개 중 선택). 컬럼 정의는 문의와 따로 둔다 — 원장을 나열하므로 필드가 아예 다르다. 저장 틀(crm_list_prefs) 과 정렬 로직은 공유한다 |
| v0.352 | 문의가 없는 고객도 상세가 열린다 — 원장 정보와 방문메모는 문의 없이도 볼 일이 있다 (전화가 와서 찾아보거나 방문 예정을 적어두는 경우). 문의 · 활동 탭은 보여줄 게 없어 숨기고 문의 없음 을 표시한다 |
| v0.352 | 컬럼 로직을 _lcDefs() 로 일반화했다 — 뷰에 따라 정의를 골라 쓴다. 정렬 · 헤더 · 행 · 설정 창 · 미리보기가 모두 한 경로를 쓴다 |
| v0.353 | 목록 날짜를 26.08.01 로 통일했다 (_lcDate) — 2026-08-01 은 10자를 차지해 좁은 컬럼에서 줄이 바뀌거나 다른 값을 밀어낸다. 목록은 훑어보는 곳이라 연도 네 자리가 필요 없다 |
| v0.353 | 등록일 · 가입일자 · 액션 기한 · 가입일 · 최근문의 · 인사이트 가입 · 해지일 · 정지일 8개 컬럼에 적용. 폭도 78 → 66px 로 줄여 그만큼 사무소명에 돌아간다 |
| v0.353 | 사무소명을 한 줄로 고정하고 최소 폭 260px 을 준다 — 두 줄이 되면 행 높이가 들쭉날쭉해져 훑기 어렵다. 문의내용 200 → 130px · 담당자 96 → 72px |
| v0.354 | 같은 행을 다시 누르면 상세가 닫힌다 — 열려 있는 것을 또 열려는 동작은 닫으려는 뜻이다. 문의 · 컨설팅 · 온보딩 · 활성화 · 고객 · 잠재 · 칸반 카드 모두 적용 |
| v0.354 | ESC 로도 닫는다. 여러 겹이 열려 있으면 위에서부터 — 확인창 → 컬럼 설정 → 개선의견 → 상세. 컬럼 설정이 열려 있는데 상세가 닫히면 순서가 뒤집힌다 |
| v0.354 | 바깥 클릭으로도 닫는다. 목록 · 칸반 · 헤더 · 좌측 탭은 예외다 — 목록을 예외로 두지 않으면 다른 행을 누를 때 닫힌 뒤 다시 열려 화면이 깜빡인다. 헤더를 예외로 두지 않으면 필터를 고치는 중에 패널이 사라진다 |
| v0.354 | 편집 중이면 closeInquiryDetail 이 확인을 띄운다 — 토글 · ESC · 바깥 클릭에서 따로 막지 않는다. 판단이 여러 곳에 있으면 한쪽만 고쳐질 위험이 있다 (v0.339 교훈) |
| v0.355 | 사무소명 표시를 모든 목록에서 통일했다 — 사무소명 (대표자) 문의 1 활동 0/0. 활성화 위험 목록 · 잠재 목록에는 배지가 없었고, 잠재-DB 에는 대표자가 없었다 |
| v0.355 | 목록 첫 칸을 항상 한 줄로 (CSS td:first-child) — 뷰마다 따로 지정하면 새 목록을 만들 때 또 빠진다. 최소 폭 240px 을 주어 첫 칸이 폭을 먼저 쓰고 나머지가 줄어든다 — 뒤 컬럼은 잘려도 마우스로 볼 수 있다 |
| v0.355 | 칸반 카드 제목도 한 줄로 — .kb-card-name 에 CSS 가 없어 두 줄이 되면 카드 높이가 서로 달라져 컬럼이 지저분해졌다 |
| v0.355 | 잠재 해지 · 위멤 목록의 행을 누르면 고객 상세가 열린다 — 원장에 있는 고객이라 볼 내용이 있는데 클릭이 막혀 있었다 |
| v0.356 | 고객 탭에 문의 탭 컬럼이 나오던 버그 수정 — _lcApply() 를 currentView = view 앞에서 부르고 있었다. _lcViewKey() 가 이전 뷰를 반환해 남의 설정이 적용되고, 그 상태로 저장되기까지 했다 |
| v0.356 | 저장된 값이 그 뷰의 컬럼 정의와 절반도 안 맞으면 버린다 — 이전 버그로 잘못 저장된 설정이 남아 있어도 기본값으로 되돌아온다. 사용자가 지우지 않아도 스스로 복구된다 |
| v0.357 | 서비스 배지가 두 줄로 넘치던 문제 수정 — 3개면 줄이 바뀌어 그 행만 높아지고 훑을 때 눈이 걸린다. 한 줄로 끊고 폭을 150 → 172px 로 늘렸다 |
| v0.357 | 핸드폰 · 대표전화 폭을 106 → 112px — 010-0000-0000 이 한 줄에 들어가야 한다. 끊기면 번호를 잘못 읽을 수 있다 |
| v0.357 | 고객 목록에서 최근문의를 기본에서 뺐다 — 실측 정상 고객 390명 중 273명(76%) 이 가입일과 같다. 가입 신청 문의가 곧 마지막 문의인 경우가 대부분이라 같은 값이 두 칸을 차지했다. 필요하면 컬럼 설정에서 켠다 |
| v0.358 | 가입일과 사무소명 사이가 벌어지던 문제 수정 — td:first-child 에 min-width:240px 을 걸었는데 고객 탭은 첫 칸이 가입일이라 그 칸이 240px 을 차지했다 |
| v0.358 | 위치로 칸을 찾을 수 없다 — 컬럼 순서를 바꿀 수 있게 만든 뒤로 첫 칸이 사무소명이 아니다. nm-cell 클래스를 붙여 그 칸만 지정한다. 활성화 · 잠재 목록에도 함께 붙였다 |
| v0.358 | 셀 좌우 여백을 14 → 9px — 14px 은 컬럼이 적을 때 기준이었다. 컬럼이 11개면 여백만 300px 이 넘어 값이 들어갈 자리가 없다 |
| v0.359 | 서비스 배지를 3종으로 줄였다 — 세모R · 세모R+ · 성장패키지. 위멤버스는 900건 전부라 구분이 안 되고, 링크패스는 요금제 컬럼과 같은 말을 두 번 한다 |
| v0.359 | 성장패키지 사업자를 미리 모아 둔다 (_promoBiz) — 프로모션은 원장에 컬럼이 없어 문의에서 읽어야 하는데, 행마다 1,659건을 훑으면 목록이 느려진다 |
| v0.359 | 기획서에 v0.347~v0.359 반영 — 확정 항목 30~33 추가(문의는 컨설팅 대기 · 실패는 대단계 · 서비스 배지 3종 · 목록 컬럼은 사용자별) |
| v0.359 | 2번에 단계 체계 최종 절 신설 — 흐름도와 네 가지 원칙(완료 폐지 · 담당자배정 제거 · 공백 없음 · 문의도 진행). 처리할 일의 수를 보여준다와 마지막에 누른 것이 이긴다도 함께 적었다 |
| v0.359 | 10번에 목록 컬럼 · 정렬과 상세 패널 열기 · 닫기 절 신설 — 정렬 세 규칙, 위치로 칸을 찾지 않는 이유, 목록 표기 규칙 5가지, 바깥 클릭 예외 근거 |
| v0.359 | 4번에 보조 테이블 행 추가 — crm_feedback · crm_list_prefs 와 첨부 저장 규칙 |
| v0.360 | 사무소명 옆에 경과일을 붙였다 (D+10) — 화면마다 기한이 다르다. 문의 90일(그 뒤 실패로 자동 판정) · 컨설팅 30일(그 안에 처리해야 한다) |
| v0.360 | 기한이 없는 화면(고객 · 온보딩 · 활성화) 에는 보여주지 않는다 — 재촉할 근거가 없는데 붉은 숫자가 있으면 신호가 무뎌진다 |
| v0.360 | 기한의 2/3 를 넘기면 노랗게, 넘기면 붉게. 툴팁에 기한까지 20일 처럼 남은 날을 적는다 — 숫자만 있으면 며칠이 문제인지 매번 따져야 한다 |
| v0.360 | 셀 여백을 9 → 6px 로 한 번 더 줄이고, 표의 양 끝만 12px 을 준다 — 벽에 붙으면 답답하다 |
| v0.361 | 기획서를 좌측 메뉴 도움말 로 옮겼다 (펼치기 위) — kevin 메뉴 안에 있어 찾으려면 두 번 눌러야 했다 |
| v0.361 | 아이콘은 펼친 책을 쓴다 — 물음표는 “모르는 걸 물어보는 곳” 을 뜻하는데, 이 문서는 설계 근거와 판단 기록이다. 「왜 이렇게 만들었나」 를 담고 있어 책이 맞는다 |
| v0.361 | 도움말은 강조 대상에서 뺐다 — 새 창을 열 뿐 화면을 바꾸지 않는다. 눌렀다고 켜져 있으면 지금 그 화면에 있는 것처럼 보인다 |
| v0.363 | 개선의견을 설정 맨 앞 탭으로 옮겼다. kevin › 개선 의견 도 그 탭을 연다 — 두 경로가 같은 화면을 쓴다 |
| v0.363 | 모달을 없앴다 — 같은 기능이 두 곳에 있으면 한쪽만 고쳐진다 |
| v0.363 | 이전 openFeedback 에 async 가 빠져 있었다 — await _fbLoad() 를 쓰는데 선언이 없어 목록을 읽기 전에 그려 항상 “읽는 중…” 에서 멈췄다 |
| v0.363 | 마크업을 지울 때 앞 요소의 닫는 태그까지 함께 지워 헤더 구조가 깨졌다 — 사용자 메뉴(kevin) 가 사라졌다.
지울 구간의 <div> 짝이 맞는지 먼저 세고 지운다. 문법 검증으로는 이 유형을 못 잡는다 (v0.331 과 같은 교훈) |
| v0.364 | 설정 창을 화면 전체로 넓혔다 — max-width:1000px 로 좁혀 개선의견 한 줄이 접혔다. 설정은 목록을 담는 화면이라 넓어야 한다 |
| v0.364 | 개선의견을 한 줄 목록으로 바꿨다 (BP 와 같은 형태) — 카드로 쌓으면 화면이 넓어도 몇 건 못 본다. 본문이 길면 말줄임으로 끊고 눌러 펼친다 |
| v0.364 | 한 줄에 내용 · 첨부 · 댓글 수 · 작성자 · 날짜 · 공감 · 상태 · 수정/삭제를 담는다. 상태는 그 자리에서 바꾸고, 버튼을 눌러도 펼쳐지지 않게 이벤트를 멈춘다 |
| v0.365 | async is not defined 로 화면이 죽던 버그 수정 — v0.363 에서 async function openFeedback 을 function openFeedback 으로 매칭해 async 만 남았다 (v0.296 과 같은 실수) |
| v0.365 | node --check 가 이 유형을 못 잡는다 — async 뒤에 주석이 오면 다음 function 과 이어져 문법은 통과하지만 실행 시 죽는다. 검증을 통과했는데 화면이 안 뜬 이유다 |
| v0.365 | 검증 도구를 만들었다 (checkjs.py) — 문법 · 고아 async · 태그 짝 · 버전 일치를 함께 본다. 오늘 겪은 세 유형(v0.331 CSS 삭제 · v0.363 태그 삭제 · v0.365 고아 async) 을 모두 잡는다 |
| v0.366 | 좌측 메뉴를 두 그룹으로 나눴다 — 위는 화면 이동(STEP · 고객 · 문의 …), 아래는 도움말 · 접기. 성격이 달라 붙어 있으면 같은 메뉴로 읽힌다 |
| v0.366 | margin-top:auto 를 아래 그룹의 첫 요소로 옮겼다 — 이전에는 접기 버튼에만 있어 도움말이 위 메뉴에 붙어 있었다. 메뉴가 몇 개든 아래 그룹은 항상 바닥에 붙는다 |
| v0.367 | 페이지 번호를 눌러도 아무 일이 없던 버그 수정 — setInquiryPage() 를 호출하는데 정의가 없었다. 오류도 안 나 알아채기 어려웠다 |
| v0.367 | checkbp.py 「죽은 함수 참조」 검사로 찾았다 — node --check 는 통과하고 클릭했을 때 죽는 유형이다 |
| v0.367 | BP 3종 세트 규칙에 맞춰 APP_VERSION 상수를 도입했다 (CRM_VERSION 은 이를 참조). 상수 · 파일명 · 배지가 항상 같은지 검사로 확인된다 |
| v0.367 | 페이지를 옮기면 목록 맨 위로 올린다 — 이전 페이지의 스크롤 위치가 남으면 새 목록의 중간부터 보게 된다 |
| v0.368 | 개선의견 등록을 모달로 바꿨다 (BP 와 같은 형태) — 목록 위에 폼을 항상 두면 그만큼 볼 수 있는 건수가 줄고, 쓰지 않을 때도 자리를 차지한다 |
| v0.368 | 목록 상단에 검색 · 상태 · 등록 버튼을 놓았다. 검색은 본문과 작성자를 함께 본다 — “누가 올린 건지” 로 찾는 일이 잦다 |
| v0.368 | 등록 모달의 z-index 를 설정 창(400) 보다 위(460) 에 둔다. ESC 스택에도 넣어 등록 모달이 먼저 닫힌다 |
| v0.368 | 창이 열려 있으면 바깥 클릭으로 상세 패널이 닫히지 않게 했다 — 모달 안을 누를 때마다 뒤에서 패널이 사라졌다 |
| v0.369 | 좌측 메뉴 펼치기 아래에 버전을 작게 표시한다 — 이전에는 kevin 메뉴를 열어야 보였다. 어느 버전을 보고 있는지 확인할 곳이 필요하다 |
| v0.369 | APP_VERSION 상수를 그대로 쓴다 — 손으로 적으면 3종 세트가 어긋난다. 접었을 때는 9px, 펼치면 10px 로 보인다 |
| v0.370 | 사무소명 칸에서 이름은 왼쪽, 배지(문의 · 활동 · D+n) 는 오른쪽 한 자리에 모았다 — 배지가 이름 길이를 따라다니면 행마다 위치가 달라 세로로 어긋나 보인다 |
| v0.370 | 배지를 칸 끝에 딱 붙이지 않는다 (우측 14px) — 옆 컬럼과 붙으면 어디까지가 이름 칸인지 흐려진다 |
| v0.370 | 사무소명 최소 폭 220 → 200px, 문의내용 130 → 200px, 주소 180 → 230px(고객 190 → 250px) — 마우스를 올려야만 읽히면 목록의 뜻이 없다 |
| v0.371 | 배지 표기를 성장패키지 → 성장 으로 줄였다. 저장값은 그대로 둔다 — 판정 규칙 · 필터 · 집계가 모두 그 값을 쓴다 |
| v0.371 | 마우스를 올리면 전체 이름이 나온다. 고객 목록은 성장패키지를 서비스 자리에 넘기므로 그쪽도 함께 처리했다 |
| v0.372 | 사무소명 칸이 남는 폭을 다 가져가 이름과 배지 사이가 멀어졌다 — 한 줄로 안 읽힌다. 폭을 정해 뒀다 (문의 330px · 고객 290px) |
| v0.372 | 고객 목록은 D+n 이 없어 배지가 짧다 — 문의보다 좁게 잡았다 |
| v0.372 | 남는 폭은 주소가 가져간다 (w:0) — 목록에서 가장 길고 잘리면 아쉬운 값이다 |
| v0.373 | 사무소명 폭을 실측으로 정했다 — 원장 886건 「사무소명 (대표자)」 폭 분포는
50% 137px · 90% 188px · 95% 209px · 최대 248px 이다 |
| v0.373 | 최대에 맞추지 않는다 — 248px 로 잡으면 절반의 행에서 100px 넘게 빈다. 95% 를 담고 나머지는 말줄임한다 |
| v0.373 | 문의 364px (이름 209 + 배지 143 + 여백 12) · 고객 328px (배지 107, D+n 없음). 실측 결과 잘리는 건 43건(4.9%) 이고 마우스를 올리면 전체 이름이 나온다 |
| v0.374 | 고객 상세에서 라벨과 값이 멀어지던 문제 수정 — margin-left:auto 로 값을 칸 끝까지 밀고 있었다. 어느 값이 어느 이름의 것인지 눈이 한 번 더 움직인다 |
| v0.374 | 두 줄 라벨을 한 줄로 — 거래처/위멤버스 → 위멤버스, 거래처/세모 → 세모, 카카오/채널 → 카카오. 라벨 폭을 52 → 58px 로 늘려 접히지 않게 했다 |
| v0.374 | 보고서 · 거래처 두 줄을 4열로 통일했다 — 줄마다 열 수가 다르면 세로로 눈이 흔들린다 |
| v0.374 | 서비스 표에 행 구분선을 넣었다 — 값이 많아 구분이 없으면 어느 줄인지 놓친다 |
| v0.375 | 문자 값을 라벨 바로 옆으로 옮겼다 — 칸 끝으로 밀면 상태 와 정상 사이가 비어 짝이 한눈에 안 읽힌다.숫자는 오른쪽에 그대로 둔다 — 자릿수가 세로로 맞아야 1,447 과 0 을 바로 비교한다 |
| v0.375 | 서비스 표에 현황 라벨을 붙였다 — 표만 왼쪽 끝에서 시작해 다른 줄과 시작선이 어긋나 있었다 |
| v0.375 | 표를 회색 상자로 감쌌다 — 다른 줄은 회색 칸인데 표만 맨바닥이면 같은 영역으로 안 읽힌다 |
| v0.375 | 입력란도 왼쪽 정렬로. 거래처만 숫자라 오른쪽에 둔다 |
| v0.376 | 고객 상세를 C안으로 — 회색 상자를 없애고 밑줄만 남겼다. 한 화면에 상자가 20개 가까이 놓이면 그것만으로 답답해 보인다 |
| v0.376 | 라벨과 값 사이를 5 → 10px — 붙으면 한 낱말처럼 읽히고, 멀면 짝이 안 보인다 |
| v0.376 | 상태 강조를 배경 대신 밑줄 색과 글자색으로 — 상자가 없으니 배경만 남으면 그 칸이 떠 보인다 |
| v0.376 | 서비스 표 규칙이 두 벌로 겹쳐 있었다 (v0.374 추가분 · 원래 것). 뒤엣것이 이겨 v0.374 에서 넣은 구분선이 무효였다 — 원래 규칙에 합쳤다 |
| v0.377 | 사업장 사무소명에 유입코드가 붙어 나오던 문제 수정 (일공삼택스(5개,1명)_260806) — 목록은 _cleanOffice 로 정리하는데 편집 칸만 원본을 보여주고 있었다 |
| v0.377 | 거래처 입력칸을 없애고 신청자 · 연락처 · 이메일을 한 줄로 — 거래처 수는 아래 현황 표에서 서비스별로 보여준다 |
| v0.377 | 현황 표에서 사유를 빼고 전체 · 정상 · 휴폐업 · 정지를 넣었다 — 거래처 수를 아래에 따로 두면 어느 서비스의 수인지 한 번 더 짚어야 한다. 사유는 줄 전체 툴팁으로 옮겼다 |
| v0.377 | 아래 위멤버스 · 세모 두 줄을 삭제했다 (현황 표로 이동). 셋업도 두 줄 → 한 줄 (4열) — 라벨을 실시간 · 자동수집 · 부서사용자 · 신고 로 줄였다 |
| v0.378 | 입력란이 든 칸의 밑줄을 없앴다 (사업장 · 메모) — 입력란에 이미 테두리가 있어 선이 두 겹으로 겹쳐 보였다 |
| v0.378 | :has() 대신 클래스를 직접 붙였다 — 브라우저에 따라 무시되면 밑줄이 그대로 남는다 |
| v0.379 | 보고서 · 부가세 숫자도 라벨 옆으로 — 원장의 상태 정상 과 같은 규칙으로 통일했다. 자릿수를 세로로 비교하는 일은 위쪽 현황 표가 맡는다 — 여기는 낱개 값이라 「어느 이름의 수인가」 가 먼저다 |
| v0.379 | 카카오를 4칸 기준 앞 3칸으로 — 3열이라 다른 줄과 칸 폭이 어긋났다. 빈 칸에는 밑줄을 두지 않는다 (허공에 선이 그어져 보인다) |
| v0.380 | 셋업과 카카오 순서를 바꿨다 — 카카오가 위, 셋업이 아래다 |
| v0.381 | 인사이트 상태 기타 를 뜻이 드러나는 말로 바꿨다 — 원장 실측 797건 중 794건이 가입일자조차 없다(쓴 적 없음). 나머지 3건은 해지일이 있다 |
| v0.381 | 해지일 있음 → 해지 · 없음 → 미이용. 날짜를 오늘과 비교하지 않는다 — 해지 예약 2건이 시간이 지나며 다르게 보인다 |
| v0.381 | 원장 값은 고치지 않는다 — 다음 파일 업로드가 덮어쓴다. 표시만 바꾼다. 미이용 은 링크패스와 같은 회색으로 나온다 |
| v0.382 | 한 사업자에 계정이 여럿이면 사무소명 옆에 이용기관코드를 붙인다 — 실측 886개 사업자 중 12곳이 복수다 (2개 10곳 · 3개 2곳) |
| v0.382 | 하나뿐인 곳에는 붙이지 않는다 — 900건 중 874건이 그러하고, 모두에 붙이면 정작 봐야 할 12곳이 묻힌다 |
| v0.382 | 세무법인진명은 이름이 셋 다 같다 — 코드 없이는 구분할 방법이 없다. 코드는 줄이지 않는다 — 자르면 다른 자료와 대조할 때 다시 찾아야 한다 |
| v0.382 | 고객 목록 사무소명 폭 328 → 400px — 코드 18자가 약 120px 을 쓴다 |
| v0.383 | v0.382 의 목록 변경을 되돌렸다 — 이용기관코드는 고객 상세의 사무소명과 대표자 사이에 둔다. 목록에서는 자리를 많이 쓰고, 구분이 필요한 순간은 상세를 열었을 때다 |
| v0.383 | 복수 계정일 때만 칸이 생긴다 — 1fr auto 1fr. 하나뿐이면 기존과 똑같이 두 칸이다 |
| v0.384 | 배지를 이름 바로 뒤에 붙이되 최소 188px 자리를 지키게 했다 — 실측 886건 중 797건(90%) 이 그 안에 들어 배지가 세로로 맞고, 89건만 뒤로 밀린다 |
| v0.384 | 칸 끝으로 밀면 이름과 멀어지고, 아예 붙이면 행마다 위치가 달라 어지럽다. 둘 사이를 잡았다 |
| v0.384 | 이름 자리가 209 → 188px 로 줄어 컬럼도 좁아진다 — 문의 364 → 343px · 고객 328 → 307px. 남는 폭은 주소가 가져간다 |
| v0.385 | 메모를 이력으로 바꿨다 (crm_notes) — 지금까지는 stage_memo 한 칸에 덮어써서 누가 언제 무엇을 적었는지 남지 않고, 나중에 적은 사람이 앞의 내용을 지웠다 |
| v0.385 | 사업자 단위로 쌓는다 — 한 사업자에 계정이 여럿이어도(지점 · 재가입) 방문 기록은 그 사무소 전체의 것이다. 계정마다 나뉘면 흩어져 못 찾는다 |
| v0.385 | 누구나 남의 메모를 고칠 수 있다 — 오탈자나 잘못된 정보를 발견한 사람이 바로 고치는 편이 낫다.
다만 고친 사실은 crm_note_edits 에 남고 화면에 수정됨 배지가 붙는다 — 확인할 방법이 없으면 아무도 메모를 믿지 않게 된다 |
| v0.385 | 입력칸이 내용에 따라 늘어난다 (최대 260px) — 스크롤 대신 늘리는 편이 전체를 보기 쉽다. Ctrl+Enter 로 등록한다 — 여러 줄을 적는 칸이라 Enter 는 줄바꿈이어야 한다 |
| v0.385 | 삭제는 is_deleted 를 세운다 — 잘못 지웠을 때 되살릴 방법이 있어야 한다. 메모는 맨 아래로 옮겼다 |
| v0.386 | 메모 입력칸을 한 줄로. 오른쪽에 등록 버튼을 두고 Ctrl+Enter 안내 문구는 없앴다 — 메모는 대개 한 문장이라 여러 줄 칸을 늘 펼쳐두면 자리만 차지한다. 길게 적으면 그때 늘어난다 |
| v0.386 | 입력칸을 상자 없이 밑줄만으로 — 아래 목록이 밑줄이라 성격을 맞춘다. 상자를 두면 입력칸만 도드라져 목록과 따로 노는 것처럼 보인다 |
| v0.386 | 메모 내용도 한 줄. 길면 말줄임하고 마우스로 전체를 본다 |
| v0.386 | 수정 · 삭제 는 그 줄에 마우스를 올렸을 때만 나온다 — 늘 보이면 메모마다 버튼이 둘씩 붙어 내용보다 눈에 먼저 든다 |
| v0.387 | 메모 한 건을 한 줄에 담았다 — 두 줄로 나누면 다섯 개만 있어도 열 줄이 되어 훑기 어렵다 |
| v0.387 | 내용이 먼저다 — 목록을 훑을 때 찾는 것은 내용이지 날짜가 아니다. 일시 · 작성자는 뒤에 둔다 |
| v0.387 | 마우스를 올리면 일시 · 작성자 자리를 버튼이 덮는다 — 버튼을 위해 자리를 따로 비워 두면 그만큼 내용이 좁아진다 |
| v0.387 | 메모 라벨과 입력줄 높이를 맞췄다 (padding-top 8 → 5px · 위 여백 제거) |
| v0.388 | 일시를 한국 시각으로 바꿨다 — 저장은 UTC(timestamptz) 인데 문자열을 잘라 그대로 보여주고 있었다. 11:09 에 적은 메모가 02:09 로 보였다 |
| v0.388 | 여섯 곳이 모두 같은 방식이었다 — 메모 · 메모 수정 · 개선의견 · 업로드 · 최근 접속 · 히스토리. _kst() 한 곳으로 모았다 |
| v0.388 | 날짜만 쓰는 곳도 고쳤다 (_kstD()) — 시각이 없어도 UTC 자정 근처에서는 하루가 밀린다. 한국 09시 이전에 저장된 건이 전날로 보인다 |
| v0.389 | 확인창을 화면 중앙에 띄운다 — 브라우저 confirm 은 창 맨 위에 떠서 보던 자리에서 눈이 멀리 움직이고, 브라우저마다 생김새가 달라 우리 화면과 따로 논다 |
| v0.389 | confirm 을 쓰던 11곳을 모두 바꿨다 — 한 곳만 바꾸면 화면마다 다른 창이 뜬다. deleteNote · deleteTeam · removeMember 세 곳은 async 가 아니라 함께 붙였다 |
| v0.389 | Promise 로 돌려줘 if (!await ask(…)) return; 한 줄로 쓴다. 지우는 동작은 붉은 버튼으로 구분하고 확인 대신 삭제 · 반영 처럼 할 일을 적는다 |
| v0.390 | 고객 상세 연락처가 비어 보이던 문제 수정 — main_phone(대표전화) 만 보고 있었다. 실측 900건 중 674건(75%) 이 휴대폰만 있어 빈칸으로 보였다 |
| v0.390 | 대표자휴대폰을 먼저 본다 — 대표전화만 있는 경우는 0건이라 휴대폰이 우선이다 |
| v0.391 | 담당자를 여러 명 관리한다 (crm_contacts) — 원장에 대표자 한 명, 문의에 신청자 한 명뿐이라 한 사무소에 세무사가 여럿이고 실무 담당자도 따로 있는데 담을 곳이 없었다 |
| v0.391 | 구분 3종 — 신청자 · 세무사 · 담당자. 이름 · 핸드폰 · 이메일 · 메모를 적고 별표로 먼저 연락할 사람을 표시한다. 별표는 여럿 가능하고, 목록에는 세무사를 먼저 쓴다 — 연락은 대개 그쪽부터 한다 |
| v0.391 | 사업장에 대표전화 칸을 넣었다. 신청자 · 연락처 · 이메일은 담당자 표로 옮겼다 — 한 사무소에 사람이 여럿이라 한 칸으로는 담기지 않는다 |
| v0.391 | 기존 값을 옮긴다 (SQL 208 · 209) — 원장 대표자 → 세무사 · 별표, 문의 신청자 → 신청자. 처음부터 비어 있으면 아무도 채우지 않는다. 대표자와 같은 이름은 넣지 않는다 — 한 사람이 두 줄로 보인다 |
| v0.391 | 칸을 벗어날 때 저장한다 — 한 글자마다 보내면 요청이 쏟아진다. 삭제는 is_deleted 를 세운다 |
| v0.392 | 한 사업자에 계정이 여럿이면 몇 번째인지 적는다 — 세무법인송촌 (김명선) 2. 세무법인진명처럼 이름과 대표자가 같으면 목록에서 구분할 방법이 없다 |
| v0.392 | 번호는 가입일 순이다 — 처음 가입한 곳이 1번. 배열 순서(정상 > 정지 > 해지) 와 다르다. 그 순서는 「어느 것을 대표로 볼까」 이고 번호는 「몇 번째로 만든 계정인가」 라 기준이 다르다 |
| v0.392 | 지점 선택 버튼에도 번호와 대표자를 붙였다 — 이름이 같으면 상태만으로는 구분이 어렵다. 마우스를 올리면 이용기관코드와 가입일이 나온다 |
| v0.393 | 목록에서는 번호를 빼고 상세에서만 보여준다 — 목록은 대표 1건만 나오는 자리라 「3번째 계정」 이 「계정 3개」 로 읽힌다 |
| v0.394 | 목록에 이용기관 개수를 적는다 — 세무법인송촌 (김명선) 3. 몇 번째가 아니라 몇 개인가다.
대표 1건만 보이는 자리이므로 알아야 할 것은 「다른 계정이 더 있나」 이고, 몇 번째인지는 상세의 지점 버튼에 붙는다 |
| v0.395 | + 담당자 버튼을 표 머리 오른쪽으로 옮겼다 — 표 아래에 두면 그만큼 줄이 늘고, 담당자가 없을 때는 버튼이 홀로 떠 보인다 |
| v0.396 | 가입 이력이 없는 고객도 같은 화면을 쓴다 — 담당자 표와 메모를 붙였다. 원장에서 오는 현황만 빠진다 |
| v0.396 | 담당자와 메모는 가입 전에 더 필요하다 — 누구를 만났고 무슨 얘기를 했는지가 영업의 내용이다. 그런데 그 자리가 비어 있었다 |
| v0.396 | SQL 211 — 미가입 사업자의 신청자를 담당자로 넣는다. 원장이 없으면 그 사람이 유일한 연락처라 별표를 붙인다 |
| v0.397 | 기획서에 v0.384~v0.396 반영 — 확정 항목 34~37 추가(담당자 여러 명 · 메모는 쌓는다 · 일시는 한국 시각 · 확인창은 화면 중앙) |
| v0.397 | 10번에 담당자와 메모 절 신설 — 구분 3종과 실측(세무사 886 · 신청자 393), 별표 규칙, 가입 전에 더 필요한 이유. 메모는 왜 덮어쓰면 안 되는가를 다섯 규칙으로 |
| v0.397 | 4번에 사람 · 기록 계층 추가 — crm_contacts · crm_notes · crm_note_edits. 모두 사업자 단위인 이유를 적었다 |
| v0.397 | 8번 미확정 표를 다시 썼다 — 완료된 항목이 섞여 있었다. 남은 12건을 우선순위로 정리했다 (Must 3 · Should 4 · 2차 5) |
| v0.398 | 담당자 블록 위아래 여백을 같게 하고, 현황 · 담당자 표 머리 위에도 선을 넣었다 — 위에 선이 없으면 앞 줄과 붙어 어디서 표가 시작하는지 흐려진다 |
| v0.398 | 문의 상세 주소에 복사 · 공유를 붙였다 — 고객 탭에는 있었는데 문의 탭에만 없었다. 방문 전에 지도 앱으로 옮기는 일이 잦다 |
| v0.398 | 휴지통 되돌리기 가 두 줄로 접히던 문제 — 열 폭이 60px 이라 4자가 들어가지 않았다. 74px 로 넓혔다 |
| v0.398 | 메모에 첨부를 붙였다 (SQL 217) — 방문 사진이나 받아온 자료를 남긴다. 개선의견과 같은 버킷 · 같은 경로 규칙을 쓴다 (menu-files · crm/) |
| v0.398 | SQL 215 · 216 — Storage 업로드 권한. 버킷이 public 이라도 쓰기는 별개다.
crm/ 경로만 열어 CRM 에서 BP 첨부를 지울 수 없게 한다 |
| v0.399 | 현황 · 담당자 표 아래에도 선을 넣었다 — 위만 있으면 어디서 끝나는지 흐려지고 다음 줄(보고서) 과 붙어 표의 일부처럼 읽힌다 |
| v0.400 | 미리보기를 잘렸을 때만 보여준다 — 다 보이는데 뜨면 읽는 것을 가려 방해만 된다. scrollWidth > clientWidth 로 판정한다 |
| v0.400 | 사무소명도 같게 고쳤다 — 브라우저 title 은 늘 뜬다. 마우스가 들어올 때 판정해 잘렸을 때만 붙인다 |
| v0.401 | 컨설팅 필터 줄 첫 버튼을 전체 → 컨설팅 으로 — 전체 라고 하면 잠재까지 포함하는 것처럼 읽힌다. 실제로는 컨설팅에서 진행 중인 건만 센다 |
.limit(3000) 으로는 넘지 못한다. 서버 max-rows 설정에 마혀 잔리는데 에러가 안 나기 때문에 드러나지 않는다.49 + 54 + 0 + 11 + 886 = 1,000 이라는 우연한 합계를 보고서야 알아처렸다. 588건이 버려지고 있었다.| 방법 | 통계 |
|---|---|
| 대시보드에서 제한 상향 | 권하지 않음. 문제를 미룰 뿐이고 데이터가 늘면 다시 잔린다. 그때는 원인 찾기가 더 어렵다 |
.range() 페이지네이션 | 채택. 1,000행씩 나눠 받아 합치다. 서버 설정 의존이 없고 1,588건이면 요국 2번이라 부담도 없다 |
| 새로 다 받지 않기 | 데이터가 5,000건을 넘으면 필요. 컬럼별 limit 50 + 건수는 count head 로 분리 |
| 파일 | 내용 |
|---|---|
| v0.061 | step_group · step_detail · 가능성 · 위험도 · 다음액션 컴럼 추가. crm_stage_history 생성 |
| v0.062 | crm_inquiries_step_backup — 이관 전 1,588건 스냅샷 |
| v0.063 | 신규 단계 체계로 이관 |
| v0.067 | 담당자 분리 — Flow 담당자를 flow_assignee 로 이동, assignee 는 CRM 배정 전용 |
| v0.068~069 | crm_settings 생성. 위험 기준 2개로 단순화 |
| v0.065 | 기존 step 컴럼 제거 — 실행 완료. 값은 백업 테이블에 보존 |
| 그룹 | 세부 단계 | 건수 | 비고 |
|---|---|---|---|
| 문의 | 담당자배정 | 48 | 헤나 일괄 배정 |
| 신규접수 | 2 | 2026-07 이후 등록 | |
| 컨설팅 | 대기 | 63 | 중 57건 판정보류 |
| 온보딩 | 대기 | 11 | 최근 3개월 가입 |
| 활성화 | 정상 | 1,464 | 전량 이관분 |
migrated_at 을 찍어 온보딩 전환율 계산에서 제외한다. 이걸 안 하면 평균 소요일 같은 지표가 의미를 잃는다.| 항목 | 이전 | 이후 | 내용 |
|---|---|---|---|
crm_inquiries | 1,588 | 1,652 | +101 INSERT · −37 is_deleted |
crm_inquiry_activities | 58 | 59 | +7 INSERT · −6 DELETE · 26건 유형 재분류 |
| 링크패스 문의 | 16 | 72 | Link Path 도입문의(구 표기) 56건 복구 |
| 성장패키지 | 0 | 10 | 문의 4 · 요금변경 6 |
biz_no 공백 | 757 | 0 | 하이픈 없는 10자리 파싱 추가 |
| 미사용 컬럼 | plan · plan_promo | 제거 | 실측 0건 · inquiry_promo 와 개념 중복 |
Link Path 도입문의(2024-09~2025-01) 가 링크패스 도입문의(2025-02~) 로 바뀐 것을 이전 이관이 반영하지 못해 56건이 통째로 빠져 있었다. 링크패스 문의가 16건으로 보였던 이유다.세모리포트 신청 → 세모R 신청, 인사이트 신청 → 세모R 플러스 신청 에도 있다. 제목을 판정 키로 쓰면 안 되는 이유이며, 9-C 의 본문 필드 기반 규칙이 이를 해결한다.address 43/101 · email 61/101 · 거래처수 28/101 만 채워졌다. 좌표가 없어 MAP 탭에서 빠진다. biz_no 로 crm_prospects 와 매칭해 주소 · 좌표를 보완해야 한다. 8번 미확정 #12(문의 양식 주소 필수화) 와 같은 원인이다.기존 앱 입력값 6종에 Flow 파생 4종을 더한 합집합. 제목 키워드로 자동 분류한다. 위에서 아래로 먼저 매칭한다.
| 유형 | 건수 | 키워드 |
|---|---|---|
| 촬영 | 1 | 촬영 |
| 문자 | 6 | 문자 |
| 이메일 | 0 | 메일 |
| 방문 | 19 | 방문 — 목적어보다 우선 (kevin 확정) |
| 컨설팅 | 11 | 컨설팅 · 셋업 · 교육 · 설명 · 시연 |
| 상담 | 1 | 상담 · 협의 · 문의 |
| 요금/정산 | 2 | 요금 · 면제 · 선결제 · 프로모션 · 세금계산서 · 견적 |
| 가입/해지 | 1 | 가입 · 해지 · 정지 · 활성화 |
| 통화 | 18 | 통화 · 전화 · 접촉 |
| 기타 | 0 | 위 어느 것도 아님 |
방문 컨설팅 · 컨설팅 방문 진행 처럼 목적과 방문이 함께 있는 건이 8건 있었다. 방문 우선으로 확정했다. 목적은 activity_note 에 원문이 남는다.촬영 만 방문보다 위에 둔다 — 1건이고 성격이 명확히 다르다.console.warn 으로 둥치면 권한 문제와 “데이터 없음”을 구분할 수 없다node --check — 인라인 script 블록을 추출해 문법 검증<button> 은 font-size 를 명시한다 — 및로우젌 기본값(Chrome 13.33px)이 상속을 가로말아 나란한 div 와 크기가 어긋난다calc(100vh - N) 대신 flex 로 — 헤더 높이가 바뀌면 어긋나며, 넘친 부분이 부모의 overflow:hidden 에 잔려 스톤론도 안 된다<title> · CRM_VERSION · 파일명 · 문법검증kevin 확정이 필요한 항목. 확정된 건은 해당 섹션에 반영 완료.
| # | 항목 | 확정 내용 | 반영 |
|---|---|---|---|
| 1 | 실패 · 휴폐업 위치 | 별도 상태축. 실패 = 문의 후 3개월 경과 자동 판정, 휴폐업 = 고객정보 업로드로 반영 | 2번 |
| 2 | 단계 관리 단위 | 고객 단위. 단 고객 상세에 STEP 기반 상품별 단계 현황 제공 (GD003 B8 참조) | 2번 |
| 4 | 중복 판정 키 | 등록일 + 상호명. 상위업무 있는 행은 신규 문의가 아닌 활동 이력으로 처리 | 6번 |
| 3 | Flow 유형 매핑 | 제목이 아니라 본문 필드로 판정. 템플릿 2종 · 행종류 7단계 · 접수구분 3종 · 문의서비스 7단계 규칙 확정. 실측 1,739행 정확도 99.94% | 9-C |
| 13 | 문의서비스 ≠ 현재 이용 서비스 | 고객당 현재 이용 서비스는 1개지만 문의는 여러 서비스로 발생한다. 필드를 분리하고 문의는 접수시점 기준으로 표시한다. 정확한 요금제는 고객원장(가입고객현황)에서만 관리 | 3번 |
| 14 | 성장패키지 위치 | 별도 서비스가 아니라 세모R+ 요금제 프로모션. inquiry_promo 속성으로 처리 | 9-C |
| 15 | 활동 이력 분리 | 상위업무 有 → crm_inquiry_activities 에 일자 · 활동내역 · 담당자로 기록. 서비스 · 사업자번호는 부모 상속 | 9-C |
| 16 | 동기화 원칙 | export = 정답. 없는 건은 is_deleted = true (물리 삭제 금지). 문의 → 활동 순서 준수 | 6번 |
| 17 | 활동유형 10종 | 기존 6종 + Flow 파생 4종. 방문이 목적어보다 우선 | 7번 |
| 18 | inquiry_type 위상 | 레거시. 신규 · 재가입 구간이 서비스와 무관하게 항상 세모R+ 로 찍혀 780건이 잘못돼 있다. 서비스 판단에는 inquiry_service 를 쓴다 | 9-D |
| 20 | _x000D_ 제거 규칙 | 로더가 아니라 DB 트리거로 처리. crm_strip_x000d() 를 두 테이블에 BEFORE INSERT OR UPDATE 로 등록해 연동 방식과 무관하게 유지 | 6번 |
| 37 | 확인창은 화면 중앙 | 브라우저 confirm 은 창 맨 위에 떠서 보던 자리에서 눈이 멀리 움직인다.
11곳을 모두 바꿨다 — 한 곳만 바꾸면 화면마다 다른 창이 뜬다. 버튼에 할 일을 적는다 (확인 이 아니라 삭제 · 반영) | 10번 |
| 36 | 일시는 한국 시각 | 저장은 UTC(timestamptz) 다. 문자열을 자르면 9시간 어긋난다 —
11:09 에 적은 메모가 02:09 로 보였다. 날짜만 쓰는 곳도 자정 근처에서 하루가 밀린다 | 10번 |
| 35 | 메모는 쌓는다 | 한 칸에 덮어쓰면 나중에 적은 사람이 앞의 내용을 지운다. 사업자 단위로 쌓고, 누구나 고칠 수 있되 고친 사실은 남긴다 — 확인할 방법이 없으면 아무도 메모를 믿지 않게 된다 | 10번 |
| 34 | 담당자는 여러 명 | 한 사무소에 세무사가 여럿이고 실무 담당자도 따로 있다. 구분 3종(신청자 · 세무사 · 담당자) 에 별표로 먼저 연락할 사람을 표시한다. 사업자 단위다 — 계정마다 나뉘면 같은 사람을 두 번 적게 된다 | 10번 |
| 33 | 목록 컬럼은 사용자별 | 컬럼 구성 · 순서 · 정렬을 사람마다 뷰마다 저장한다 (crm_list_prefs) —
영업 담당자는 연락처와 주소를, 관리자는 담당자와 단계를 본다. 한 벌로 맞추면 누군가는 늘 필요 없는 컬럼을 본다 | 10번 |
| 32 | 서비스 배지 3종 | 세모R · 세모R+ · 성장패키지만 보여준다 — 위멤버스는 900건 전부라 구분이 안 되고, 링크패스는 플러스 이용 시 무료 제공이라 요금제 컬럼과 같은 말을 두 번 한다. 배지가 늘면 정작 볼 것이 묻힌다 | 10번 |
| 31 | 실패 는 대단계 | DB 에 step_group = 실패 384건이 있고 칸반에도 컬럼이 있다.
화면에서는 컨설팅 하위로 보여준다 — 컨설팅에서 끝난 건이라 별개 흐름처럼 보이면 안 된다.
고르면 컨설팅 탭으로 간다 — 문의 탭에는 그 목록이 없다 | 2번 |
| 30 | 문의는 컨설팅 대기 | 담당자 배정 전이라 성격이 같다. 컨설팅 화면에서 바로 배정하고 처리할 수 있어야 한다. 컨설팅 건수는 진행 건만 센다 — 결말까지 세면 처리할 일이 몇 건인지 알 수 없다 (167건이 보이는데 손댈 게 없었다). 같은 이유로 활성화 건수는 위험 있음을 쓴다 | 2번 |
| 29 | 실패는 방문 대기열 | 실패 는 결과 기록이 아니라 나중에 방문할 대상이다. 그래서 미가입만 남아야 한다.
고객원장이 갱신되면 실패 건 중 가입이 확인된 것은 문의종료 로 자동 전환한다 —
담당자가 매번 원장을 대조할 수는 없고, 이미 가입한 곳이 섞이면 헛걸음이 된다. 반대 방향은 없다 | 2번 |
| 28 | 고객원장 신설 | crm_customers — 세무사무소목록 엑셀 93컬럼 중 33개 항목을 담는다. 키는 이용기관아이디 다. 사업자번호는 886개(중복 12) 인데 이용기관아이디는 900개 전부 고유하다 — 한 사업자에 지점 · 팀 분리와 재가입이 붙는다 | 4번 |
| 27 | 고객원장 기준 단계 판정 | 서비스별 가입 여부 + 가입일과 문의일의 앞뒤로 단계를 정한다. 같은 날 가입은 전환 성공이다 — 시각까지 비교하면 문의 후 당일 가입이 “이미 고객” 으로 잘못 잡힌다. 2026-08-11 실행 (실패 511 · 해지 421 · 활성화 400 · 정지 234 · 신규 40 · 온보딩 36 · 문의 17) | 2번 |
| 26 | 컨설팅 세부단계 7종 | 대기 · 접촉 · 접촉실패 · 컨설팅예약 · 예정 · 완료 · 실패. 저장값에 공백을 넣지 않는다 — 비교 · 필터에서 실수가 생긴다. 가능성(높음 · 보통 · 낮음) 은 possibility 에 별개 축으로 담는다 | 2번 |
| 25 | 잠재 4종 정의 | 위멤 · 해지 · DB · 기타. 모집단을 복제하지 않는다 — 원본에서 그때그때 계산하고, 담당자를 배정하면 문의를 만들어 crm_stage 를 채워 목록에서 빠지게 한다 (기획서 6번 구조 재사용) | 6번 |
| 24 | 위험 판정 대상 | 현재 이용 중인 고객(원장 status = 정상) 이다. 문의 단계 활성화 가 아니다 — 활성화는 “문의가 전환된 건” 이고 위험 관리는 “지금 쓰고 있는 고객” 을 본다 | 10번 |
| 23 | 위멤버스 상태 미확정 | 원장의 status 는 세모R 기준이라 위멤버스 상태로 쓸 수 없다. 상품명이 있다는 사실만 이용 으로 표시한다. 위멤버스 DB 를 받으면 그 자료로 정의한다 | 3번 |
| 22 | 단계 판정 규칙 | 접수구분 + 담당자 유무로 결정. 요금변경 → 활성화/정상 · 담당자 있음 → 컨설팅/대기 · 그 외 → 문의/신규접수. 가입 여부는 고객 데이터로만 판정하므로 접수 기록이 활성화를 주장하지 않는다. 2026-08-11 전면 재계산 (1,599 · 47 · 6) | 2번 |
| 21 | 담당자 이원화 | Flow 담당자는 임시담당자. flow_assignee 에만 저장하고 CRM 담당자(assignee) 와 매핑하지 않는다. 성격이 다른 값이라 섞으면 배정 현황이 왜곡된다 | 3번 |
| 19 | plan · plan_promo 제거 | 실측 0건 미사용. 요금제는 고객원장에서만 관리하는 원칙과 중복 | 3번 |
| # | 항목 | 내용 | 우선 |
|---|---|---|---|
| 4 | 채널 정의 | 회사 아래 채널이 무엇인지 정해지지 않아 헤더 필터가 비어 있다. 유입 경로인지 영업 조직인지에 따라 값이 달라진다 | Must |
| 13 | 로그인 전환 | DEV_MODE 해제 + anon 권한 회수. 되돌릴 SQL 87 · 96 · 97 · 139 준비됨.
지금은 누구나 모든 데이터를 읽고 쓸 수 있다 — 외부 호스팅 전에 반드시 | Must |
| 14 | 위멤버스 DB | 받으면 위멤버스 상태를 정의하고 잠재-위멤 496건을 다시 계산한다. 지금은 상품명이 있다는 사실만 이용 으로 표시한다 | Must |
| 15 | 정산 Data | 자동이체 · 카드. 매출과 미납을 보려면 필요하다 | Should |
| 16 | 상담 Data | 좌측 상담 탭이 비어 있다. 어떤 자료가 오는지에 따라 화면이 정해진다 | Should |
| 7 | Flow Webhook | 문의 자동 동기화. 실시간 Webhook 인지 주기 배치인지 | Should |
| 12 | 문의 양식 주소 필수화 | 주소 없는 145건은 어떤 방법으로도 좌표를 구할 수 없다. Flow 양식을 고쳐야 한다 | Should |
| 17 | 관리자 · 감사로그 | 설정 탭이 비어 있다. 로그인 전환 후에 의미가 생긴다 | 2차 |
| 18 | Supabase 반환값 6곳 | insert 결과를 받지 않아 활동 기록 · 단계 이력이 실패해도 모른다. 기록성이면 주석으로 면제, 아니면 error 확인 | 2차 |
| 19 | 죽은 선택자 24개 | 제거된 화면의 잔재. ?. 로 막혀 오류는 없지만 새로 생긴 것과 구분되지 않는다 | 2차 |
| 20 | 개선의견 첨부 | 업로드를 아직 시험하지 않았다. anon 으로 Storage 쓰기가 막혀 있을 수 있다 | 2차 |
| 21 | 담당자 없는 17곳 | 문의에 신청자 이름이 비어 있어 넣을 값이 없다. 방문 때 손으로 적는다 | 2차 |
crm_inquiries에는 사업자번호 · 대표자명 · 휴대폰 · 이메일이 포함된다. v0.269 현재 anon 에 읽기와 쓰기가 모두 열려 있고 anon 키는 HTML 에 평문 노출된다. 키를 가진 누구나 고객 데이터를 조회 · 수정할 수 있는 상태다.DEV_MODE 기본값을 false 로 ② SQL 87(문의 쓰기 회수) · 96 · 97(anon 읽기 정책 제거) 실행 ③ SQL 93~95(로움 도메인 RLS) 적용.auth.users 에 이미 존재하므로 CRM 에도 그대로 로그인된다. 외부 도메인 계정이 있으면 93~95 가 반드시 필요하다.해석이 갈릴 수 있어 합의가 필요한 항목. 담당자가 바뀌거나 외부 개발자가 합류할 때 혼선을 막기 위해 기록한다.
| 사용 위치 | 범위 | 권장 명칭 |
|---|---|---|
| 1차 분류 하위 (2차) | 문의 + 접촉을 묶은 그룹 | 상담 또는 영업중 |
| 3차 세부단계 | 접수만 되고 접촉 전 | 문의 (유지) |
| 상단 탭 메뉴 | Flow 연동 데이터 목록 전체 | 문의내역 |
| # | 항목 | 정의가 필요한 이유 |
|---|---|---|
| D1 | 경쟁사 | 현재 책갈피에 칩은 있으나 새 체계에 위치가 없다. 경쟁사 제품을 쓰는 사무소를 뜻하는지, 경쟁 업체 자체를 뜻하는지 불분명 |
| D2 | 실패 3개월 기산점 해결 | v0.259 보강 — 기산 단위는 사업자번호 + 문의서비스. 재문의 시 그 일자부터 단계가 문의로 재시작하며 이전 건은 닫지 않는다 |
| D3 | 실패 후 재문의 해결 | D2 확정으로 자동 해소. 마지막 문의일이 갱신되므로 별도 부활 로직 불필요 |
| D4 | 대표 단계 선정 해결 | 링크패스가 세모R+ 종속 부가 서비스로 재분류되어 단계를 갖지 않는다. 대표 단계는 세모R · 세모R+ 두 기본 상품만 보고 산출 |
| D5 | 위멤버스 팀 범위 | 서비스는 참조만 하는 것으로 확정. 다만 위멤버스 팀이 조직상 무엇을 담당하는지는 여전히 미정 — 5번 섹션 팀 구분과 연결 |
| D6 | 외부 팀 범위 | 외부 팀이 누구인지(대리점 · 파트너). 데이터 공개 범위가 이것으로 결정된다 |
| D7 | 잠재 재진입 | 해지 고객을 다시 잠재로 보낼지, 해지 상태로 유지할지 |
| D9 | 가입 고객의 문의 표시 | 가입 고객이 새 문의를 하면 문의 목록에 나타나되 단계는 가입을 유지한다. 목록에서 이 건을 어떤 단계 배지로 표시할지 미정 — 가입인지, 문의인지, 둘 다인지 |
| D10 | 활동 기록의 출처 | 확정 (v0.240) — 양쪽 모두 포함한다. Flow 하위 태스크는 f_task_no 로, CRM 내부 입력은 f_task_no = NULL 로 구분된다. 실측 59건 전부 Flow 하위 태스크이며 stage_group 으로 문의 · 온보딩 · 활성화를 나눈다 |
| D8 | 사무소 통합 · 분리 | 세무법인 합병 · 지점 분리 시 잠재 · 문의 · 고객 이력을 어떻게 승계할지 |
제목 [유형] 은 시기에 따라 표기가 바뀌어 판정 키로 쓸 수 없다. 본문 필드가 판정 기준이다. 실측 1,739행 기준 정확도 99.94%.
상호명 · 사업자번호 · 대표자명 · 이메일 · 위멤버스 수임처 거래처수 · 마케팅 동의여부 · 요금제(선택)■ 신청내용 블록의 신청 · 세무사무소명 · 유입경로 · 유입코드 + ■ 가입내역 블록의 세모R · 인사이트 · 위멤버스 · 링크패스 상태
같은 상품인데 표기가 바뀐 사례. 기간이 겹치지 않아 동일 상품으로 확정했다.
| 구 표기 | 신 표기 | 전환 | 상품 |
|---|---|---|---|
| 세모리포트 신청 (23.06~25.01) | 세모R 신청 (24.09~26.07) | 25.02 | 세모R |
| Link Path 도입문의 (24.09~25.01) | 링크패스 도입문의 (25.02~26.04) | 25.02 | 링크패스 |
| 인사이트 신청 · 세모R & 인사이트 신청 (25.10~26.03) | 세모R 플러스 신청 (26.03~26.08) | 26.03 | 세모R+ |
| # | 조건 | 결과 | 건수 |
|---|---|---|---|
| 1 | 제목이 [공지] · [정책] | 삭제 | - |
| 2 | 상위업무 有 & 부모가 [공지] · [정책] | 삭제 | 5 |
| 3 | 상위업무 有 | 활동 | 59 |
| 4 | 상위업무 無 & 제목에 대괄호 無 | 삭제 | 4 |
| 5 | 사업자번호 추출 실패 | 삭제 | 17 |
| 6 | 부모가 삭제됨 (연쇄) | 삭제 | 2 |
| 7 | 나머지 | 문의 | 1,652 |
상위업무 필드에 값이 있으면 부모 문의의 부가 활동이다. crm_inquiry_activities 에 일자 · 활동내역 · 담당자로 기록하고, 서비스 · 사업자번호는 부모에서 상속한다.상위업무 에는 업무번호가 아니라 부모 제목 문자열이 들어온다. f_task_no 로 매칭할 수 없다. 공백 제거 정규화 후 매칭하며 실측 제목 충돌 0건, 연결률 59/59.| 조건 | 접수구분 | 건수 |
|---|---|---|
내용 신청 유형=요금제변경 | 변경 전 요금제 有 | 제목에 요금변경 | 요금변경 | 6 |
제목 유형 [신규가입] · [재가입] (템플릿 A) | 신청(가입) | 791 |
| 나머지 (템플릿 B) | 문의 | 855 |
| # | 조건 | 문의서비스 | 프로모션 |
|---|---|---|---|
| 1 | 제목에 링크패스 | Link Path | 링크패스 | - |
| 2 | 내용 관심 솔루션 = 위멤버스 (단독) | 위멤버스 | - |
| 3 | 내용에 성장패키지 | 신청값에 190만원 | 유입코드에 NEW190 | 제목에 개업성장패키지 | 세모R+ | 성장패키지 |
| 4 | 신청 · 요금제 값에 인사이트 | 플러스 | 세모R+ | - |
| 5 | 신청 · 요금제 값 존재 (세모리포트 · 세모리포트 베이직) | 세모R | - |
| 6 | 제목에 인사이트 | 플러스 (본문 필드 없을 때 폴백) | 세모R+ | - |
| 7 | 나머지 | 세모R | - |
■ 가입내역 에 성장패키지라는 요금제 값이 존재하지 않는다. 요금변경 후에도 세모R : 정상 (231113, 플러스, 115개) 로 플러스다. 즉 플러스 요금제 + 190만원 선결제 + 2년 면제 과금 프로모션이다.inquiry_promo 속성으로 처리한다.성장패키지 문자열은 내용에 0건, 제목에만 개업성장패키지 로 존재한다. 내용 쪽 마커는 신청 : 190만원 요금제(2년한정) 와 유입코드 : TAX_SEMO_NEW190* 두 개다.promo=null 인 변경 이벤트로 처리된다.플러스로 먼저 가입한 뒤 요금제를 변경한다. 칠도세무회계는 같은 날 4시간 간격으로 두 태스크가 등록됐다.
| 시각 | 태스크 | 가입내역 세모R |
|---|---|---|
| 26.07.31 11:46 | [세모R 플러스 신청] | 정상 (231113, 스페셜요금제, 113개) |
| 26.07.31 15:51 | [개업성장패키지_요금변경] | 정상 (231113, 플러스, 115개) |
신청값 · 유입코드)만으로 잡히므로 코드 수정 없이 넘어간다.라벨 라인은 세무사무소명 · 상호명 · 사업자번호 · 사업장명 · 사업자등록번호.
| # | 규칙 | 건수 | 예 |
|---|---|---|---|
| 1 | 라벨 라인의 000-00-00000 | 1,156 | 세무사무소명 : 세무법인 황산 / 775-86-01811 |
| 2 | 라벨 라인의 10자리 숫자 → 하이픈 삽입 정규화 | 497 | 세무사무소명 : 김정환 세무회계/2152206758 → 215-22-06758 |
| 3 | 라벨 없이 본문 내 하이픈 형식 | 2 | - |
| 접수구분 | 링크패스 | 세모R | 세모R+ | 세모R+(성장) | 위멤버스 | 합계 |
|---|---|---|---|---|---|---|
| 문의 | 72 | 656 | 109 | 4 | 14 | 855 |
| 신청(가입) | 0 | 780 | 11 | 0 | 0 | 791 |
| 요금변경 | 0 | 0 | 0 | 6 | 0 | 6 |
| 합계 | 72 | 1,436 | 120 | 10 | 14 | 1,652 |
사업자번호 100% 보유 · 고유 사업자 1,094개 (2건 이상 425개, 1건만 669개, 최다 9건)
활동 59건 — 방문 20 · 통화 18 · 컨설팅 9 · 문자 6 · 가입/해지 2 · 요금/정산 2 · 기타 2
inquiry_type — 레거시 컬럼 화면에서 제거 (v0.280)Flow 유형 행 · 칸반 카드 부제 · 활동 메타 세 곳에서 inquiry_service 로 교체했다. COLS 에서도 빼 더 이상 읽지 않는다.{접수구분} {서비스} 로 재생성하면 request_kind + inquiry_service 의 복사본이 된다. 같은 정보가 두 곳에 생기고 한쪽만 바뀌면 또 어긋난다. 배지가 이미 정확하므로 표시를 없애는 편이 맞다.f_task_no 로 충분하다.[신규가입] · [Link Path 도입문의]) 이 필요해지면 f_type 컬럼을 새로 만들어 Data 등록에서 채운다. 파생값을 고쳐 쓰지 않는다.기존 DB 의 inquiry_type 은 {접수구분} {유형그룹} 형태다. 서비스 필드가 아니다.
| inquiry_type | request_kind | inquiry_service | 건수 | 판정 |
|---|---|---|---|---|
| 신규 세모R+ | 신청(가입) | 세모R | 738 | 불일치 |
| 재가입 세모R+ | 신청(가입) | 세모R | 42 | 불일치 |
| 재가입 세모R+ | 문의 | 세모R+ | 4 | 재신청을 재가입으로 오분류 |
| 문의 세모R | 문의 | 세모R | 614 | 일치 |
| 문의 세모R+ | 문의 | 세모R+ | 92 | 일치 |
| 문의 링크패스 | 문의 | 링크패스 | 16 | 일치 |
| 문의 통합문의 | 문의 | 위멤버스 · 세모R | 14 · 10 | 분기 |
| 문의 이벤트-한청세 | 문의 | 세모R+ · 세모R | 8 · 1 | 분기 |
inquiry_type 으로 서비스를 판단하면 780건이 틀린다세모R+ 로 찍혀 있다. 또 재신청(템플릿 B, 신청 접수)과 재가입(템플릿 A, 가입 완료)을 구분하지 못한다.inquiry_service + request_kind 2단으로 교체한다.이벤트-한청세)는 inflow_code(KYT1004) 로 추적 가능하다.칸반과 메뉴탭은 역할이 다르다. 섮어 쓰면 양쪽 다 애매해진다.
| 화면 | 보여주는 것 | 역할 |
|---|---|---|
| 칸반 (STEP) | 현재 단계에 있는 건만 | 작업 대기열. 카드를 옥겨 진행시킨다 |
| 메뉴탭 | 해당 그룹 전체 | 조회 · 검색 · 관리 |
| 탭 | 데이터 | 비고 |
|---|---|---|
| STEP | 칸반 | 그룹별 컬럼 보드 |
| 문의 | 전체 1,652건 | 마스터 목록. 검색 · 필터 전용 |
| 컨설팅 | step_group = 컨설팅 | 그룹별 목록 |
| 온보딩 | step_group = 온보딩 | |
| 활성화 | step_group = 활성화 |
문의 로 시작한다 (v0.271)step_group 을 거는데 문의 탭만 전체가 나와 일관성이 없었다. 진입 시 단계를 문의 로 맞추되 지울 수 있는 소프트 필터라, 단계를 비우면 여전히 1,652건 전체를 조건별로 뒤질 수 있다.칸반은 사람이 처리해야 할 일이 쌓이는 곳이다. 종료된 건을 컬럼으로 두면 카드가 쌓기만 하고 비워지지 않아 대기열 역할을 잃는다.
| 그룹 | 칸반 표현 | 이유 |
|---|---|---|
| 문의 · 컨설팅 · 온보딩 | 카드 컬럼 | 카드가 실제로 움직이는 구간 |
| 활성화 | 위험 필터 패널 | 1,464건. 이미 이용 중이라 처리 대기열이 아니다. 실무는 “위험한 곳을 찾아 조치”라 필터가 맞다 |
| 완료 · 정지 · 해지 | 통계 패널 | 종료 상태. 카드를 옥길 일이 없다 |
세 컬럼 모두 동일한 4개 지표를 쓴다. 같은 형식이라 서로 비교하기 쉽다.
| 지표 | 출처 |
|---|---|
| 누적 | crm_inquiries.step_detail 현재 값 |
| 이번 달 · 3개월 · 연간 | crm_stage_history 진입 이력 |
crm_stage_history 가 비어 있어 현재는 - 로 표시된다. 카드를 옥기기 시작하면 자동으로 채워진다.탭 순서는 고객 → 문의/신청 → 활동이력 이다. 좌측 고객 메뉴에서 들어오면 고객 탭부터 열린다.
| 구획 | 내용 |
|---|---|
| 원장 | 상태 · 사업자구분 · 사업자번호 + 이용기관코드 · 휴폐업 읽기 전용 |
| 사업장 | 사무소명 · 대표자 · 신청자 · 연락처 · 이메일 · 거래처 · 주소 수정 가능 |
| 메모 | 방문 중 알게 된 내용 · 관심 사항 · 다음 액션 수정 가능 |
| 서비스 이용 | 세모R · 위멤버스 · 인사이트 · 링크패스 × 상태 · 요금제 · 가입일 · 해지일 · 정지일 · 재사용일 · 사유 |
| 보고서 | 완료 · 대기 · 보류 / 부가세 완료 · 대기 · 읽음 · 에러 |
| 거래처 | 위멤버스 전체 · 정상 · 휴폐업 / 세모 전체 · 이용 · 정지 |
| 셋업 | 실시간 · 자동수집 인증서 · 부서사용자 · 신고프로그램 |
| 카카오채널 | 보고서 · 채팅 · 승인 |
잠재를 누르면 목록 구성 자체가 바뀐다 — 문의가 아닌 다른 테이블에서 오므로 컬럼이 다르다. 잠재-DB 12,135건은 누를 때 한 번만 읽는다.
가입 이력이 있는 고객만 나온다. 기본은 정상 이다 — 지금 쓰고 있는 고객이 먼저 보여야 한다.
검색 중 — 상태 무관 전체에서 찾습니다 를 표시한다.완료 를 신규고객 으로 바꾸고 가입 실적을 보여준다.
| 지표 | 기준 |
|---|---|
| 신규고객 | 원장 joined_at |
| 정지 · 해지 | 원장 paused_at · canceled_at · 현재 그 상태인 고객만 |
| 세모R · 세모R+ | 인사이트 가입일 유무. 둘의 합이 그 기간 신규고객 수다 |
| 성장패키지 | 문의 inquiry_promo. 그중 일부라 합계에 더해지지 않는다 |
crm_stage_history 를 기간 집계에 쓰지 않는다목록으로 보기 버튼을 두지 않는다원장에 대표자 한 명, 문의에 신청자 한 명뿐이었다. 한 사무소에 세무사가 여럿이고 실무 담당자도 따로 있는데 담을 곳이 없었다.
| 구분 | 실측 | 뜻 |
|---|---|---|
| 세무사 | 886명 | 원장 대표자. 사업자 수와 정확히 일치한다 — 지점 · 재가입이 겹치지 않았다 |
| 신청자 | 393명 | 문의를 넣은 사람. 대표자와 이름이 같으면 넣지 않는다 — 한 사람이 두 줄로 보인다 |
| 담당자 | 수기 | 실무 담당. 보고서를 받거나 자료를 챙기는 사람 |
kind = '세무사' 로 거른다.
구분을 나눠 둔 이유가 여기 있다.crm_inquiries.stage_memo 한 칸을 쓰고 있었다. 누가 언제 무엇을 적었는지 남지 않고,
나중에 적은 사람이 앞의 내용을 지웠다.| 규칙 | 이유 |
|---|---|
| 사업자 단위로 쌓기 | 계정이 여럿이어도 방문 기록은 그 사무소 전체의 것이다 |
| 누구나 고칠 수 있음 | 오탈자나 잘못된 정보를 발견한 사람이 바로 고치는 편이 낫다 |
| 고친 사실은 남김 | crm_note_edits 에 고치기 전 내용을 통째로. 확인할 방법이 없으면 아무도 메모를 믿지 않게 된다 |
| 차이가 아니라 전문 저장 | 차이만 저장하면 여러 번 고쳤을 때 원본을 못 되살린다 |
삭제는 is_deleted | 잘못 지웠을 때 되살릴 방법이 있어야 한다 |
컬럼 구성 · 순서 · 정렬을 사람마다 뷰마다 저장한다 (crm_list_prefs).
| 화면 | 컬럼 | 기본 구성 |
|---|---|---|
| 문의 · 컨설팅 · 온보딩 | 31개 중 | 등록일 · 사무소명 · 사업자번호 · 신청자 · 핸드폰 · 문의서비스 · 담당자 · 주소 · 유입코드 · 문의내용 |
| 고객 | 29개 중 | 가입일 · 사무소명 · 상태 · 서비스 · 고객(전체) · 세모(전체) · 세모(사용) · 요금제 · 주소 · 핸드폰 |
| 활성화 | 고정 | 사무소명 · 서비스 · 거래처 · 보고서 · 인증서 · 담당자 위험 관리 전용 |
jsonb 한 덩어리로 저장한다10 이 9 보다 앞에 온다localeCompare('ko') — 코드값 비교는 순서가 어긋난다td:first-child 에 최소 폭을 걸었더니 고객 탭은 첫 칸이 가입일이라 그 칸이 240px 을 차지했다.
컬럼 순서를 바꿀 수 있게 만든 이상 첫 칸이 무엇인지 알 수 없다 — nm-cell 클래스로 그 칸만 지정한다.26.08.01 — 2026-08-01 은 10자를 차지해 좁은 칸에서 줄이 바뀐다. 목록은 훑어보는 곳이라 연도 네 자리가 필요 없다title 은 1초 넘게 걸리고 줄바꿈이 안 되며 길면 잘린다. 값을 DOM 속성에 담지 않고 id 로 그때 읽는다 — 1,600건 × 긴 본문을 속성에 넣으면 HTML 이 무거워진다| 동작 | 결과 |
|---|---|
| 같은 행 다시 누르기 | 닫힌다 — 열려 있는 것을 또 열려는 동작은 닫으려는 뜻이다 |
| ESC | 위에서부터 — 확인창 → 컬럼 설정 → 개선의견 → 상세 |
| 바깥 클릭 | 닫힌다. 목록 · 칸반 · 헤더 · 좌측 탭은 예외 |
closeInquiryDetail 을 부르고 거기서 한 번만 확인을 띄운다.
판단이 여러 곳에 있으면 한쪽만 고쳐질 위험이 있다.문의 없음 을 표시한다.| 지표 | 조건 | 기준값 |
|---|---|---|
| 거래처 위험 | 사용 거래처가 기준 미만 (미등록 포함) | risk_count_min기본 20 |
| 발송수 위험 | 발송 거래처가 기준 미만 | |
| 인증서 위험 | 미등록 또는 만료 | 기준값 없음 |
| 발송 감소 | 전월 대비 발송 거래처 감소율 | risk_drop_pct기본 20% |
- 로 표시된다. 연동 후 집계 조건만 채우면 바로 동작한다.위험 기준은 개인 취향이 아니라 회사 정책이다. 사람마다 다르면 “위험 12건이요”라고 했을 때 상대 화면엔 30건이 나와 대화가 안 통한다. 그래서 localStorage 가 아니라 crm_settings 테이블에 저장한다.
설정 창을 따로 두지 않고 화면 상단에 입력란을 직접 놓았다. 값을 고치면 즉시 저장되고, 저장 실패 시 이전 값으로 되돌린다.
| 항목 | 규칙 |
|---|---|
| 컬럼 폭 | 카드형 4개는 1fr, 통계형 2개는 0.5fr.통계형은 카드가 없어 폭이 덜 필요하며, 대신 카드형이 넣어지면 사무소명이 덜 잔린다 |
| 기본 보기 모드 | 리스트형. 컬럼 헤더 버튼으로 카드형 전환 |
| 한 번에 그리는 수 | 50장. 더보기를 누를때마다 50장씩 추가 |
| 더보기 버튼 | 다음 표시할 건수와 남은 건수를 함께 보여준다. 그 아래에 목록 탭에서 전체 보기 를 별도로 둔다 |
| 통계형 헤더 숫자 | 집계가 가능해질 때만 노출. 아랫 항목이 전부 - 인데 헤더에 전수만 큰 숫자로 뜼우면 어긋나 보인다 |
| 통계형 서식 | 활성화 위험 패널과 완료 · 정지 · 해지 통계는 헉은 사이즈를 공유한다. 항목명 11.5px · 숫자 12.5px · 안내문구 10.5px |
다음액션: 통화가 3개월째 그대로 남는다. 기한을 지난 카드를 드러내면 방치를 바로 잡을 수 있고, 실패 자동 판정과도 연결된다.필터를 리스트 로컬 바와 헤더에 나눠 두면 어디서 걸렸는지 알 수 없다. 전부 헤더로 모으고 로컬 바를 없앴다.
| 필터 | 컬럼 | 비고 |
|---|---|---|
| 상품 | inquiry_service | 세모R · 세모R+ · └ 성장패키지(inquiry_promo) · 링크패스 · 위멤버스. 성장패키지는 세모R+ 하위에 둔다 |
| 단계 | step_detail · step_group | 문의 데이터를 쓰는 뷰에서만 노출 |
| 접수 | request_kind | 문의 · 신청(가입) · 요금변경. 문의 뷰에서만 노출 |
| 담당자 | assignee | 딜 담당자 + 문의 담당자 합집합 |
| 검색 | 사무소명 · 사업자 · 신청자 · 연락처 · 주소 | 헤더 검색창 공용 |
세모R (1436) · 링크패스 (72) 처럼 표시하며 crmInquiries 로 클라이언트에서 계산하므로 추가 쿼리가 없다.inquiry_type 필터를 제거한 이유세모R+ 로 찍혀 780건이 잘못돼 있다 (9-D). 필터로 두면 오분류가 화면에 그대로 노출된다.헤더 [전체 | 중복제외] 세그먼트. 다건 사업자가 425개라 전체 목록에서는 같은 사무소가 여러 줄 반복된다.
| 모드 | 동작 | 의미 |
|---|---|---|
| 전체 | 묶지 않는다 | 그 메뉴 안의 모든 건. 문의 탭에서 단계 문의 를 걸면 그 조건의 전 건이 나온다 |
| 중복제외 | biz_no 별 최신 1건 | 같은 사무소가 여러 줄 반복되는 것을 없앤다. 접힌 이력은 상세 패널 타임라인에서 본다 |
전체 는 1,652 를 뜻하지 않는다biz_no + 문의서비스 로 묶었다. 전체 라는 이름과 동작이 어긋나 v0.278 에서 되돌렸다.localStorage 에 저장해 재접속 시 복원1–20 · 72건 / 1,652 형태로 현재 구간 · 필터 결과 · 전체를 함께 표시리스트 위에 덮이는 우측 도킹 840px. 바깥 클릭 · ESC 로 닫힌다. 리스트 폭이 줄지 않아 컬럼 7개를 유지한다.
| 영역 | 폭 | 내용 |
|---|---|---|
| 탭 | - | 문의/신청 · 활동이력 |
| 좌 · 타임라인 | 380px | 같은 사업자번호의 접수를 최신 → 과거 로 쌓는다. 카드를 눌러 우측을 전환 |
| 우 · 상세 | 460px | 선택 건의 배지 · 단계 · 기본정보 · 가입내역 · 문의내용 · 이 건의 활동 |
biz_nocrmInquiries 로 클라이언트 필터라 추가 쿼리가 없고, 활동만 in('inquiry_id', ids) 로 1회 읽는다. 같은 사업자 안에서 카드를 옮기면 재조회하지 않는다.| 표시 규칙 | 내용 |
|---|---|
| 날짜 | 배지 줄 우측에 진하게. 타임라인이므로 시간이 먼저 읽혀야 한다 |
| 서비스 전환 배너 | 앞 건과 서비스가 달라진 카드에 ↗ 세모R → 세모R+. 시간순으로 계산하고 표시만 역순 |
| 사무소명 | _cleanOffice() 로 유입코드 · 등록일 · 거래처수 접미어 제거 후 사무소명 (인물명). 문의는 신청자명, 신청(가입) 은 대표자명 |
| 거래처 | _parseJoin() 으로 가입내역을 분해해 세모 113개 · 위멤 164개(프리미엄). 세모R 요금제는 서비스 배지와 중복이라 생략 |
| 문의내용 | _inqNarrative() 로 상단 표에 이미 나온 필드와 가입내역 블록을 제거. 남는 게 없으면 섹션을 숨긴다 |
| 리스트 다건 배지 | 사무소명 옆 숫자. _bizCount() 클라이언트 계산 |
사업자 단위 평면 시간순. stage_group 칩(문의 · 온보딩 · 활성화) + 유형 칩으로 걸러본다.
| 동작 | 활동이력 | 이유 |
|---|---|---|
| 조회 | ○ | 탭의 목적 |
| 수정 · 삭제 | ○ | 부모가 이미 정해져 있어 선택할 것이 없다 |
| 추가 | × | 부모 문의를 골라야 한다 → 결정이 늘고 오배정 위험. 문의/신청 탭에서만 추가하며 선택된 문의가 곧 부모다 |
stage_group 칩으로 자연히 분리된다.성겁이 다릅니다. 어떤 이유로 멈췐 있는지가 우선순위를 결정합니다.
crm_stage_history 도 계속 비었다. 그러면 기간별 통계가 영원히 - 로 남는다.updateInquiryStep() 과 같은 패턴을 쓴다.step 컬럼에 저장해 아무 것도 반영되지 않았다.| 요건 | 준버된 것 | 필요한 것 |
|---|---|---|
| 담당자 배정 | assignInquiry() 함수assignee 컴럼 | 상세 패널에 담당자 드롭다운. 배정 시 컨설팅 대기로 자동 이동하는 핵심 설계가 작동하지 않는다 |
| 가능성 입력 | possibility 컴럼카드 배지 표시 | 높음 · 보통 · 낮음 선택 UI |
| 다음액션 · 기한 | next_actionnext_action_due | 입력란 · 날짜 선택 |
| 메모 | stage_memo | 텍스트 에리어 |
| 판정보류 해제 | hold_reason 57건 | 해제 버튼. 지금은 판정보류를 풀 방법이 없다 |
화면은 만들어 두었으며 집계 조건만 채우면 바로 동작한다.
| 요건 | 막힌 지점 | 부녕을 곳 |
|---|---|---|
| 위험 지표 4종 집계 | 거래처 수 · 발송 건수 · 인증서 정보 | 고객원장 (3계층) |
| 온보딩 모니터링 1~3 | 수임처 등록 · 첫 발송 · 정기 발송 판정 | |
| 기간별 통계 | 이번 달 · 3개월 · 연간 진입 건수 | crm_stage_historyA번 해소 시 자동 추적 |
| 홈페이지 유형 확정 | 문의 단계는 전부 미확인 | 고객원장 |
| 가입일 기준 재분류 | registered_at 은 문의일이다.2023년 문의 → 2026년 가입이면 이관분으로 섮인다 | 고객원장의 정확한 가입일 |
| # | 항목 | 내용 |
|---|---|---|
| 2 | 경쟁사 정의 | 경쟁사 제품을 쓰는 사무소인가, 경쟁 업재 자체인가 |
| 3 | 유입 경로 컴럼 | inflow_path 실제 값이 온라인 · 상담 · 타겟 · MGM 분류와 대응하는지 미확인 |
| 4 | 조직 데이터 | 팀 3개(로움 · 위멤버스 · 외부) 하위 채널과 담당자 배정표. 헤더 필터가 보다 빈 상태 |
| 5 | 외부 팀 범위 | 대리점인가 파트너인가. 데이터 공개 범위가 이것으로 결정된다 |
| 6 | Flow Webhook 방식 | 실시간인가 주기적 배치인가. 첫 대화부터 미정 |
| 요건 | 상태 | 내용 |
|---|---|---|
| 신규 929건 등록 | 미채수 | 잠재에 없던 문의를 crm_prospects 에 넣는다. 좌표가 이밌 확보되어 넣는 즉시 지도에 뜼다 |
prospect_id 역방향 링크 | SQL 준버 (v0.047 · 048) | 한 사무소의 문의 내역 전제를 상세에 보이려면 필요. 없으면 조회할 때마다 매칭 함수를 다시 태워야 한다 |
join_* 파싱 | 미채수 | 정상 (240430, PREMIUM, 463개) 를 단계 · 가입일 · 요금제 · 수임처수로 분해. 상품별 단계 현황 UI 의 기초 |
| 활성화 목록 화면 | 필터만 있음 | 1,464건을 위험도 · 담당자 · 상품으로 거릅는 목록 |
risk_legacy 정리 | 1분 작업 | 안 쓰는 기준 4건이 설정 테이블에 남아 헷갈림을 유발한다 |
crm_inquiries 1,652건에 사업자번호 · 대표자명 · 휴대폰 · 이메일이 있으며, anon 키만 알면 읽혐다. anon 키는 HTML 에 평문으로 박혔 있다.| 조치 | 내용 |
|---|---|
DEV_MODE = false | OAuth 로그인 연결. initSupa() 에서 getSession() + onAuthStateChange() 로 세션을 잡아야 authenticated 로 인식된다 |
| anon 읽기 정책 회수 | crm_v0_013 — <table>_anon_select 정책 제거. OAuth 동작 확인 후에만 실행 |
| 컴럼 UPDATE 권한 회수 | 좌표(lat · lng)와 crm_settings.value 에 열어듐 anon UPDATE |
| 새 테이블 권한 점검 | Table Editor 로 만들면 GRANT ALL 이 자동 부여된다. anon 이 TRUNCATE · DELETE 를 갖게 되므로 매번 확인한다 |
crm_stage_history 에 의지한다.