using System.ComponentModel.DataAnnotations;
namespace Domain.Entities.Stocks;
///
/// SEIBro 배당일정 (getDivSchedulInfo) — 현금/주식/동시/무배당 일정·명부폐쇄·권리락일 (Wave 1 ★P0).
/// 자연키 UNIQUE (IssucoCustno, RgtStdDt, RgtRsnDetailSortCd) — 한 회사·기준일에 배당 세부유형이 여럿(주식+현금 동시 등) 존재할 수 있다.
/// 날짜 스윕(getDivSchedulInfo, custno 미지정 → 그날 전체 회사)으로 수집한다.
///
public class DividendSchedule
{
[Key]
public int ID { get; private set; }
/// 발행회사 고객번호 (ISSUCO_CUSTNO)
public int IssucoCustno { get; private set; }
/// 대표종목명 (REP_SECN_NM)
public string RepSecnNm { get; private set; } = default!;
/// 권리사유코드 (RGT_RACD) — 103 배당/분배
public string? RgtRacd { get; private set; }
/// 권리사유세부유형코드 (RGT_RSN_DTAIL_SORT_CD) — 01주식 02현금 03동시 04무배당
public string RgtRsnDetailSortCd { get; private set; } = default!;
/// 권리기준일자 (RGT_STD_DT)
public DateOnly RgtStdDt { get; private set; }
/// 배정방법코드 (ALOC_WHCD) — 1정율 2정액 3정율+정액
public string? AllocWhcd { get; private set; }
/// 결산구분코드 (SETACC_TPCD) — 1결산 2반기 3분기
public string? SetaccTpcd { get; private set; }
/// 확정구분코드 (FIX_TPCD) — 1확정 2예고 3미정
public string? FixTpcd { get; private set; }
/// 명부폐쇄시작일자 (ROST_CLOSE_BEGIN_DT)
public DateOnly? RostCloseBeginDt { get; private set; }
/// 명부폐쇄종료일자 (ROST_CLOSE_EXPRY_DT)
public DateOnly? RostCloseExpryDt { get; private set; }
/// 권리락일자 (XRGT_DT)
public DateOnly? XrgtDt { get; private set; }
/// 전자증권 여부 (ELTSC_YN, Y=전자/N=예탁) — 미제공 null
public bool? IsElectronicSecurity { get; private set; }
public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow;
private DividendSchedule() { }
public static DividendSchedule Create(
int issucoCustno,
string repSecnNm,
string? rgtRacd,
string rgtRsnDetailSortCd,
DateOnly rgtStdDt,
string? allocWhcd,
string? setaccTpcd,
string? fixTpcd,
DateOnly? rostCloseBeginDt,
DateOnly? rostCloseExpryDt,
DateOnly? xrgtDt,
bool? isElectronicSecurity)
{
if (string.IsNullOrWhiteSpace(repSecnNm))
{
throw new ArgumentException("repSecnNm required", nameof(repSecnNm));
}
if (string.IsNullOrWhiteSpace(rgtRsnDetailSortCd))
{
throw new ArgumentException("rgtRsnDetailSortCd required", nameof(rgtRsnDetailSortCd));
}
return new DividendSchedule
{
IssucoCustno = issucoCustno,
RepSecnNm = repSecnNm.Trim(),
RgtRacd = string.IsNullOrWhiteSpace(rgtRacd) ? null : rgtRacd.Trim(),
RgtRsnDetailSortCd = rgtRsnDetailSortCd.Trim(),
RgtStdDt = rgtStdDt,
AllocWhcd = string.IsNullOrWhiteSpace(allocWhcd) ? null : allocWhcd.Trim(),
SetaccTpcd = string.IsNullOrWhiteSpace(setaccTpcd) ? null : setaccTpcd.Trim(),
FixTpcd = string.IsNullOrWhiteSpace(fixTpcd) ? null : fixTpcd.Trim(),
RostCloseBeginDt = rostCloseBeginDt,
RostCloseExpryDt = rostCloseExpryDt,
XrgtDt = xrgtDt,
IsElectronicSecurity = isElectronicSecurity
};
}
/// 재수집 반영 — 변경 필드가 있을 때만 UpdatedAt 갱신 (무변경 upsert 는 no-op)
public void Update(
string repSecnNm,
string? rgtRacd,
string? allocWhcd,
string? setaccTpcd,
string? fixTpcd,
DateOnly? rostCloseBeginDt,
DateOnly? rostCloseExpryDt,
DateOnly? xrgtDt,
bool? isElectronicSecurity)
{
var changed = false;
if (!string.IsNullOrWhiteSpace(repSecnNm) && RepSecnNm != repSecnNm.Trim())
{
RepSecnNm = repSecnNm.Trim();
changed = true;
}
var normalizedRacd = string.IsNullOrWhiteSpace(rgtRacd) ? null : rgtRacd.Trim();
if (RgtRacd != normalizedRacd)
{
RgtRacd = normalizedRacd;
changed = true;
}
var normalizedAllocWhcd = string.IsNullOrWhiteSpace(allocWhcd) ? null : allocWhcd.Trim();
if (AllocWhcd != normalizedAllocWhcd)
{
AllocWhcd = normalizedAllocWhcd;
changed = true;
}
var normalizedSetaccTpcd = string.IsNullOrWhiteSpace(setaccTpcd) ? null : setaccTpcd.Trim();
if (SetaccTpcd != normalizedSetaccTpcd)
{
SetaccTpcd = normalizedSetaccTpcd;
changed = true;
}
var normalizedFixTpcd = string.IsNullOrWhiteSpace(fixTpcd) ? null : fixTpcd.Trim();
if (FixTpcd != normalizedFixTpcd)
{
FixTpcd = normalizedFixTpcd;
changed = true;
}
if (RostCloseBeginDt != rostCloseBeginDt)
{
RostCloseBeginDt = rostCloseBeginDt;
changed = true;
}
if (RostCloseExpryDt != rostCloseExpryDt)
{
RostCloseExpryDt = rostCloseExpryDt;
changed = true;
}
if (XrgtDt != xrgtDt)
{
XrgtDt = xrgtDt;
changed = true;
}
if (IsElectronicSecurity != isElectronicSecurity)
{
IsElectronicSecurity = isElectronicSecurity;
changed = true;
}
if (changed)
{
UpdatedAt = DateTime.UtcNow;
}
}
}