SeibroIssuerCode.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. using System.ComponentModel.DataAnnotations;
  2. namespace Domain.Entities.Stocks;
  3. /// <summary>
  4. /// SEIBro 시장별 단축코드 ↔ 발행회사번호 매핑 (getShotnByMart) — (Market, ShortCode) UNIQUE.
  5. /// ISSUCO_CUSTNO 는 SEIBro 기업정보 API 전체의 조인키라 Wave 0 에서 가장 먼저 구축한다.
  6. /// K-OTC(13)·기타(50) 등 KRX Stock 이 커버하지 않는 시장의 유일한 종목 마스터이기도 하다
  7. /// (KOSPI/KOSDAQ/KONEX 는 Stock.IssucoCustno 로도 스탬핑되지만 이 테이블이 원본 스냅샷).
  8. /// </summary>
  9. public class SeibroIssuerCode
  10. {
  11. [Key]
  12. public int ID { get; private set; }
  13. /// <summary>시장구분 (MART_TPCD, char 2) — [11]유가 [12]코스닥 [13]K-OTC [14]코넥스 [50]기타</summary>
  14. public string Market { get; private set; } = default!;
  15. /// <summary>단축코드 (SHOTN_ISIN)</summary>
  16. public string ShortCode { get; private set; } = default!;
  17. /// <summary>종목명 (KOR_SECN_NM)</summary>
  18. public string Name { get; private set; } = default!;
  19. /// <summary>발행회사 고객번호 (ISSUCO_CUSTNO) — 예탁결제원 부여</summary>
  20. public int IssucoCustno { get; private set; }
  21. /// <summary>마지막 동기화 시각 (UTC)</summary>
  22. public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow;
  23. private SeibroIssuerCode() { }
  24. public static SeibroIssuerCode Create(string market, string shortCode, string name, int issucoCustno)
  25. {
  26. if (market is not { Length: 2 } || market.Any(c => !char.IsAsciiDigit(c)))
  27. {
  28. throw new ArgumentException("market must be 2 digits (MART_TPCD)", nameof(market));
  29. }
  30. if (string.IsNullOrWhiteSpace(shortCode) || shortCode.Trim().Length > 12)
  31. {
  32. throw new ArgumentException("shortCode required (max 12)", nameof(shortCode));
  33. }
  34. if (string.IsNullOrWhiteSpace(name))
  35. {
  36. throw new ArgumentException("name required", nameof(name));
  37. }
  38. return new SeibroIssuerCode
  39. {
  40. Market = market,
  41. ShortCode = shortCode.Trim(),
  42. Name = name.Trim(),
  43. IssucoCustno = issucoCustno
  44. };
  45. }
  46. /// <summary>재동기화 반영 — 이름/회사번호 변경 시에만 UpdatedAt 갱신 (무변경 upsert 는 no-op)</summary>
  47. public void Update(string name, int issucoCustno)
  48. {
  49. var changed = false;
  50. if (!string.IsNullOrWhiteSpace(name) && Name != name.Trim())
  51. {
  52. Name = name.Trim();
  53. changed = true;
  54. }
  55. if (IssucoCustno != issucoCustno)
  56. {
  57. IssucoCustno = issucoCustno;
  58. changed = true;
  59. }
  60. if (changed)
  61. {
  62. UpdatedAt = DateTime.UtcNow;
  63. }
  64. }
  65. }