ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Cal.diy API v2 排期(Schedules)管理完全指南:从可用性规则到组织级日程编排

Cal.diy API v2 排期(Schedules)管理完全指南:从可用性规则到组织级日程编排 Cal.diy API v2 排期Schedules管理完全指南从可用性规则到组织级日程编排【免费下载链接】cal.diyScheduling infrastructure for absolutely everyone.项目地址: https://gitcode.com/GitHub_Trending/ca/cal.diy本篇指南围绕 Cal.diyCal.comPlatform API v2 的/v2/schedules端点族展开系统讲解可用性Availability排期的核心概念、CRUD 请求/响应字段、输入输出时间格式差异并结合仓库内 NestJS 控制器、服务与仓库层源码解析默认排期、日期覆盖、版本头与权限校验的底层实现。读完你将能够独立设计业务时间周一到周五 9–17 点、拆分时段、按天差异化、周末支持等与节假日覆盖规则并通过 slots 端点验证排期是否真正生效。Schedules 是什么定义何时可被预订的规则载体Schedules排期/日程规则在 Cal.diy 中用来定义某个用户何时可以被预约。当一个事件类型event type被预约时系统会依据它绑定的排期而非默认排期来计算可用时段。围绕排期有四个关键概念Working Hours工作时间/常规周可用性例如每周一至周五 09:00–17:00 的可约时段以重复性规则存在Date Overrides日期覆盖对某一具体日期生效的例外规则例如节假日不可约、某天临时缩短为半天Timezone时区定义可用性时所基于的时区排期是时区感知timezone-aware的Default Schedule默认排期当事件类型未显式绑定任何排期时系统回退使用的那个排期每个用户应当有且仅有一个默认排期。在数据层面一条排期PrismaSchedule下属的可用性和覆盖都被落在一张Availability表中可用性行的date字段为null而覆盖行的date字段不为null。这一点在仓库的更新实现中体现得很直接见 schedules.repository.ts 的注释与删除条件。端点总览MethodEndpointDescriptionGET/v2/schedules列出当前用户的所有排期POST/v2/schedules创建排期GET/v2/schedules/default获取默认排期GET/v2/schedules/{scheduleId}获取单个排期PATCH/v2/schedules/{scheduleId}更新排期仅传需修改的字段DELETE/v2/schedules/{scheduleId}删除排期此外面向组织Organization/Team场景还有一组子资源端点详见下文组织/团队排期一节。认证、权限与版本控制头所有 schedule 端点都受两层守卫保护并带有版本与权限要求。以 2024-06-11 控制器为例见 schedules.controller.ts认证ApiAuthGuard与PermissionsGuard。支持的凭据是 API Key 或 OAuth 访问令牌通过Authorization: Bearer token或对应 API key 头传入权限读操作需要SCHEDULE_READ写操作创建/更新/删除需要SCHEDULE_WRITE对应源码中的Permissions([SCHEDULE_READ])/Permissions([SCHEDULE_WRITE])版本头必须携带cal-api-version: 2024-06-11请求头。该控制器同时注册了VERSION_2024_06_14与VERSION_2024_06_11两个版本若不传该头会默认落到较旧版本的端点导致字段语义不同详见下文时间与日期的两种书写方式。相关版本常量定义在 api-versionsVERSION_2024_06_14、VERSION_2024_06_11。提示控制器中Get(/default)声明在Get(/:scheduleId)之前是有意为之——NestJS 按声明顺序匹配路由先注册的default字面量路由避免被动态参数:scheduleId吞掉。列出排期GET /v2/schedules返回当前认证用户的所有排期。典型响应如下{ status: success, data: [ { id: 1, name: Working Hours, isDefault: true, timeZone: America/New_York, workingHours: [ { days: [1, 2, 3, 4, 5], startTime: 540, endTime: 1020 } ], availability: [ { id: 1, days: [1, 2, 3, 4, 5], startTime: 1970-01-01T09:00:00.000Z, endTime: 1970-01-01T17:00:00.000Z } ], dateOverrides: [], isManaged: false, readOnly: false, isLastSchedule: false } ] }该示例展示的是旧版本输出中的两种并存表示workingHours使用距零点分钟数540 9:001020 17:00availability使用锚定在1970-01-01的 ISO 时间串。而在 2024-06-11 版本中输出对象ScheduleOutput_2024_06_11的结构为id、ownerId、name、timeZone、isDefault以及用英文星期名与HH:MM表示的availability与overrides定义见 schedule.output.ts。创建排期POST /v2/schedules请求体示例POST /v2/schedules cal-api-version: 2024-06-11 Authorization: Bearer your_token Content-Type: application/json{ name: Working Hours, timeZone: America/New_York, isDefault: true, availability: [ { days: [Monday, Tuesday, Wednesday, Thursday, Friday], startTime: 09:00, endTime: 17:00 } ], overrides: [ { date: 2024-12-25, startTime: 00:00, endTime: 00:00 } ] }字段说明CreateScheduleInput_2024_06_11FieldTypeRequiredDescriptionnamestring是排期名称如 Catch up hourstimeZonestring是IANA 时区标识符如Europe/Rome预订时用于换算可约时间isDefaultboolean是*是否设为默认排期。每个用户应有 1 个默认排期事件类型未绑定排期时回退到它availabilityarray否每周可用性规则。不传时默认生成周一至周五 09:00–17:00overridesarray否具体日期的覆盖规则注以上字段约束来自 create-schedule.input.ts。其中isDefault在 DTO 层面标注为必填布尔值而availability/overrides缺省时由 input-schedules.service.ts 注入周一至周五 09:00–17:00这一默认可用性。文档中对isDefault标记为否因此以省略 availability 使用默认值、default 排期语义按用户意图设置来理解更稳妥。timeZone校验使用了 class-validator 的IsTimeZone()name为普通字符串。注意所有时间输入含覆盖都必须匹配HH:MM24 小时制格式底层正则见 constants.ts/^([01]\d|2[0-3]):([0-5]\d)$/——小时范围 00–23、分钟范围 00–59。Availability可用性对象每个对象描述周几 时间段的组合FieldTypeDescriptiondaysarray生效的星期集合2024-06-11 版本用英文星期名Monday…Sunday枚举WEEK_DAYS旧版用数字0Sunday、1Monday … 6SaturdaystartTimestring开始时间格式HH:MM24 小时制endTimestring结束时间格式HH:MM24 小时制Date Override日期覆盖对象FieldTypeDescriptiondatestring日期格式YYYY-MM-DDIsISO8601({ strict: true })校验startTimestring开始时间HH:MM。设为不可约在 2024-06-11 版本中的语义旧文档习惯以null表示整天不可约而新版本输入层会调用createDateFromHoursMinutes解析HH:MM字符串endTimestring结束时间HH:MM语义同上获取默认排期GET /v2/schedules/defaultGET /v2/schedules/default cal-api-version: 2024-06-11 Authorization: Bearer your_token返回当前用户的默认排期。服务层实现先读取用户记录中的defaultScheduleId再回表查询排期并做输出转换见 schedules.service.ts。获取单个排期GET /v2/schedules/{scheduleId}路径参数scheduleId为数字类型的排期 ID。服务层会先校验排期存在再通过checkUserOwnsSchedule确认该排期属于当前认证用户否则抛出ForbiddenExceptionGET /v2/schedules/42{ status: success, data: { id: 42, ownerId: 478, name: Working Hours, timeZone: America/New_York, availability: [ { days: [Monday, Tuesday, Wednesday, Thursday, Friday], startTime: 09:00, endTime: 17:00 } ], isDefault: true, overrides: [] } }更新排期PATCH /v2/schedules/{scheduleId}只传希望变更的字段即可全字段可选{ name: Updated Schedule Name, availability: [ { days: [Monday, Tuesday, Wednesday, Thursday, Friday], startTime: 08:00, endTime: 18:00 } ] }请求体类型定义见 update-schedule.input.tsname、timeZone、availability、isDefault、overrides均为可选。若本次更新将isDefault置为true服务层会同步调用usersRepository.setDefaultSchedule(userId, scheduleId)把该排期登记为用户默认排期。更新在仓库层遵循先删后建策略提交availability时删除该排期下所有date null的行再重建提交overrides时删除所有date ! null的行再重建从而避免残留脏数据实现见 schedules.repository.ts。删除排期DELETE /v2/schedules/{scheduleId}DELETE /v2/schedules/42 cal-api-version: 2024-06-11 Authorization: Bearer your_token成功时返回{ status: success }HTTP 200。注意不允许删除最后一个排期——系统要求每个用户至少保留一条排期底层仓库提供getUserSchedulesCount用于此类约束判断见 schedules.repository.ts。删除不属于当前用户的排期同样会被checkUserOwnsSchedule拒绝。时间与日期的两种书写方式Working Hours Format围绕/v2/schedules存在多种时间表示建议区分输入格式与输出格式1. 距零点分钟数常见于旧版输出的 workingHours{ workingHours: [ { days: [1, 2, 3, 4, 5], startTime: 540, endTime: 1020 } ] }540 9:00 AM9 × 60 分钟1020 5:00 PM17 × 60 分钟2. ISO 时间串锚定 1970-01-01常见于旧版输出的 availability{ availability: [ { days: [1, 2, 3, 4, 5], startTime: 1970-01-01T09:00:00.000Z, endTime: 1970-01-01T17:00:00.000Z } ] }3.HH:MM24 小时制创建/更新时的输入格式2024-06-11 版本同时用于输出{ startTime: 09:00, endTime: 17:00 }当传入HH:MM时输入转换服务会解析出小时与分钟做范围校验小时 0–23、分钟 0–59再封装为Date.UTC(1970, 0, 1, hours, minutes)的Date落库而days中的英文星期名WeekDay会被映射为数字下标Sunday: 0, Monday: 1, …, Saturday: 6。这两段逻辑可分别在 input-schedules.service.ts 与同文件的transformDayToNumber中验证。兼容提示由于旧版本端点如不传cal-api-version时默认命中的版本使用数字星期与 ISO/分钟数表示而新版本要求英文星期名与HH:MM混用会造成请求被校验拒绝或响应字段语义偏差。务必固定版本头并依据对应版本构造负载。常用排期模式可直接套用以下负载均可直接用于创建或更新availability需将days换成英文星期名、时间保持HH:MM。标准工作时间周一至周五 9–17 点{ name: Business Hours, timeZone: America/New_York, isDefault: true, availability: [ { days: [Monday, Tuesday, Wednesday, Thursday, Friday], startTime: 09:00, endTime: 17:00 } ] }拆分时段上午 下午中间留午休{ name: Split Hours, timeZone: America/New_York, availability: [ { days: [Monday, Tuesday, Wednesday, Thursday, Friday], startTime: 09:00, endTime: 12:00 }, { days: [Monday, Tuesday, Wednesday, Thursday, Friday], startTime: 14:00, endTime: 18:00 } ] }每天不同时段如周一三五早、周二四晚{ name: Variable Hours, timeZone: America/New_York, availability: [ { days: [Monday, Wednesday, Friday], startTime: 09:00, endTime: 17:00 }, { days: [Tuesday, Thursday], startTime: 10:00, endTime: 19:00 } ] }周末可用{ name: Weekend Support, timeZone: America/New_York, availability: [ { days: [Saturday, Sunday], startTime: 10:00, endTime: 14:00 } ] }节假日覆盖整天不可约在overrides中将某一天的起止时间留空旧版字段语义为null即表示当天关闭。新增多条覆盖只需追加数组元素{ overrides: [ { date: 2024-12-25, startTime: null, endTime: null }, { date: 2024-01-01, startTime: null, endTime: null } ] }若使用 2024-06-11 版本该对象仍以HH:MM校验时间字段日期须满足YYYY-MM-DD如需表达当天不可约请结合目标版本的契约确认null或等效语义旧版文档以null表达不可用。特殊时段覆盖如平安夜半天{ overrides: [ { date: 2024-12-24, startTime: 09:00, endTime: 12:00 } ] }覆盖优先级高于常规可用性同一日期存在覆盖时以其起止时间为准。组织/团队排期端点当由平台客户platform customer托管组织与成员时可通过嵌套路由对组织内用户的排期做管理。参考文档给出的端点族如下GET /v2/organizations/{orgId}/schedules GET /v2/organizations/{orgId}/users/{userId}/schedules POST /v2/organizations/{orgId}/users/{userId}/schedules GET /v2/organizations/{orgId}/teams/{teamId}/users/{userId}/schedules{orgId}/{teamId}/{userId}组织、团队与成员用户 ID前两组用于列出/创建某用户在组织内的排期最后一条用于读取团队内某成员在团队事件上下文下的排期语义上它们与用户级 schedule 端点一致默认排期、可用性、覆盖规则相同区别在于资源归属从认证用户自身改为组织作用域内被管理的用户。源码级原理一条排期请求在服务端如何流转将上文各端点串联起来一次排期操作的完整链路是守卫与鉴权ApiAuthGuard解析 API Key / Access Token 得到用户PermissionsGuard校验SCHEDULE_READ/SCHEDULE_WRITEschedules.controller.ts输入归一化InputSchedulesService把英文星期名映射为 0–6 数字、把HH:MM字符串解析为Date.UTC(1970,0,1,hh,mm)并注入缺省可用性input-schedules.service.ts归属校验对已存在的排期checkUserOwnsSchedule(userId, schedule)校验schedule.userId userId不通过则 403schedules.service.ts默认排期登记创建或更新时若isDefaulttrue调用usersRepository.setDefaultSchedule回写用户记录schedules.service.ts持久化SchedulesRepository将可用性/覆盖写入同一张Availability表更新采用按date是否为空分别删除后重建的策略schedules.repository.ts输出转换OutputSchedulesService.getResponseSchedule把落库数据还原为对外 DTO星期名、HH:MM等。值得特别说明的两点业务语义事件类型与排期的绑定关系事件类型可以被指向某条非默认排期此时预订可用性不再按默认排期计算而是按该事件绑定的排期计算控制器 OpenAPI 描述中明确提到创建非默认排期后通过 PATCHevent-types/{eventTypeId}把事件类型指向该排期。服务层getUserSchedules(userId, eventTypeId?)甚至支持传入事件类型 ID 反查其生效排期解析顺序为eventType.scheduleId ?? user.defaultScheduleId ?? null团队事件则再叠加host.scheduleId的优先层级逻辑见 schedules.service.ts。托管用户的默认排期如果你是平台客户并已创建托管用户managed user那么每个托管用户都应当具备一条默认排期创建托管用户时若传了timeZone系统会自动以该时区生成周一至周五 09:00–17:00的默认排期对应createUserDefaultSchedule见 schedules.service.ts若未传时区则需要通过本端点显式创建并传isDefault: true。在用户拥有默认排期之前该用户既无法被预订也无法通过AvailabilitySettingsatom 管理排期。最佳实践始终显式指定时区排期是时区感知的缺失或错误时区会直接导致可约时段偏移校验由IsTimeZone()完成务必使用合法 IANA 标识符。克制使用日期覆盖日期覆盖面向一次性例外节假日、调休、临时休假。若是周期性模式如每周三下午开会应创建独立排期而非堆叠覆盖。创建后验证可用性排期本身只是规则可用性是否真正生效需结合 slots 端点核验。创建/更新排期后可调用/v2/slots参见仓库内 slots-availability.md查询某时间窗内产出的可预订 slot确认时段、时区与覆盖均符合预期。缓冲时间放在事件类型而非排期上会议间隔buffer time属于事件类型的设置项不要试图用排期时段去模拟缓冲二者职责不同。固定版本头务必携带cal-api-version: 2024-06-11或在 2024-06-14 支持范围内使用对应版本否则请求会落到旧版端点并遭遇字段/格式不一致的问题。默认排期只保留一条遵循每人一条默认排期约定通过isDefault转移而不是创建多条 default避免预订回退出现歧义。小结Cal.diy API v2 的 schedules 体系用排期 可用性 日期覆盖 默认排期四要素完整刻画了一个用户的周而复始与临时例外。无论你是普通用户管理个人可约时间、还是平台客户为托管用户批量编排组织与团队的可用性都可以通过本文的端点说明与可复制的负载模板快速落地而当你想深挖实现时仓库内 控制器、服务层、输入输出转换 与 类型契约 是继续阅读的最佳起点。【免费下载链接】cal.diyScheduling infrastructure for absolutely everyone.项目地址: https://gitcode.com/GitHub_Trending/ca/cal.diy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表