campus.go 4.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Package port academic 域跨域只读接口(**academic 定义,org 侧实现/注入**)。
  2. //
  3. // 依据:unified/03-migration/academic-domain-design.md §1.3(包结构与依赖方向)/ §1.6(跨库跨域收敛)。
  4. //
  5. // 依赖方向铁律:
  6. // - academic → org(单向):本包只定义接口,实现放 port/orgadapter.go(只读转发)+ 装配层注入;
  7. // - org **不得**反向依赖 academic;
  8. // - 禁止跨库 SQL(`yuansiwei.xxx` 前缀)与跨域 JOIN——取数一律经本包接口 + 同事务查询。
  9. //
  10. // 为什么需要 port:
  11. // - 旧 SP `custom_refund` / `cleared_balance` 跨库读 `yuansiwei.t_school_campus.self_support`,
  12. // `cancel_recharge_activity` 读 `school_id`;目标态校区数据归 org 域 `t_campus`(§11.1 拍板 A
  13. // 补 `self_support`),academic 只能通过接口读,不得直接 import org 的仓储做业务判断。
  14. package port
  15. import (
  16. "context"
  17. "gorm.io/gorm"
  18. )
  19. // CampusInfo 校区只读视图(跨域取数的唯一载体,字段裁剪到 academic 所需最小集)。
  20. //
  21. // 字段:
  22. // - CampusID int64:校区 ID(→ t_campus.campus_id)。
  23. // - SchoolID int64:所属机构 ID(旧口径名 schoolid,即 t_campus.institution_id;作用域列取值源)。
  24. // - SelfSupport bool:是否自营校区(t_campus.self_support:1 自营 / 0 加盟);
  25. // 决定 custom_refund / cleared_balance 的活动失效范围(`campus_id IN (x,0)` vs `= x`,设计 §11-2)。
  26. // - Status string:校区状态(active/disabled;disabled 校区禁止发起资金操作)。
  27. type CampusInfo struct {
  28. CampusID int64
  29. SchoolID int64
  30. SelfSupport bool
  31. Status string
  32. }
  33. // InstitutionID 机构 ID 的规范命名访问器(SchoolID 为旧口径字段名,语义等同 institution_id)。
  34. //
  35. // 出参:int64——机构 ID(与 t_campus.institution_id 同值)。
  36. func (c *CampusInfo) InstitutionID() int64 {
  37. if c == nil {
  38. return 0
  39. }
  40. return c.SchoolID
  41. }
  42. // IsActive 校区是否可用(status=active)。
  43. func (c *CampusInfo) IsActive() bool {
  44. return c != nil && c.Status == "active"
  45. }
  46. // CampusReader 校区只读读取器(academic 定义;实现见 OrgCampusReader,可 mock 单测)。
  47. //
  48. // 契约:
  49. // - 校区不存在 → `*infraerrors.AppError{Code: 3104}`(apperr.ErrCampusNotFound),不返回 gorm 原错;
  50. // - 只读,不写 org 表;
  51. // - 同一事务内只读的强一致场景(如退费事务里判自营),用可选的 TxCampusReader 扩展接口。
  52. type CampusReader interface {
  53. // GetByID 按校区 ID 取校区只读视图。
  54. //
  55. // 入参:ctx 请求上下文;campusID 校区 ID(<=0 视为业务参数错 3140)。
  56. // 出参:*CampusInfo(命中);error——apperr.ErrCampusNotFound(3104) / infraerrors.ErrDBError(5002)。
  57. GetByID(ctx context.Context, campusID int64) (*CampusInfo, error)
  58. // GetSchoolID 按校区 ID 取所属机构 ID(旧 SP 的 `SchoolCampusHelper::getInfo($campusid)->school_id`)。
  59. //
  60. // 入参:ctx 请求上下文;campusID 校区 ID。
  61. // 出参:int64 机构 ID;error——apperr.ErrCampusNotFound(3104) / infraerrors.ErrDBError(5002)。
  62. GetSchoolID(ctx context.Context, campusID int64) (int64, error)
  63. // IsSelfSupport 校区是否自营(决定活动失效范围的判据,设计 §1.6 / §11-2)。
  64. //
  65. // 入参:ctx 请求上下文;campusID 校区 ID。
  66. // 出参:bool 自营=true;error——apperr.ErrCampusNotFound(3104) / infraerrors.ErrDBError(5002)。
  67. IsSelfSupport(ctx context.Context, campusID int64) (bool, error)
  68. }
  69. // TxCampusReader 同事务只读扩展接口(可选实现)。
  70. //
  71. // 使用场景:资金事务内需要"与写操作同一快照"的校区判定(旧 SP 是同库 JOIN 语义),
  72. // 传 tx 保证读到的校区行与事务可见性一致;不传 tx 的 GetByID 走连接池默认隔离级别。
  73. type TxCampusReader interface {
  74. // GetByIDTx 在给定事务句柄上读取校区(只读,不写)。
  75. //
  76. // 入参:ctx 请求上下文;tx 事务句柄(可为 nil → 退化到连接池);campusID 校区 ID。
  77. // 出参:*CampusInfo;error 语义同 CampusReader.GetByID。
  78. GetByIDTx(ctx context.Context, tx *gorm.DB, campusID int64) (*CampusInfo, error)
  79. }