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 }; } }