using System.ComponentModel.DataAnnotations;
namespace Domain.Entities.Stocks;
///
/// SEIBro 의무보호예수/반환 정보 (getSafeDpDutyDepoStatus, 락업) — 예수/반환 일정·수량·사유 (Wave 2 ★P1).
/// 자연키 UNIQUE (IssucoCustno, ShotnIsin, SafedpDt, OccrSeq, DutySafedpRacd) — 한 종목·예수일에 사유가 여럿일 수 있어 사유코드까지 포함.
/// 수집은 조회기준일(BEGIN_DT) 날짜 스윕 후 window(스윕 창) delete+insert 로 반영한다.
/// ⚠️ 실응답의 SECN_KACD 는 코드(0101)가 아니라 종목종류명(보통주) 문자열이다(fixture 확인) — 문자열로 저장.
/// DUTY_SAFEDP_RACD 는 코드표가 크므로 코드 원문(문자열)으로 저장한다.
///
public class LockupEvent
{
[Key]
public int ID { get; private set; }
/// 발행회사 고객번호 (ISSUCO_CUSTNO)
public int IssucoCustno { get; private set; }
/// 한글종목명 (KOR_SECN_NM)
public string KorSecnNm { get; private set; } = default!;
/// 종목종류 (SECN_KACD — 실응답은 보통주/우선주… 명칭 문자열)
public string? SecnKacd { get; private set; }
/// 단축코드 (SHOTN_ISIN)
public string ShotnIsin { get; private set; } = default!;
/// 시장구분 (MART_TPCD)
public string? MartTpcd { get; private set; }
/// 업무구분 (OCCR_SEQ) — 1예수 2반환
public string OccrSeq { get; private set; } = default!;
/// 의무보호예수일 (SAFEDP_DT)
public DateOnly SafedpDt { get; private set; }
/// 예수주식수 (SAFEDP_QTY)
public long? SafedpQty { get; private set; }
/// 보호예수사유코드 (DUTY_SAFEDP_RACD) — 코드 원문 문자열 (코드표 큼)
public string DutySafedpRacd { get; private set; } = default!;
/// 반환일 (RETURN_DT)
public DateOnly? ReturnDt { get; private set; }
/// 반환주식수 (RETURN_QTY)
public long? ReturnQty { get; private set; }
/// 총발행주식수 (TOTAL_STK_CNT)
public long? TotalStkCnt { get; private set; }
public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow;
private LockupEvent() { }
public static LockupEvent Create(
int issucoCustno,
string korSecnNm,
string? secnKacd,
string shotnIsin,
string? martTpcd,
string occrSeq,
DateOnly safedpDt,
long? safedpQty,
string dutySafedpRacd,
DateOnly? returnDt,
long? returnQty,
long? totalStkCnt)
{
if (string.IsNullOrWhiteSpace(korSecnNm))
{
throw new ArgumentException("korSecnNm required", nameof(korSecnNm));
}
if (string.IsNullOrWhiteSpace(shotnIsin))
{
throw new ArgumentException("shotnIsin required", nameof(shotnIsin));
}
if (string.IsNullOrWhiteSpace(occrSeq))
{
throw new ArgumentException("occrSeq required", nameof(occrSeq));
}
if (string.IsNullOrWhiteSpace(dutySafedpRacd))
{
throw new ArgumentException("dutySafedpRacd required", nameof(dutySafedpRacd));
}
return new LockupEvent
{
IssucoCustno = issucoCustno,
KorSecnNm = korSecnNm.Trim(),
SecnKacd = string.IsNullOrWhiteSpace(secnKacd) ? null : secnKacd.Trim(),
ShotnIsin = shotnIsin.Trim(),
MartTpcd = string.IsNullOrWhiteSpace(martTpcd) ? null : martTpcd.Trim(),
OccrSeq = occrSeq.Trim(),
SafedpDt = safedpDt,
SafedpQty = safedpQty,
DutySafedpRacd = dutySafedpRacd.Trim(),
ReturnDt = returnDt,
ReturnQty = returnQty,
TotalStkCnt = totalStkCnt
};
}
}