| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- package fixture
- import (
- "database/sql"
- "time"
- )
- // 本文件是**第三批(org 域)的数据形状**:机构 t_institution + 校区 t_campus。
- //
- // 口径(已拍板):
- // - **两张表都走 D1**:`t_school.id` → `t_institution.institution_id`、`t_school_campus.id`
- // → `t_campus.campus_id`,**原值插入**。理由:两者都是 int 自然主键、数据量极小,
- // 而 institution_id / campus_id 在几十张表里是裸 int,双跑要靠 id 直接对齐;
- // 走 biz_no 反而要多一跳。
- // - **只迁数据用得到的机构**,不全量迁 t_school(61905 行里 61900 行与本项目无关)。
- // - `campus_id = 0` **不建行**:0 是"机构级/未分配"的约定值(DDL 里 `campus_id ... DEFAULT 0
- // COMMENT '校区ID(0=平台级/机构级)'`),建了会让前端校区下拉框多出一个"未知校区"。
- // OrgOptions 是第三批的取样参数。
- type OrgOptions struct {
- // InstitutionIDs 是要迁移的机构 id 集合(D1 原值)。
- //
- // 这是**显式决策**,不是从数据里自动推导的:多迁一个机构 = 多一个孤儿机构;
- // 少迁一个 = 引用它的一整批数据变成孤儿引用。集合必须由人确认。
- InstitutionIDs []int64
- // WithAllCampuses 是否迁移所选机构的**全部**校区(true)
- // 还是只迁数据里出现过的校区(false)。默认 true:机构迁了、校区不迁会让
- // 前端校区下拉框与机构对不上,且属于 org 域自身的不一致。
- WithAllCampuses bool
- OrgSourceDB string
- }
- // DefaultOrgOptions 是默认取样 = **7 个机构**。
- //
- // ⚠ 初版统计给的是 5 个(`SELECT DISTINCT schoolid FROM t_courses` + campus 1/2 的 school_id=1),
- // 实测逐来源清点后发现**漏了 2 个**,各自都带孤儿引用:
- //
- // 63332(用户注册)← finance_bk.t_user_balance_request 1 行(schoolid=63332, campusid=57)
- // 63330(弘毅教育)← finance_bk.t_courses_classify 1 行(schoolid=63330)
- // —— 这张表不在原统计的 7 个来源清单里,是靠"按列名反查"找出来的
- //
- // 只迁 5 个会让这两个来源各留 1 条孤儿机构 + 1 条孤儿校区(实测见报告)。
- func DefaultOrgOptions() OrgOptions {
- return OrgOptions{
- InstitutionIDs: []int64{1, 63317, 63323, 63324, 63325, 63330, 63332},
- WithAllCampuses: true,
- OrgSourceDB: "yuansiwei_i",
- }
- }
- // ---------- legacy(yuansiwei_i) ----------
- // LegacySchool 对应 `yuansiwei_i.t_school`。
- type LegacySchool struct {
- ID int64
- Name string
- ProvinceID int64
- CityID int64
- DistrictID int64
- GradePeriod string
- Status int8 // tinyint(1):1=正常 0=停用(业务口径,见 mapping 注释)
- IsOpenUserLogin int8
- }
- // LegacyCampus 对应 `yuansiwei_i.t_school_campus`。
- type LegacyCampus struct {
- ID int64
- Name string
- SchoolID int64
- ProvinceID int64
- CityID int64
- DistrictID int64
- Status int8
- Code sql.NullString
- SelfSupport int8 // bit(1) → 0/1
- IsOpenUserLogin int8
- }
- // ---------- target ----------
- // TargetInstitution 对应 `t_institution`(16 列里只用得到的那些)。
- type TargetInstitution struct {
- InstitutionID int64
- InstitutionName string
- InstitutionCode sql.NullString // legacy 无对应列 → NULL(uk_institution_code 允许多 NULL)
- Address sql.NullString // legacy 只有省市区 id,没有地址文本 → NULL
- Phone sql.NullString // legacy 无 → NULL
- Status string // active / disabled
- CreatedAt time.Time // legacy 无时间列 → epoch 哨兵
- UpdatedAt time.Time
- }
- // TargetCampus 对应 `t_campus`。
- type TargetCampus struct {
- CampusID int64
- InstitutionID int64
- CampusName string
- CampusCode sql.NullString // legacy code(varchar(16))→ campus_code
- Address sql.NullString
- Phone sql.NullString
- Status string
- SelfSupport int8 // bit(1) → TINYINT(1)
- CreatedAt time.Time
- UpdatedAt time.Time
- }
- // ---------- 引用完整性 ----------
- // RefSource 是一个「带 institution_id / campus_id 的数据来源」。
- type RefSource struct {
- Table string // finance_bk 里的表名
- InstCol string // 机构列
- CampusCol string // 校区列(空 = 该表没有校区列)
- Note string
- }
- // RefStat 是一个来源的引用统计结果。
- type RefStat struct {
- Source string
- Rows int64 // 该表总行数
- DistinctInst int // distinct institution_id
- DistinctCampus int // distinct campus_id(不含 0)
- OrphanInst int64 // institution_id 在 target 里找不到的行数
- OrphanCampus int64 // campus_id != 0 但在 target 里找不到的行数
- CampusZeroRows int64 // campus_id = 0(机构级,不建行)的行数
- OrphanInstList []string
- OrphanCampusList []string
- }
|