using Application.Abstractions.Data; using Application.Helpers; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Infrastructure.StockData; /// /// 장전 브리핑 자동 발행 배치 (D2 M3, d2 §③·§⑥) — 매 영업일 07:30 KST. /// 전일 지수(IndexDailyPrice)·등락 상위/하위 종목(StockDailyPrice)·주요 공시(Disclosure)를 취합해 /// briefing 보드에 시스템 계정(MemberID=null)으로 IsNotice Post 를 발행하고 DailyBriefing 기록을 남긴다. /// BriefingDate 로 멱등 — 같은 날 이미 발행됐으면 skip. /// /// BackgroundJobs:DailyBriefing 플래그로 토글(기본 false), Web.Api 전용(중복 실행 방지). /// 조립/발행 로직은 순수 엔진(DailyBriefingComposer)에 위임 — 여기서는 스케줄만 담당한다. /// internal sealed class DailyBriefingPublisher( IServiceScopeFactory scopeFactory, ILogger logger ) : DailyScheduledService(logger) { /// KST 실행 시각 — 장 시작(09:00) 전. private static readonly TimeOnly RunTime = new(7, 30); protected override string JobName => "DailyBriefing"; protected override TimeOnly TargetTime => RunTime; protected override async Task RunOnceAsync(DateOnly todayKst, CancellationToken ct) { using var scope = scopeFactory.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var result = await DailyBriefingComposer.PublishAsync(db, todayKst, ct); if (result.AlreadyExisted) { Logger.LogInformation("[{Job}] 이미 발행됨 — skip. date={Date}, postID={PostID}", JobName, todayKst, result.PostID); } else { Logger.LogInformation("[{Job}] 발행 완료 — date={Date}, postID={PostID}", JobName, todayKst, result.PostID); } return true; } }