auto: 일일 백업 2026-06-21 02:00
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
# 2026-06-20
|
||||
|
||||
- 신한은행 잔액 불일치 `144원`은 관리자님 확인으로 은행이자였다. 후잉에 `신한은행(효원) ← 기타수익`, item `이자`, memo `은행이자`, 금액 `144원`, 날짜 `2026-06-20`로 수동 등록했고, 후잉 잔액이 SMS 잔액 `307,004원`과 일치함을 검증했다. `state/whooing_balance_alerts.json`의 신한은행 정합성 상태도 diff `0`으로 정리했다.
|
||||
- 관리자님 지시로 신한은행도 잔액 불일치 자동 이자 보정 대상에 추가했다. `whooing_sync.py` 정합성 체크에서 자산 계정이고 후잉 잔액이 SMS보다 부족하며 차이가 `5,000원` 이하이면 카카오뱅크와 동일하게 `{은행계정} ← 기타수익`, item `이자`, memo `은행이자`로 자동 분개한다.
|
||||
@@ -935,13 +935,13 @@ def main():
|
||||
prev = carriers_state.get(carrier, {})
|
||||
prev_diff = prev.get("last_diff")
|
||||
|
||||
# 카뱅 자동 이자/캐시백 보정: 자산 + 후잉이 SMS보다 적고(deposit 누락), 차이 ≤ 5,000원.
|
||||
# 은행 자동 이자/캐시백 보정: 자산 + 후잉이 SMS보다 적고(deposit 누락), 차이 ≤ 5,000원.
|
||||
# 횟수·날짜 제한 없이 매번 자동 분개. 매 발화마다 텔레그램 알림으로 누적 가시성 확보.
|
||||
# 정상 SMS가 와서 deposit이 후잉에 들어가면 diff>=0이 되어 안전하게 미발화.
|
||||
cur_month = datetime.now(KST).strftime("%Y-%m")
|
||||
if (
|
||||
info.get("side") == "asset"
|
||||
and carrier == "kakaobank"
|
||||
and carrier in {"kakaobank", "shinhan_bank"}
|
||||
and diff < 0
|
||||
and abs(diff) <= 5000
|
||||
):
|
||||
@@ -957,7 +957,7 @@ def main():
|
||||
ok, status, body = post_to_whooing(webhook_url, interest_payload, dry_run=False)
|
||||
if ok:
|
||||
notify.send(
|
||||
f"💰 <b>카뱅 은행이자 자동 분개</b>\n"
|
||||
f"💰 <b>{notify.escape_html(info['label'])} 은행이자 자동 분개</b>\n"
|
||||
f"+{interest_amount:,}원 ({notify.escape_html(info['account'])} ← 기타수익)"
|
||||
)
|
||||
carriers_state[carrier] = {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# 2026-06-20
|
||||
|
||||
- 오전 브리핑 HTML 조립 로직 변경: 오선(@futuresnow) 또는 비하이브 장전 시황 요약이 없으면 메일 하단에 `오선 요약 없음`, `비하이브 요약 없음`을 짧게 표시하도록 `scripts/briefing_mail.py`에 footer note를 추가했다.
|
||||
@@ -1106,6 +1106,37 @@ def _article_card(a: dict) -> str:
|
||||
return '\n'.join(parts)
|
||||
|
||||
|
||||
def _briefing_footer_note(lines: list[str]) -> str:
|
||||
if not lines:
|
||||
return ''
|
||||
S = HTML_STYLES
|
||||
body = '<br>'.join(html_escape(line) for line in lines if str(line).strip())
|
||||
if not body:
|
||||
return ''
|
||||
return (
|
||||
f'<div style="margin-top:18px;padding-top:11px;border-top:1px solid #eee;'
|
||||
f'{S["source"]}">{body}</div>'
|
||||
)
|
||||
|
||||
|
||||
def _morning_missing_summary_notes(data: dict) -> list[str]:
|
||||
notes = []
|
||||
us_market = data.get('us_market') or {}
|
||||
behive_market = data.get('behive_market') or {}
|
||||
|
||||
if not us_market.get('available_today'):
|
||||
notes.append('오선 요약 없음')
|
||||
elif not data.get('overseas_summary'):
|
||||
notes.append('오선 요약 없음')
|
||||
|
||||
if not behive_market.get('available_today'):
|
||||
notes.append('비하이브 요약 없음')
|
||||
elif not data.get('domestic_summary'):
|
||||
notes.append('비하이브 요약 없음')
|
||||
|
||||
return notes
|
||||
|
||||
|
||||
def build_html_body(data: dict) -> str:
|
||||
S = HTML_STYLES
|
||||
mode = data.get('mode', 'morning')
|
||||
@@ -1172,6 +1203,8 @@ def build_html_body(data: dict) -> str:
|
||||
out.append(f'<div style="{S["news_section"]}">주요 뉴스</div>')
|
||||
for a in articles:
|
||||
out.append(_article_card(a))
|
||||
if mode == 'morning':
|
||||
out.append(_briefing_footer_note(_morning_missing_summary_notes(data)))
|
||||
out.append('</div>')
|
||||
return '\n'.join(out)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user