用 Grist 关系表搭建课程报名管理流程

当业务表格开始同时记录课程、教师、学员、家庭和缴费状态,困难通常不是“还缺一列”,而是同一条信息已经在很多地方重复出现。Grist 官方的课后活动教程用一个儿童课程机构作例子,展示如何先规划关系,再把关联的表组织成方便日常使用的页面。

本文据 Grist Help Center 的 How to manage business data 全文翻译整理。可以从空白文档手工建立所有表;原文提供的 CSV 和 模板只是节省录入时间的可选路线。下面沿用英文表名与字段名,方便对照公式和界面。

先想清楚两种日常工作

这个机构开设多门课程,每门课由一位教师负责,并容纳多名学员。一个孩子可以报名多门课,也可能下一年继续回来。工作人员一方面需要选中课程,看到已报名的学员和剩余名额;另一方面需要在家长来电时,快速添加、调整或取消孩子的报名。

不必一开始就预见所有功能。先把当前实体和操作场景理顺,后续可以逐步增加家庭资料、付款信息和其他层次。这个过程同时是在设计数据库和搭建应用,不过实际操作仍然围绕表格、公式和视图展开。

Grist 课程报名关系图:教师关联课程,家庭关联学员,课程与学员通过报名表形成多对多关系
未完纪根据原文关系模型绘制;每条箭头标明一对多关系,图中未使用真实儿童资料。

建立 Classes 和 Staff:把教师资料从课程中分离

同一位教师可以教授多门课程,因此教师与课程应放在不同的表里。每门课程只需保存指向教师记录的引用,避免在每门课程中反复录入教师姓名和联络资料。

  1. 创建一个空白 Grist 文档,把最初的 Table1 改名为 Classes,添加课程需要的列,并录入几门虚构课程。也可以使用原文的 Classes.csv。
  2. 点击 Add New → Add Empty Table,把新表改名为 Staff,添加教师字段并录入虚构记录。可选样例为 Staff.csv。
  3. 准备让 Classes 中的 Instructor 列指向 Staff。先为教师记录增加一个便于识别的姓名显示列。

用公式生成 Full Name

进入 Staff 页面,通过列菜单或 Alt + = 快捷键添加列,将其命名为 Full Name。在新列任意单元格以等号开始输入公式,公式内容为:

$Last_Name + ", " + $First_Name

也可以使用类似 Excel 的函数写法:

CONCAT($Last_Name, ", ", $First_Name)

Grist 的公式列对整个表中每一行生效,因此不需要逐行拖拽填充。它既支持 Python 表达式,也支持许多使用大写名称的 Excel 风格函数。计算后,每位教师都会显示为“姓, 名”。界面显示名 Full Name 与公式中的标识符可能带下划线,编写公式时应使用 Grist 显示的实际列 ID。

编者说明:原文把完整姓名作为方便识别每条记录的列,但现实中的同名教师或同名学员并不少见。Full Name 是显示标签,不应被当成永不重复的业务主键;引用实际指向 Grist 的记录身份。需要对外对账或去重时,可另设稳定的教师、学员或家庭编号。

把 Instructor 转成 Reference 引用列

  1. 返回 Classes 页面,打开 Instructor 列的 Column Options。
  2. 在右侧面板把 Column Type 设置为 Reference,被引用表选择 Staff。
  3. 在 SHOW COLUMN 中选择刚才的 Full Name。
  4. 点击 Apply 完成类型转换。若原列为空,可能不需要额外确认。

引用列类似数据库中的外键。现在点击 Instructor 单元格,可以按 Enter 从已有教师中选择,也可以输入部分文字自动补全。这样改动教师资料时,不必逐门课程去维护副本。已有文字转为引用后,应逐条确认匹配结果,尤其注意同名或拼写差异。

建立 Students,并用 Enrollments 保存多对多关系

再创建 Students 表,记录学员姓名、年级等信息;也可以导入 Students.csv。像 Staff 一样添加 Full Name 公式列,方便后续显示和选择。

学员与课程不能简单地放进单一引用列:一个孩子会参加多门课程,一门课程也有很多孩子,还需要保留过去的课程和报名历史。合适的做法是新增 Enrollments 表。它的一条记录表示“某位学员报名某门课程”,这条关联本身还可以保存报名状态、是否缴费等属性。

原文使用三个报名状态:Confirmed(已确认)、Waitlisted(候补)和 Cancelled(已取消)。这张连接表把多对多关系拆为两个一对多关系:一个学员对应多条报名,一门课程也对应多条报名。

  1. 创建 Enrollments 表,或导入可选的 Enrollments.csv。
  2. 把 Student 列设为 Reference,引用 Students,SHOW COLUMN 选择 Full Name。
  3. 把 Class 列设为 Reference,引用 Classes,SHOW COLUMN 选择 Class Code。
  4. 添加状态、付款等需要的列。可以直接在连接表中新增一行,再通过自动补全选择学员和课程。

取消报名时修改状态,可以保留曾经发生的关联与付款历史。直接删除关联行会失去这些信息。至于同一学员是否可重复报同一课程、每期课程怎样区分,应按实际业务另行定义;连接表的存在本身不会自动完成所有去重规则。

建立 Class View:选课程看报名

第一个工作页面围绕课程展开。

  1. 点击 Add New → Add Page,在组件选择器中选择显示 Classes 的 Table,再点击 Add Page;将页面改名为 Class View。
  2. 再点 Add New → Add Widget to Page,选择 Enrollments 的 Table;把 SELECT BY 设为 CLASSES,然后 Add to Page。
  3. 页面现在有两个关联表格。选中一门课程,报名组件只显示这门课对应的报名记录,并包含学员引用及报名状态等信息。
  4. 继续 Add Widget to Page,为 Classes 添加 Card,SELECT BY 仍选择 CLASSES,让选中课程的详细信息更集中。
  5. 为 Staff 添加 Card,SELECT BY 选择 CLASSES • Instructor,即可展示所选课程的教师资料。

卡片右上角三点菜单中的 Widget options 可以打开设置;在右侧 Theme 下选择 Compact,会得到紧凑样式。之后隐藏重复或无关字段,调整组件位置,让课程列表、课程详情、教师卡片和报名表各自负责清晰的任务。

建立 Enrollment View:选学员办理报名

第二个页面从学员出发。点击 Add New → Add Page,选择 Students 表格并把页面命名为 Enrollment View。然后 Add Widget to Page,添加 Enrollments 表格,将 SELECT BY 设置为 STUDENTS。

点击左侧某位学员,右侧就会显示其全部报名。在这个已关联的报名组件底部空白行中输入课程代码,便能新增报名;Student 会按当前关联选择自动带入,Class 引用列继续提供自动补全。因此 Student 列可以在此组件隐藏,避免重复显示当前已经选中的姓名。

如果希望在报名表里同时看到上课时间,打开 Class 列的 Column Options,点击侧边栏的 + Add Column,选择课程中的字段。原文以 Times 为例,生成的实际上是引用取值公式:

$Class.Times

课程资料因此仍保留在 Classes 中;报名组件只是按关联读取相应值,没有手动复制一份需要单独维护的时间信息。

增加 Families:让来电操作从家庭开始

给儿童办理课程报名时,工作人员通常与家长沟通。可以把家长联络资料直接加到 Students,但若一个家庭有多个孩子,这些资料又会重复。原文因此增加 Families 表,记录家长姓名与联络方式,并让每个孩子引用一个家庭记录。

  1. 添加 Families 表,可选使用 Families.csv。同样添加 Full Name 公式列。
  2. 在 Students 表增加 Family 列,设为 Reference,引用 Families。
  3. 若原列已有家庭姓名,转换引用时会尝试按文字匹配;新资料则可以像其他引用列一样自动补全。真实数据需要核对同名、重复记录和空值。
  4. 回到 Enrollment View,新增 Families 表格组件,调整布局,使家庭位于左侧,Students 和 Enrollments 位于右侧。
  5. 打开 STUDENTS 组件右上角三点菜单,选择 Data Selection,在侧边栏把 SELECT BY 改为 FAMILIES。原有 Enrollments 继续跟随 Students。
  6. 按需要补充所选家庭和所选学员的 Card,重新排列字段与组件。

此时操作顺序变成:选家长或家庭,看到其孩子;再选孩子,看到其报名。工作人员可以增加课程报名、把某条状态改为 Cancelled、添加同一家庭的另一个孩子,或者建立新的家庭记录。

计算已确认人数与剩余名额

官方示例文档在上述流程之外,为 Classes 增加了 Count 与 Spots Left 两个字段。Count 的公式是:

len(Enrollments.lookupRecords(Class=$id, Status="Confirmed"))

$id 是当前课程记录的 ID;lookupRecords 在 Enrollments 中找出 Class 引用该课程、且状态恰好为 Confirmed 的记录,len 再计算数量。候补和已取消记录不计入这个值,重复的已确认报名则会各算一条。因此列 ID、状态拼写与重复数据都影响结果。

Spots Left 用最大人数减去已确认人数,最低显示为零;当结果为零时显示 Full:

max($Max_Students - $Count, 0) or "Full"
Grist 原文课程视图截图,展示 Count 与 Spots Left 列计算课程剩余名额
Grist Help Center 原图:课程人数与剩余名额。原样保存,来源见文末;不是本次执行教程所得截图。

编者核查:这是便于工作人员观察的显示公式,不是并发报名锁或数据库约束。两人同时办理报名时,不能指望这个单元格自动阻止超额;还需要业务规则与合适的写入校验。另外,这个公式会把零名额和超额都显示为 Full,不能用它识别超额幅度。若要单独追踪超额,可另设数值列 $Max_Students - $Count,并保留负数;这是编者建议,未在原教程中提供或测试。

使用边界与来源

练习时仅使用虚构家庭与儿童资料。若要投入实际业务,应先确定哪些工作人员能查看或修改各张表,并合理限制家庭联络方式、儿童资料和导出文件的访问。隐藏列或隐藏组件只是界面整理,不能替代访问规则。

本文完整覆盖原文的规划、数据建模、公式、引用、多对多关系、课程视图、报名视图、家庭层次与人数计算。来源:How to manage business data — Grist Help Center;原页未单列个人作者和明确发表日期,本稿不推定。原图:spots-left.png,归属 Grist。本文经授权翻译整理,不用产品代码许可证推定帮助文档转载权。

本次只读原文并静态核对公式、关联方向与操作说明;未创建 Grist 文档、导入 CSV、执行公式或操作真实报名。编者补充的唯一性、权限和并发边界已单独标出。

文档许可与改编说明

原始 Grist Help Center 文档及相关原图:Copyright 2022 Grist Labs Inc.。官方 grist-help 文档仓库依据 Creative Commons Attribution-ShareAlike 4.0 International(CC BY-SA 4.0) 提供内容。本文保留各处原文链接及图片归属;中文翻译、结构整理、明确标示的技术补充和原创示意图同样依 CC BY-SA 4.0 提供。修改与原文结论已在相应段落区分,不暗示原作者为本译稿背书。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容