auto: 일일 백업 2026-08-05 02:00

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
hyowons
2026-08-05 02:00:06 +09:00
parent 7e7d759b34
commit c03b3f2659
148 changed files with 3428 additions and 1380 deletions
@@ -154,7 +154,16 @@ node@22 가 2026-07-20 에 `22.22.2` → `22.23.1` 로 올라가며 **바이너
- 사람 이름 송금(예: "박영춘", "이지윤")은 exact 룰로 등록하지 말고 default fallback 에 맡긴다. merchant_map 비대화 방지.
- `deposit` 은 default fallback 없음 — rule 없으면 raw 폴백 (수익/이체/환급 구분 위험 때문).
- `card_cancel` 은 **승인의 역분개**로 좌우를 뒤집어 POST 한다 (2026-08-03). 승인이 `{비용 ← 카드}` 이므로 취소는 `{카드 ← 비용}`. 부분취소도 취소 문자 금액 그대로 상쇄되어 맞는다. 이전엔 raw 폴백으로 후잉 자체 파서에 맡겼는데, 결과는 맞았지만 파싱을 외부에 의존하고 raw 폴백 알림이 매번 울렸다. 현대카드·신한카드(`매입취소`/`승인취소`) 공통.
- ⚠️ **후잉은 계정 그룹별로 쓸 수 있는 변이 정해져 있다**`비용(expenses)`**차변(left) 전용**, `수익(income)`은 **대변(right) 전용**이고 `자산·부채`만 양쪽 자유다. 위반하면 `[r_account] => 잘못된 값입니다`(비용을 우측에) 또는 `[l_account] => 잘못된 값입니다`(수익을 좌측에)로 **HTTP 200 + 실패 본문**이 온다. 이 제약을 몰라서 2026-08-03~04 회귀가 났다. 새 분개 방향을 만들 때 반드시 확인할 것.
- ⚠️ **후잉은 취소·환불 문자를 자동 처리하지 않는다.** 공식 FAQ(`/help/faqs/inserting/refund`)가 "기존의 구입 거래를 **찾아서 지워주거나**, 금액을 마이너스로..." 라고 **사용자에게 수동 안내**한다. raw 로 취소 원문을 보내도 원본 승인은 그대로 남는다. 2026-08-04 에 과거 3건(07-04 카카오 월드킹·06-09 현대 쿠팡·06-13 현대 네이버페이)에서 원본이 사라진 걸 보고 "후잉 파서가 지운다"고 판단했는데, **관리자님이 그동안 수동 삭제해 오신 것**이었다. 두 설명 모두 "건수 −1, 순액 일치"라 검산으로는 구분되지 않는다 — 같은 착각을 반복하지 말 것.
- `card_cancel`**원본 승인 거래를 찾아 PUT 으로 감액**한다 (2026-08-04, 관리자님 결정 — 수동 삭제를 없애는 게 목적). `_handle_card_cancel` → `whooing_balance.find_card_entries` 로 같은 카드·같은 상호(memo 토큰 매칭)·금액이 취소액 이상인 거래를 30일 창에서 찾고, **정확히 1건일 때만** `set_entry_money``원금액 취소액` 으로 줄인다. 전액취소면 0원 줄이 남지만 잔액·합계에 영향은 없다.
- ⚠️ **좌우를 뒤집은 역분개로 바꾸지 말 것** — 비용이 대변으로 가서 후잉이 거부한다(위 제약). 2026-08-03 에 이 방식으로 바꿨다가 **첫 취소 문자에서 동기화가 통째로 멈췄다**(`blocked_at` 이 커서를 잠가 뒤의 정상 결제까지 전부 대기).
- ⚠️ **거래 삭제는 API 로 불가능하다** — 후잉 OpenAPI 의 DELETE 는 `section_id` 를 쿼리·본문(urlencoded/JSON)·쿠키·경로 어디에서도 읽지 못한다(2026-08-04 전수 실측, 같은 본문을 PUT 으로 보내면 정상). 0원 줄을 지우려면 후잉 UI 에서 수동으로. 마이너스 분개(후잉 공식 안내안)도 가능하지만 ± 두 줄이 남아 채택하지 않았다.
- **후보가 0건이거나 2건 이상이면 감액하지 않고 raw 폴백**(오감액보다 안전). 이때는 **후잉이 알아서 처리해주지 않으므로 관리자님 수동 작업이 필요하다** — 그래서 폴백 건은 `new_raw` 에 그대로 실어 raw 폴백 텔레그램 알림이 울리게 둔다. 알림을 끄면 수동 작업이 필요한 걸 모르고 지나친다.
- ⚠️ **매칭은 `item` 이 아니라 `memo` 로 한다**`merchant_map` contains 룰이 `item` 을 재작성해서(동행복권→`복권`) item 은 상호와 다를 수 있지만 memo 는 항상 승인 SMS 원문이다.
- ⚠️ **memo 매칭은 토큰 단위**(`_memo_has_merchant`) — 단순 substring 이면 `쿠팡``쿠팡페이주` 승인까지 잡는다. 2026-08-04 에 두 상호가 같은 날 같은 금액(22,700원)으로 실제로 있었다.
- ⚠️ **`card_cancel` 을 내는 파서는 현대카드·신한카드(`매입취소`/`승인취소`) 둘뿐이다.** 카카오뱅크 `카드결제취소``KAKAOBANK_CARD_RE``카드결제\s+` 가 안 맞아 **파싱 자체가 실패**(`kind=None`)하고, 하나·신한은행은 입금/출금만 있다. **이들은 감액 대상이 아니라 raw 로 가고, 후잉도 처리하지 않으므로 관리자님 수동 삭제가 계속 필요하다.** 자동화하려면 `parsers.py` 보강 + 2026-08-03 픽스처 회귀 재실행이 필요하다 — **2026-08-04 관리자님 지시로 "실제 취소 문자가 올 때 처리"로 보류**. 판단 근거는 파싱이 실패해도 `_infer_raw_details` 가 정규식으로 금액·상호를 뽑아 raw 폴백 알림에 실어주기 때문(실측: 카카오 취소 문자 → `2,000원 · (주)월드킹`). 알림을 보고 그때 대응하면 된다.
- **삼성카드는 아예 동기화 대상이 아니다** — 발신번호 `+8215888700``whooing_account_map.json` 에서 `confirmed=False` 라 수집조차 안 되고, 실제 오는 문자는 전부 `(광고)` 이며 후잉 `삼성신용(효원)`(x77) 은 최근 90일 거래 0건이다(2026-08-04 확인). 취소를 기다릴 대상이 아니라, **다시 사용하기 시작하면 승인 문자부터 누락**되니 그때 `confirmed` 등록이 먼저다.
- 기존 contains(예: "스타벅스 → 식비") / exact(예: "방효원 → 기초잔액(효원)") 는 계속 유효. fallback 은 둘 다 miss 일 때만 탄다.
- ⚠️ **주유소는 두 곳을 함께 손대야 한다**`whooing_sync.py``FUEL_KEYWORDS`(150,000원 선승인/취소 스킵)와 `whooing_merchant_map.json` contains 룰(실제 결제 → `차량유지비/주유비`)이 한 쌍이다. 한쪽만 넣으면 선승인이 후잉에 남거나 실제 주유가 기타비용으로 샌다. 상호에 주유/석유가 없는 충전소(현대가스·한경에너)는 상호 자체를 등록. 한경에너는 선승인이 149,900원이라 `FUEL_PREAUTH_AMOUNT`(150,000 정확일치) 스킵엔 안 걸리고 분류만 적용된다.
- 결과적으로 자잘한 인명 송금·가맹점 미등록 건은 전부 기타비용으로 자동 분류되고, 분류가 필요한 것만 후잉 UI 에서 사후 조정하거나 merchant_map 에 규칙 추가한다.
@@ -267,7 +276,7 @@ python3 .../whooing_manual.py --dry-run --item ... --money ...
원칙:
- 차트에 없는 계정명으로 절대 추측 POST 금지. 모르면 반드시 재질문.
- 사용자가 이미 한 문장에 "스타벅스 5800원 신한카드로" 다 말했다면, 카테고리만 확인하고 바로 실행.
- 카드 취소/환불이면 structured 대신 `--message` raw 모드로 원문 보내 후잉이 상쇄하게 한다.
- 카드 취소/환불은 원본 승인 거래를 찾아 감액하는 게 원칙(위 `card_cancel` 항목). 후잉은 취소 문자를 자동 처리해주지 않으니 raw 로 보내고 끝내면 안 된다 — 원본이 그대로 남는다.
## 잔액 조회 (whooing_balance.py)