batch3_model.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package fixture
  2. import (
  3. "database/sql"
  4. "time"
  5. )
  6. // 本文件是**第三批(org 域)的数据形状**:机构 t_institution + 校区 t_campus。
  7. //
  8. // 口径(已拍板):
  9. // - **两张表都走 D1**:`t_school.id` → `t_institution.institution_id`、`t_school_campus.id`
  10. // → `t_campus.campus_id`,**原值插入**。理由:两者都是 int 自然主键、数据量极小,
  11. // 而 institution_id / campus_id 在几十张表里是裸 int,双跑要靠 id 直接对齐;
  12. // 走 biz_no 反而要多一跳。
  13. // - **只迁数据用得到的机构**,不全量迁 t_school(61905 行里 61900 行与本项目无关)。
  14. // - `campus_id = 0` **不建行**:0 是"机构级/未分配"的约定值(DDL 里 `campus_id ... DEFAULT 0
  15. // COMMENT '校区ID(0=平台级/机构级)'`),建了会让前端校区下拉框多出一个"未知校区"。
  16. // OrgOptions 是第三批的取样参数。
  17. type OrgOptions struct {
  18. // InstitutionIDs 是要迁移的机构 id 集合(D1 原值)。
  19. //
  20. // 这是**显式决策**,不是从数据里自动推导的:多迁一个机构 = 多一个孤儿机构;
  21. // 少迁一个 = 引用它的一整批数据变成孤儿引用。集合必须由人确认。
  22. InstitutionIDs []int64
  23. // WithAllCampuses 是否迁移所选机构的**全部**校区(true)
  24. // 还是只迁数据里出现过的校区(false)。默认 true:机构迁了、校区不迁会让
  25. // 前端校区下拉框与机构对不上,且属于 org 域自身的不一致。
  26. WithAllCampuses bool
  27. OrgSourceDB string
  28. }
  29. // DefaultOrgOptions 是默认取样 = **7 个机构**。
  30. //
  31. // ⚠ 初版统计给的是 5 个(`SELECT DISTINCT schoolid FROM t_courses` + campus 1/2 的 school_id=1),
  32. // 实测逐来源清点后发现**漏了 2 个**,各自都带孤儿引用:
  33. //
  34. // 63332(用户注册)← finance_bk.t_user_balance_request 1 行(schoolid=63332, campusid=57)
  35. // 63330(弘毅教育)← finance_bk.t_courses_classify 1 行(schoolid=63330)
  36. // —— 这张表不在原统计的 7 个来源清单里,是靠"按列名反查"找出来的
  37. //
  38. // 只迁 5 个会让这两个来源各留 1 条孤儿机构 + 1 条孤儿校区(实测见报告)。
  39. func DefaultOrgOptions() OrgOptions {
  40. return OrgOptions{
  41. InstitutionIDs: []int64{1, 63317, 63323, 63324, 63325, 63330, 63332},
  42. WithAllCampuses: true,
  43. OrgSourceDB: "yuansiwei_i",
  44. }
  45. }
  46. // ---------- legacy(yuansiwei_i) ----------
  47. // LegacySchool 对应 `yuansiwei_i.t_school`。
  48. type LegacySchool struct {
  49. ID int64
  50. Name string
  51. ProvinceID int64
  52. CityID int64
  53. DistrictID int64
  54. GradePeriod string
  55. Status int8 // tinyint(1):1=正常 0=停用(业务口径,见 mapping 注释)
  56. IsOpenUserLogin int8
  57. }
  58. // LegacyCampus 对应 `yuansiwei_i.t_school_campus`。
  59. type LegacyCampus struct {
  60. ID int64
  61. Name string
  62. SchoolID int64
  63. ProvinceID int64
  64. CityID int64
  65. DistrictID int64
  66. Status int8
  67. Code sql.NullString
  68. SelfSupport int8 // bit(1) → 0/1
  69. IsOpenUserLogin int8
  70. }
  71. // ---------- target ----------
  72. // TargetInstitution 对应 `t_institution`(16 列里只用得到的那些)。
  73. type TargetInstitution struct {
  74. InstitutionID int64
  75. InstitutionName string
  76. InstitutionCode sql.NullString // legacy 无对应列 → NULL(uk_institution_code 允许多 NULL)
  77. Address sql.NullString // legacy 只有省市区 id,没有地址文本 → NULL
  78. Phone sql.NullString // legacy 无 → NULL
  79. Status string // active / disabled
  80. CreatedAt time.Time // legacy 无时间列 → epoch 哨兵
  81. UpdatedAt time.Time
  82. }
  83. // TargetCampus 对应 `t_campus`。
  84. type TargetCampus struct {
  85. CampusID int64
  86. InstitutionID int64
  87. CampusName string
  88. CampusCode sql.NullString // legacy code(varchar(16))→ campus_code
  89. Address sql.NullString
  90. Phone sql.NullString
  91. Status string
  92. SelfSupport int8 // bit(1) → TINYINT(1)
  93. CreatedAt time.Time
  94. UpdatedAt time.Time
  95. }
  96. // ---------- 引用完整性 ----------
  97. // RefSource 是一个「带 institution_id / campus_id 的数据来源」。
  98. type RefSource struct {
  99. Table string // finance_bk 里的表名
  100. InstCol string // 机构列
  101. CampusCol string // 校区列(空 = 该表没有校区列)
  102. Note string
  103. }
  104. // RefStat 是一个来源的引用统计结果。
  105. type RefStat struct {
  106. Source string
  107. Rows int64 // 该表总行数
  108. DistinctInst int // distinct institution_id
  109. DistinctCampus int // distinct campus_id(不含 0)
  110. OrphanInst int64 // institution_id 在 target 里找不到的行数
  111. OrphanCampus int64 // campus_id != 0 但在 target 里找不到的行数
  112. CampusZeroRows int64 // campus_id = 0(机构级,不建行)的行数
  113. OrphanInstList []string
  114. OrphanCampusList []string
  115. }