|
|
@@ -7,6 +7,8 @@
|
|
|
// 1. 方案两级回退:campus_id 命中 → 回退 campus_id=0(机构级);
|
|
|
// 2. 规则三级回退:个人(teacher_id=uid)→ 持证通用(teacher_id 空 + teacher_cert=1)→ 无证通用(teacher_cert=0);
|
|
|
// 3. grade_id / subject_id 支持 −1 通配;教龄区间用 BETWEEN(teacher_exp_min..max)。
|
|
|
+// 教龄列保留 **decimal(6,3)**(源 float(10,3)):教龄不是金额、没有"分"的概念;
|
|
|
+// 收敛到 2 位会把 0.999 变成 1.00,使相邻两档**并列命中** ⇒ 课酬按错档位算(D7 双跑必红)。
|
|
|
//
|
|
|
// 无可用方案 → 3112(apperr.ErrPayrollPlanMissing)。
|
|
|
//
|
|
|
@@ -36,7 +38,7 @@ type CoursePayment struct {
|
|
|
EffectDate *time.Time `gorm:"index:idx_inst_campus_actived_effect,priority:4;column:effect_date" json:"effectDate,omitempty"` // 生效日期(datetime(3);取 effect_date<=当前 最新一条)|枚举:无|写入:创建/编辑|FK:无|红线:同机构校区多方案按本列 DESC 取首条
|
|
|
Actived bool `gorm:"index:idx_inst_campus_actived_effect,priority:3;column:actived;not null;default:0" json:"actived"` // 是否生效(bit(1)→tinyint(1)/bool)|枚举:false/true|写入:启用/停用|FK:无|红线:仅 actived=true 参与匹配
|
|
|
CreateUserID *string `gorm:"column:create_user_id;size:26" json:"createUserId,omitempty"` // 创建人(ULID;原 create_userid)|枚举:无|写入:创建|FK:→ t_user(逻辑)|红线:禁止旧 int id
|
|
|
- CreateTime time.Time `gorm:"column:create_time;not null;default:CURRENT_TIMESTAMP" json:"createTime"` // 创建时间(datetime(3))|枚举:无|写入:DB 默认|FK:无|红线:勿手改
|
|
|
+ CreateTime time.Time `gorm:"column:create_time;not null;default:CURRENT_TIMESTAMP" json:"createTime"` // 创建时间(datetime(3))|枚举:无|写入:DB 默认|FK:无|红线:勿手改
|
|
|
Memo *string `gorm:"column:memo;type:longtext" json:"memo,omitempty"` // 备注|枚举:无|写入:创建/编辑|FK:无|红线:脱敏
|
|
|
}
|
|
|
|
|
|
@@ -48,23 +50,23 @@ func (CoursePayment) TableName() string { return "t_course_payment" }
|
|
|
// grade_id / subject_id 支持 −1 通配(匹配逻辑保留旧口径,设计 §3.4 #26);
|
|
|
// percentage 为 1 位小数的百分比数字部分(如 65.5 表示 65.5%)。
|
|
|
type CoursePaymentDetail struct {
|
|
|
- ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // 明细 ID(D3 自增)|枚举:无|写入:INSERT 自动|FK:无|红线:试算按 id ASC 取首条命中(回退优先级靠查询顺序)
|
|
|
- CoursePaymentID int64 `gorm:"index:idx_payment;column:course_payment_id;not null" json:"coursePaymentId"` // 课酬方案 ID(原 course_paymentid)|枚举:无|写入:创建规则时|FK:→ t_course_payment.id|红线:方案停用即整组失效
|
|
|
- GradeID int32 `gorm:"column:grade_id;not null;default:-1" json:"gradeId"` // 年级 ID(-1 所有/0 混合)|枚举:−1 通配 + 年级字典|写入:创建规则|FK:→ 教学域年级|红线:−1 通配逻辑不得写成 `= -1` 强制条件
|
|
|
- SubjectID int32 `gorm:"column:subject_id;not null;default:-1" json:"subjectId"` // 科目 ID(-1 所有/0 混合)|枚举:−1 通配 + 科目字典|写入:创建规则|FK:→ 教学域科目|红线:同上
|
|
|
- ClassType int32 `gorm:"index:idx_teacher_classify,priority:2;column:class_type;not null;default:0" json:"classType"` // 班级类型(对应 t_courses_classify.class_type)|枚举:班型编码|写入:创建规则|FK:弱关联 t_courses_classify.class_type|红线:匹配维度
|
|
|
- ClassifyID int64 `gorm:"index:idx_teacher_classify,priority:3;column:classify_id;not null;default:0" json:"classifyId"` // 课程分类 ID(原 classifyid;个人配置维度)|枚举:无|写入:创建规则|FK:→ t_courses_classify.id|红线:0=不限定分类
|
|
|
- TeacherID *string `gorm:"index:idx_teacher_classify,priority:1;column:teacher_id;size:26" json:"teacherId,omitempty"` // 老师(ULID;NULL/空=通用规则)|枚举:无|写入:个人规则时|FK:→ t_user(逻辑)|红线:三级回退的第一级判据(个人优先)
|
|
|
- Name *string `gorm:"column:name;size:300" json:"name,omitempty"` // 计算方式名称|枚举:无|写入:创建规则|FK:无|红线:展示转义
|
|
|
- Percentage string `gorm:"column:percentage;type:decimal(5,1);not null;default:0.0" json:"percentage"` // 课酬比例(百分比数字部分,1 位小数;旧 float(10,1))|枚举:0~100 常见|写入:创建规则|FK:无|红线:精度例外列;参与计算须走整数运算(分×比例→四舍五入)
|
|
|
- MinPayment string `gorm:"column:min_payment;type:decimal(12,2);not null;default:0.00" json:"minPayment"` // 最低课酬标准(元)|枚举:无|写入:创建规则|FK:无|红线:<= max_payment(0 表示不限制)
|
|
|
- MaxPayment string `gorm:"column:max_payment;type:decimal(12,2);not null;default:0.00" json:"maxPayment"` // 最高课酬标准(元)|枚举:无|写入:创建规则|FK:无|红线:0 表示不限制
|
|
|
- Reward string `gorm:"column:reward;type:decimal(12,2);not null;default:0.00" json:"reward"` // 额外课酬(元)|枚举:无|写入:创建规则|FK:无|红线:在比例基础上追加
|
|
|
- TeacherCert bool `gorm:"index:idx_cert_exp,priority:1;column:teacher_cert;not null;default:0" json:"teacherCert"` // 是否持证(bit(1)→tinyint(1)/bool)|枚举:false 无证/true 持证|写入:创建规则|FK:弱关联 t_teacher_information.teacher_cert|红线:第二级回退判据(持证通用)
|
|
|
- TeacherExpMin string `gorm:"index:idx_cert_exp,priority:2;column:teacher_exp_min;type:decimal(6,2);not null;default:0.00" json:"teacherExpMin"` // 教龄下限(年;旧 float(10,3) → 2 位)|枚举:无|写入:创建规则|FK:无|红线:精度例外列;BETWEEN 匹配
|
|
|
- TeacherExpMax string `gorm:"index:idx_cert_exp,priority:3;column:teacher_exp_max;type:decimal(6,2);not null;default:0.00" json:"teacherExpMax"` // 教龄上限(年)|枚举:无|写入:创建规则|FK:无|红线:>= teacher_exp_min
|
|
|
- Actived bool `gorm:"column:actived;not null;default:0" json:"actived"` // 是否生效(bit(1)→tinyint(1)/bool)|枚举:false/true|写入:启用/停用|FK:无|红线:仅 true 参与匹配
|
|
|
- Memo *string `gorm:"column:memo;type:longtext" json:"memo,omitempty"` // 备注|枚举:无|写入:创建/编辑|FK:无|红线:脱敏
|
|
|
+ ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // 明细 ID(D3 自增)|枚举:无|写入:INSERT 自动|FK:无|红线:试算按 id ASC 取首条命中(回退优先级靠查询顺序)
|
|
|
+ CoursePaymentID int64 `gorm:"index:idx_payment;column:course_payment_id;not null" json:"coursePaymentId"` // 课酬方案 ID(原 course_paymentid)|枚举:无|写入:创建规则时|FK:→ t_course_payment.id|红线:方案停用即整组失效
|
|
|
+ GradeID int32 `gorm:"column:grade_id;not null;default:-1" json:"gradeId"` // 年级 ID(-1 所有/0 混合)|枚举:−1 通配 + 年级字典|写入:创建规则|FK:→ 教学域年级|红线:−1 通配逻辑不得写成 `= -1` 强制条件
|
|
|
+ SubjectID int32 `gorm:"column:subject_id;not null;default:-1" json:"subjectId"` // 科目 ID(-1 所有/0 混合)|枚举:−1 通配 + 科目字典|写入:创建规则|FK:→ 教学域科目|红线:同上
|
|
|
+ ClassType int32 `gorm:"index:idx_teacher_classify,priority:2;column:class_type;not null;default:0" json:"classType"` // 班级类型(对应 t_courses_classify.class_type)|枚举:班型编码|写入:创建规则|FK:弱关联 t_courses_classify.class_type|红线:匹配维度
|
|
|
+ ClassifyID int64 `gorm:"index:idx_teacher_classify,priority:3;column:classify_id;not null;default:0" json:"classifyId"` // 课程分类 ID(原 classifyid;个人配置维度)|枚举:无|写入:创建规则|FK:→ t_courses_classify.id|红线:0=不限定分类
|
|
|
+ TeacherID *string `gorm:"index:idx_teacher_classify,priority:1;column:teacher_id;size:26" json:"teacherId,omitempty"` // 老师(ULID;NULL/空=通用规则)|枚举:无|写入:个人规则时|FK:→ t_user(逻辑)|红线:三级回退的第一级判据(个人优先)
|
|
|
+ Name *string `gorm:"column:name;size:300" json:"name,omitempty"` // 计算方式名称|枚举:无|写入:创建规则|FK:无|红线:展示转义
|
|
|
+ Percentage string `gorm:"column:percentage;type:decimal(5,1);not null;default:0.0" json:"percentage"` // 课酬比例(百分比数字部分,1 位小数;旧 float(10,1))|枚举:0~100 常见|写入:创建规则|FK:无|红线:精度例外列;参与计算须走整数运算(分×比例→四舍五入)
|
|
|
+ MinPayment string `gorm:"column:min_payment;type:decimal(12,2);not null;default:0.00" json:"minPayment"` // 最低课酬标准(元)|枚举:无|写入:创建规则|FK:无|红线:<= max_payment(0 表示不限制)
|
|
|
+ MaxPayment string `gorm:"column:max_payment;type:decimal(12,2);not null;default:0.00" json:"maxPayment"` // 最高课酬标准(元)|枚举:无|写入:创建规则|FK:无|红线:0 表示不限制
|
|
|
+ Reward string `gorm:"column:reward;type:decimal(12,2);not null;default:0.00" json:"reward"` // 额外课酬(元)|枚举:无|写入:创建规则|FK:无|红线:在比例基础上追加
|
|
|
+ TeacherCert bool `gorm:"index:idx_cert_exp,priority:1;column:teacher_cert;not null;default:0" json:"teacherCert"` // 是否持证(bit(1)→tinyint(1)/bool)|枚举:false 无证/true 持证|写入:创建规则|FK:弱关联 t_teacher_information.teacher_cert|红线:第二级回退判据(持证通用)
|
|
|
+ TeacherExpMin string `gorm:"index:idx_cert_exp,priority:2;column:teacher_exp_min;type:decimal(6,3);not null;default:0.000" json:"teacherExpMin"` // 教龄下限(年;旧 float(10,3) → **保留 3 位**)|枚举:无|写入:创建规则|FK:无|红线:精度例外列;BETWEEN 匹配;**收敛到 2 位会改变区间命中集合**(0.999→1.00 ⇒ [0.000,1.000] 与 [1.000,1.999] 并列命中,课酬按错档位算)
|
|
|
+ TeacherExpMax string `gorm:"index:idx_cert_exp,priority:3;column:teacher_exp_max;type:decimal(6,3);not null;default:0.000" json:"teacherExpMax"` // 教龄上限(年;**保留 3 位**,理由同 teacher_exp_min)|枚举:无|写入:创建规则|FK:无|红线:>= teacher_exp_min
|
|
|
+ Actived bool `gorm:"column:actived;not null;default:0" json:"actived"` // 是否生效(bit(1)→tinyint(1)/bool)|枚举:false/true|写入:启用/停用|FK:无|红线:仅 true 参与匹配
|
|
|
+ Memo *string `gorm:"column:memo;type:longtext" json:"memo,omitempty"` // 备注|枚举:无|写入:创建/编辑|FK:无|红线:脱敏
|
|
|
}
|
|
|
|
|
|
// TableName 指定表名。
|
|
|
@@ -75,11 +77,11 @@ func (CoursePaymentDetail) TableName() string { return "t_course_payment_detail"
|
|
|
// 作用域:**无** institution_id/campus_id(教师是平台级人员属性,跨机构共享)——
|
|
|
// Repository 不继承 BaseRepo,越权断言在 Service 层(设计 §1.7 例外一)。
|
|
|
type TeacherInformation struct {
|
|
|
- TeacherID string `gorm:"column:teacher_id;primaryKey;size:26;not null" json:"teacherId"` // 老师(ULID;原 teacherid,主键)|枚举:无|写入:首次填资质时|FK:→ t_user(逻辑)|红线:一人一行
|
|
|
- TeacherCert bool `gorm:"column:teacher_cert;not null;default:0" json:"teacherCert"` // 教师资格证(bit(1)→tinyint(1)/bool;0 无/1 有)|枚举:false/true|写入:资质维护|FK:无|红线:课酬第二级回退判据
|
|
|
- TeacherExp *time.Time `gorm:"column:teacher_exp;type:date" json:"teacherExp,omitempty"` // 教龄起算日(date)|枚举:无|写入:资质维护|FK:无|红线:教龄年数由本列与试算日期差算出,勿存冗余年数
|
|
|
- CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"createdAt"` // 创建时间(datetime(3))|枚举:无|写入:DB 默认|FK:无|红线:勿手改
|
|
|
- UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP" json:"updatedAt"` // 更新时间(datetime(3),ON UPDATE)|枚举:无|写入:DB 自动|FK:无|红线:勿手改
|
|
|
+ TeacherID string `gorm:"column:teacher_id;primaryKey;size:26;not null" json:"teacherId"` // 老师(ULID;原 teacherid,主键)|枚举:无|写入:首次填资质时|FK:→ t_user(逻辑)|红线:一人一行
|
|
|
+ TeacherCert bool `gorm:"column:teacher_cert;not null;default:0" json:"teacherCert"` // 教师资格证(bit(1)→tinyint(1)/bool;0 无/1 有)|枚举:false/true|写入:资质维护|FK:无|红线:课酬第二级回退判据
|
|
|
+ TeacherExp *time.Time `gorm:"column:teacher_exp;type:date" json:"teacherExp,omitempty"` // 教龄起算日(date)|枚举:无|写入:资质维护|FK:无|红线:教龄年数由本列与试算日期差算出,勿存冗余年数
|
|
|
+ CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"createdAt"` // 创建时间(datetime(3))|枚举:无|写入:DB 默认|FK:无|红线:勿手改
|
|
|
+ UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP" json:"updatedAt"` // 更新时间(datetime(3),ON UPDATE)|枚举:无|写入:DB 自动|FK:无|红线:勿手改
|
|
|
}
|
|
|
|
|
|
// TableName 指定表名。
|
|
|
@@ -104,8 +106,8 @@ type TeacherCoursesPercentage struct {
|
|
|
MinReward string `gorm:"column:min_reward;type:decimal(12,2);not null;default:0.00" json:"minReward"` // 最小课酬(元/一次课)|枚举:无|写入:配置时|FK:无|红线:0=不限制
|
|
|
MinRewardExtend *string `gorm:"column:min_reward_extend;size:500" json:"minRewardExtend,omitempty"` // 最小课酬扩展(原样保留)|枚举:旧扩展串格式|写入:配置时|FK:无|红线:同上
|
|
|
EffectiveDate *time.Time `gorm:"column:effective_date;type:date" json:"effectiveDate,omitempty"` // 课酬生效日期(date)|枚举:无|写入:配置时|FK:无|红线:取 <= 试算日期的最新一条
|
|
|
- CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"createdAt"` // 创建时间(datetime(3))|枚举:无|写入:DB 默认|FK:无|红线:勿手改
|
|
|
- UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP" json:"updatedAt"` // 更新时间(datetime(3),ON UPDATE)|枚举:无|写入:DB 自动|FK:无|红线:勿手改
|
|
|
+ CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"createdAt"` // 创建时间(datetime(3))|枚举:无|写入:DB 默认|FK:无|红线:勿手改
|
|
|
+ UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP" json:"updatedAt"` // 更新时间(datetime(3),ON UPDATE)|枚举:无|写入:DB 自动|FK:无|红线:勿手改
|
|
|
}
|
|
|
|
|
|
// TableName 指定表名。
|
|
|
@@ -128,18 +130,18 @@ func (Expenditure) TableName() string { return "t_expenditure" }
|
|
|
//
|
|
|
// year/month 为报表分桶冗余列(原 year year 类型 / month tinyint),保留以避免月度报表改 SQL。
|
|
|
type ExpenditureLog struct {
|
|
|
- ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // 记录 ID(D3 自增)|枚举:无|写入:INSERT 自动|FK:无|红线:对外单号是 biz_no
|
|
|
- BizNo string `gorm:"uniqueIndex:uk_biz_no;column:biz_no;size:32;not null" json:"bizNo"` // 业务单号(旧 UUID 原样保留;UNIQUE)|枚举:无|写入:记账时|FK:迁移/回滚锚点|红线:不可变
|
|
|
- InstitutionID int64 `gorm:"index:idx_inst_campus_time,priority:1;column:institution_id;not null;default:0" json:"institutionId"` // 机构 ID(原 schoolid;作用域列)|枚举:无|写入:记账时|FK:→ t_institution|红线:scoping 强依赖
|
|
|
- CampusID int64 `gorm:"index:idx_inst_campus_time,priority:2;column:campus_id;not null;default:0" json:"campusId"` // 校区 ID(原 campusid;作用域列)|枚举:无|写入:记账时|FK:→ t_campus|红线:同上
|
|
|
- ExpenditureID int64 `gorm:"index:idx_expenditure;column:expenditure_id;not null;default:0" json:"expenditureId"` // 收支类型 ID(原 expenditureid)|枚举:无|写入:记账时|FK:→ t_expenditure.id|红线:决定支出/收入方向
|
|
|
- Cost string `gorm:"column:cost;type:decimal(12,2);not null;default:0.00" json:"cost"` // 费用(元;旧 float(10,3) 收敛)|枚举:无|写入:记账时|FK:无|红线:符号由 type 决定,本列存正数
|
|
|
- CreateUserID *string `gorm:"column:create_user_id;size:26" json:"createUserId,omitempty"` // 创建人(ULID;原 create_userid)|枚举:无|写入:记账时|FK:→ t_user(逻辑)|红线:禁止旧 int id
|
|
|
- CreateTime time.Time `gorm:"index:idx_inst_campus_time,priority:3;column:create_time;not null;default:CURRENT_TIMESTAMP" json:"createTime"` // 创建时间(datetime(3))|枚举:无|写入:DB 默认|FK:无|红线:勿手改
|
|
|
- Year *int16 `gorm:"index:idx_year_month,priority:1;column:year" json:"year,omitempty"` // 收支年份(报表分桶冗余列,原 year 类型)|枚举:如 2026|写入:记账时冗余|FK:无|红线:与 create_time 年份须一致(一致性校验)
|
|
|
- Month *int8 `gorm:"index:idx_year_month,priority:2;column:month" json:"month,omitempty"` // 收支月份(报表分桶冗余列,原 month tinyint)|枚举:1~12|写入:记账时冗余|FK:无|红线:同上
|
|
|
- Remark *string `gorm:"column:remark;type:longtext" json:"remark,omitempty"` // 备注|枚举:无|写入:记账时|FK:无|红线:脱敏
|
|
|
- Imgs *string `gorm:"column:imgs;type:longtext" json:"-"` // 图片地址(JSON 直存)|枚举:无|写入:记账时|FK:无|红线:**凭证可能含敏感信息,json:"-"**(按需授权下载)
|
|
|
+ ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // 记录 ID(D3 自增)|枚举:无|写入:INSERT 自动|FK:无|红线:对外单号是 biz_no
|
|
|
+ BizNo string `gorm:"uniqueIndex:uk_biz_no;column:biz_no;size:32;not null" json:"bizNo"` // 业务单号(旧 UUID 原样保留;UNIQUE)|枚举:无|写入:记账时|FK:迁移/回滚锚点|红线:不可变
|
|
|
+ InstitutionID int64 `gorm:"index:idx_inst_campus_time,priority:1;column:institution_id;not null;default:0" json:"institutionId"` // 机构 ID(原 schoolid;作用域列)|枚举:无|写入:记账时|FK:→ t_institution|红线:scoping 强依赖
|
|
|
+ CampusID int64 `gorm:"index:idx_inst_campus_time,priority:2;column:campus_id;not null;default:0" json:"campusId"` // 校区 ID(原 campusid;作用域列)|枚举:无|写入:记账时|FK:→ t_campus|红线:同上
|
|
|
+ ExpenditureID int64 `gorm:"index:idx_expenditure;column:expenditure_id;not null;default:0" json:"expenditureId"` // 收支类型 ID(原 expenditureid)|枚举:无|写入:记账时|FK:→ t_expenditure.id|红线:决定支出/收入方向
|
|
|
+ Cost string `gorm:"column:cost;type:decimal(12,2);not null;default:0.00" json:"cost"` // 费用(元;旧 float(10,3) 收敛)|枚举:无|写入:记账时|FK:无|红线:符号由 type 决定,本列存正数
|
|
|
+ CreateUserID *string `gorm:"column:create_user_id;size:26" json:"createUserId,omitempty"` // 创建人(ULID;原 create_userid)|枚举:无|写入:记账时|FK:→ t_user(逻辑)|红线:禁止旧 int id
|
|
|
+ CreateTime time.Time `gorm:"index:idx_inst_campus_time,priority:3;column:create_time;not null;default:CURRENT_TIMESTAMP" json:"createTime"` // 创建时间(datetime(3))|枚举:无|写入:DB 默认|FK:无|红线:勿手改
|
|
|
+ Year *int16 `gorm:"index:idx_year_month,priority:1;column:year" json:"year,omitempty"` // 收支年份(报表分桶冗余列,原 year 类型)|枚举:如 2026|写入:记账时冗余|FK:无|红线:与 create_time 年份须一致(一致性校验)
|
|
|
+ Month *int8 `gorm:"index:idx_year_month,priority:2;column:month" json:"month,omitempty"` // 收支月份(报表分桶冗余列,原 month tinyint)|枚举:1~12|写入:记账时冗余|FK:无|红线:同上
|
|
|
+ Remark *string `gorm:"column:remark;type:longtext" json:"remark,omitempty"` // 备注|枚举:无|写入:记账时|FK:无|红线:脱敏
|
|
|
+ Imgs *string `gorm:"column:imgs;type:longtext" json:"-"` // 图片地址(JSON 直存)|枚举:无|写入:记账时|FK:无|红线:**凭证可能含敏感信息,json:"-"**(按需授权下载)
|
|
|
}
|
|
|
|
|
|
// TableName 指定表名。
|