fix: 크롤링 오류 시 daily_stats 0으로 덮어쓰기 방지
- save_to_supabase()에서 status에 '오류' 포함 시 daily_stats 갱신 금지 - today_kwh == 0인 경우도 daily_stats 갱신 금지 (새벽/야간 보호) - solar_logs는 이상 이력 추적을 위해 오류 데이터도 계속 기록 - 재현 사례: 2026-05-14 15:40 nrems-03 NREMS 응답 오류로 0kW 오보
This commit is contained in:
parent
c736b2982f
commit
c885bab007
36
database.py
36
database.py
|
|
@ -73,11 +73,16 @@ def save_to_supabase(data_list):
|
|||
kst = timezone(timedelta(hours=9))
|
||||
kst_now = datetime.now(kst).isoformat()
|
||||
|
||||
status = item.get('status', '')
|
||||
is_error = '오류' in status # '🔴 오류' 상태 감지
|
||||
|
||||
# [보호] 오류 상태 데이터는 solar_logs에는 기록하되 daily_stats는 건드리지 않음
|
||||
# 단, solar_logs 기록 자체는 이상 이력 추적을 위해 유지
|
||||
record = {
|
||||
'plant_id': plant_id,
|
||||
'current_kw': float(item.get('kw', 0)),
|
||||
'today_kwh': float(item.get('today', 0)),
|
||||
'status': item.get('status', ''),
|
||||
'status': status,
|
||||
'created_at': kst_now # 한국 시간으로 저장
|
||||
}
|
||||
records.append(record)
|
||||
|
|
@ -86,28 +91,34 @@ def save_to_supabase(data_list):
|
|||
print("[DB] 저장할 유효한 레코드가 없습니다.")
|
||||
return False
|
||||
|
||||
# Supabase에 일괄 삽입 (solar_logs)
|
||||
# Supabase에 일괄 삽입 (solar_logs) - 오류 상태 포함 전체 기록
|
||||
result = client.table("solar_logs").insert(records).execute()
|
||||
|
||||
print(f"✅ [DB] Supabase 저장 완료: {len(records)}건 (solar_logs)")
|
||||
|
||||
# daily_stats 테이블 업데이트 (Upsert)
|
||||
# 오늘 날짜(KST) 기준, 현재 수집된 today_kwh가 기존 값보다 크거나 같으면 업데이트
|
||||
# 하지만 보통 today_kwh는 누적값이므로 간단하게 upsert 처리
|
||||
# [보호 로직]
|
||||
# 1. 오류 상태(크롤링 실패)인 경우 daily_stats 갱신 금지
|
||||
# 2. today_kwh == 0인 경우 daily_stats 갱신 금지 (새벽 0 값으로 하루치 덮어쓰기 방지)
|
||||
daily_records = []
|
||||
kst_date_str = datetime.now(timezone(timedelta(hours=9))).strftime("%Y-%m-%d")
|
||||
|
||||
for item in data_list:
|
||||
plant_id = item.get('id', '')
|
||||
if not plant_id: continue
|
||||
if not plant_id:
|
||||
continue
|
||||
|
||||
status = item.get('status', '')
|
||||
is_error = '오류' in status
|
||||
today_val = float(item.get('today', 0))
|
||||
|
||||
# 0인 경우는 저장하지 않거나(새벽), 기존 값을 덮어쓰지 않도록 주의해야 함
|
||||
# 하지만 발전소 데이터 보정을 위해 0이어도 일단 기록하거나,
|
||||
# 아니면 max 값을 유지하는 로직이 필요할 수 있음.
|
||||
# 여기서는 Upsert로 덮어쓰되, DB 트리거가 없다면 마지막 값이 저장됨.
|
||||
# 보통 크롤링은 누적값이므로 마지막 값이 그날의 최종값에 가까움.
|
||||
|
||||
# 오류 상태이거나 today_kwh가 0이면 daily_stats 갱신 건너뜀
|
||||
if is_error:
|
||||
print(f" ⚠️ [{plant_id}] 오류 상태 → daily_stats 갱신 건너뜀")
|
||||
continue
|
||||
if today_val == 0:
|
||||
print(f" ⚠️ [{plant_id}] today_kwh=0 → daily_stats 갱신 건너뜀 (새벽/야간 추정)")
|
||||
continue
|
||||
|
||||
daily_records.append({
|
||||
"plant_id": plant_id,
|
||||
|
|
@ -118,10 +129,7 @@ def save_to_supabase(data_list):
|
|||
})
|
||||
|
||||
if daily_records:
|
||||
# upsert: plant_id, date가 unique constraint여야 함
|
||||
try:
|
||||
# ignore_duplicates=False -> 업데이트
|
||||
# on_conflict="plant_id, date" (Supabase/PG 설정에 따라 다름, 보통 PK나 UK 기준)
|
||||
stats_result = client.table("daily_stats").upsert(daily_records, on_conflict="plant_id, date").execute()
|
||||
print(f"✅ [DB] daily_stats 업데이트 완료: {len(daily_records)}건")
|
||||
except Exception as e:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user