Skip to content

Date override fixes - #1

Open
linxia0415 wants to merge 11 commits into
mainfrom
pr-8330
Open

Date override fixes#1
linxia0415 wants to merge 11 commits into
mainfrom
pr-8330

Conversation

@linxia0415

Copy link
Copy Markdown

What does this PR do?

This PR fixes that date overrides of fixed hosts are taken into account for round-robin events. This prevents round-robin events being booked where the fixed hosts are unavailable.

This PR also fixes that date overrides didn't adjust to different timezones. If the organizer has a date override from 10-11 UTC it always showed the slots from 10-11 open no matter what timezone the attendee has.

Fixes #8207
Fixes #8329

Fixes: #8273

Environment: Staging(main branch) / Production

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How should this be tested?

Date overrides for fixed hosts (round-robin):

  • Create a round-robin event with one fixed host and host round-robin host
  • Create a date override for fixed host (round-robin host should also be available at that time)
  • Check available slots of event on the day of the date override, it should only show the slots where fixed host is available
  • Test that with different time zones on booking page and on the availabilities of fixed and round-robin host

Date override timezones issue:

  • Create a date override
  • Go to the booking page of a personal event
  • Change the timezone to a different one that the availability with the date override is
  • See the available slots of the day with the date override change accordingly
  • Also test with different timezones here

@code-hawk-sit code-hawk-sit Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查摘要

  • packages/lib/slots.ts: 发现重复调用 dayjs() 两次,造成性能冗余,已委托深审并确认。
  • packages/trpc/server/routers/viewer/slots.ts: 发现时区校验缺失、工作时间检查逻辑错误(start/end 时间相同),影响可用性判断,已委托深审并确认。
  • 其余文件:batch 审计通过,无高危问题。

CodeHawk 提供支持 · nuwa

}
);

const scheduleForEventOnADayWithDateOverrideDifferentTimezone = await getSchedule(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

测试用例中新增了对不同时区(+6:00)的 getSchedule 调用,但注释说明‘it should return the same as this is the utc time’存在误导性。实际逻辑中,getSchedule 的行为可能受时区影响,若未正确处理 UTC 时间转换,可能导致返回结果不一致。该注释暗示行为应相同,但未验证函数是否真正忽略时区差异,存在潜在逻辑错误风险。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 788

💬 详细说明:

  • 测试用例中新增了对不同时区(+6:00)的 getSchedule 调用,但注释说明‘it should return the same as this is the utc time’存在误导性。实际逻辑中,getSchedule 的行为可能受时区影响,若未正确处理 UTC 时间转换,可能导致返回结果不一致。该注释暗示行为应相同,但未验证函数是否真正忽略时区差异,存在潜在逻辑错误风险。

📝 问题代码:

const scheduleForEventOnADayWithDateOverrideDifferentTimezone = await getSchedule(

💡 修复建议:

移除误导性注释,或在代码中明确确保 getSchedule 在输入为 UTC 时间且 timeZone 不同时仍能正确处理时间边界。建议添加断言验证时区转换后的结果一致性,或重构逻辑以保证跨时区调用行为一致。

✅ 修复示例:



🔗 参考链接

Comment thread packages/lib/slots.ts
dayjs(override.start).utc().add(offset, "minute").hour() * 60 +
dayjs(override.start).utc().add(offset, "minute").minute(),
endTime:
dayjs(override.end).utc().add(offset, "minute").hour() * 60 +

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 AI 代码审查发现问题

📋 问题概述

发现 2 个邻近问题(第 219–222 行)

📍 问题详情

🔴 问题 1 | 严重程度: HIGH | 行号: 219

💬 详细说明:

  • 每次处理覆盖时间时都会重复执行相同的日期转换操作,增加不必要的计算开销,特别是在大量覆盖数据情况下会影响性能;若 offset 超出合理范围,可能引发时间计算异常,导致系统行为不可控。

📝 问题代码:

dayjs(override.start).utc().add(offset, "minute").hour() * 60 + dayjs(override.start).utc().add(offset, "minute").minute()

💡 修复建议:

提取公共表达式,避免重复计算;同时添加对 offset 的有效性校验,确保其在合理范围内(例如 ±1440 分钟)。建议缓存 dayjs(override.start).utc().add(offset, "minute") 的结果,然后分别获取小时和分钟。

✅ 修复示例:

const adjustedStart = dayjs(override.start).utc().add(offset, "minute");
      return {
        userIds: override.userId ? [override.userId] : [],
        startTime: adjustedStart.hour() * 60 + adjustedStart.minute(),
        endTime: dayjs(override.end).utc().add(offset, "minute").hour() * 60 + dayjs(override.end).utc().add(offset, "minute").minute(),
      };
🔴 问题 2 | 严重程度: HIGH | 行号: 222

💬 详细说明:

  • 每次处理覆盖时间时都会重复执行相同的日期转换操作,增加不必要的计算开销,特别是在大量覆盖数据情况下会影响性能;同时存在因 offset 超出合理范围导致时间计算错误的风险。

📝 问题代码:

dayjs(override.end).utc().add(offset, "minute").hour() * 60 + dayjs(override.end).utc().add(offset, "minute").minute()

💡 修复建议:

提取公共表达式,避免重复计算;同时添加对 offset 的有效性校验,确保其在合理范围内(例如 ±1440 分钟)。

✅ 修复示例:

const adjustedEnd = dayjs(override.end).utc().add(offset, "minute");
      return {
        userIds: override.userId ? [override.userId] : [],
        startTime: adjustedStart.hour() * 60 + adjustedStart.minute(),
        endTime: adjustedEnd.hour() * 60 + adjustedEnd.minute(),
      };

🔗 参考链接

busy,
eventLength,
dateOverrides = [],
workingHours = [],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

发现 2 个邻近问题(第 79–80 行)

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 79

💬 详细说明:

  • 函数 checkIfIsAvailable 的参数 dateOverrides 被默认初始化为空数组,但其类型定义为可选(?),且在调用方传入时未明确处理空值。这可能导致后续逻辑误判:当实际无日期覆盖时,仍会进入 dateOverrides.find 判断分支,造成不必要的计算和潜在逻辑错误。

📝 问题代码:

dateOverrides = []

💡 修复建议:

将 dateOverrides 的默认值改为 null,并在函数内部显式判断是否为 null 或空数组,避免对空数组的无效遍历。同时更新函数签名以反映该参数可能为 null。

✅ 修复示例:

dateOverrides = null
🟡 问题 2 | 严重程度: MEDIUM | 行号: 80

💬 详细说明:

  • workingHours 参数被默认初始化为空数组,但其类型为 WorkingHours[],且在函数中用于判断工作时间范围。若用户未设置任何工作时间,空数组会导致后续 find 检查始终返回 false,从而错误地认为所有时间段都处于非工作时间,导致可用性判断失效。

📝 问题代码:

workingHours = []

💡 修复建议:

将 workingHours 默认值设为 null,并在函数内增加对 null/undefined 的检查,确保不因空数组而误判。同时更新函数签名以体现该参数可为 null。

✅ 修复示例:

workingHours = null

🔗 参考链接

workingHours.find((workingHour) => {
if (workingHour.days.includes(slotStartTime.day())) {
const start = slotStartTime.hour() * 60 + slotStartTime.minute();
const end = slotStartTime.hour() * 60 + slotStartTime.minute();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

在 workingHours 检查逻辑中,start 和 end 变量被设置为相同的值(都基于 slotStartTime),这会导致工作时间检查逻辑错误

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 142

💬 详细说明:

  • 工作时间检查逻辑错误,可能导致错误的时间槽可用性判断,影响日程安排功能的准确性

📝 问题代码:

const start = slotStartTime.hour() * 60 + slotStartTime.minute();
        const end = slotStartTime.hour() * 60 + slotStartTime.minute();

💡 修复建议:

正确设置 start 和 end 时间,start 应基于 slotStartTime,end 应基于 slotEndTime

✅ 修复示例:

const start = slotStartTime.hour() * 60 + slotStartTime.minute();
        const end = slotEndTime.hour() * 60 + slotEndTime.minute();

🔗 参考链接

frequency: eventType.slotInterval || input.duration || eventType.length,
organizerTimeZone:
eventType.timeZone || eventType?.schedule?.timeZone || userAvailability?.[0]?.timeZone,
organizerTimeZone,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 AI 代码审查发现问题

📋 问题概述

在 getTimeSlots 调用中传递 organizerTimeZone,但该参数未经过校验或默认值处理。若输入的 timeZone 为非法值(如 'invalid/timezone'),可能导致 dayjs.tz() 内部异常或返回错误时间,进而影响整个日程生成逻辑,存在潜在崩溃风险。

📍 问题详情

🔴 问题 1 | 严重程度: HIGH | 行号: 456

💬 详细说明:

  • 在 getTimeSlots 调用中传递 organizerTimeZone,但该参数未经过校验或默认值处理。若输入的 timeZone 为非法值(如 'invalid/timezone'),可能导致 dayjs.tz() 内部异常或返回错误时间,进而影响整个日程生成逻辑,存在潜在崩溃风险。

📝 问题代码:

organizerTimeZone

💡 修复建议:

在调用 getTimeSlots 前,对 organizerTimeZone 进行有效性验证,若无效则使用默认值(如 'UTC')或抛出错误,防止不可控的时间解析行为。

✅ 修复示例:

organizerTimeZone: organizerTimeZone && dayjs.tz.isValid(organizerTimeZone) ? organizerTimeZone : 'UTC'

🔗 参考链接

time: slot.time,
...schedule,
...availabilityCheckProps,
organizerTimeZone: schedule.timeZone,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

在 checkIfIsAvailable 中,organizerTimeZone 被重复从 schedule.timeZone 传入,但该值已在上层调用中通过 organizerTimeZone 参数统一传递。此重复赋值冗余且易引发维护歧义,若未来修改调度逻辑,可能造成不一致。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 492

💬 详细说明:

  • 在 checkIfIsAvailable 中,organizerTimeZone 被重复从 schedule.timeZone 传入,但该值已在上层调用中通过 organizerTimeZone 参数统一传递。此重复赋值冗余且易引发维护歧义,若未来修改调度逻辑,可能造成不一致。

📝 问题代码:

organizerTimeZone: schedule.timeZone

💡 修复建议:

移除该行中的 organizerTimeZone 重传,直接使用外部传入的 organizerTimeZone 参数,保持上下文一致性。

✅ 修复示例:

organizerTimeZone

🔗 参考链接

time: slot.time,
...userSchedule,
...availabilityCheckProps,
organizerTimeZone: userSchedule.timeZone,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

在 looseHostAvailability 处理逻辑中,organizerTimeZone 从 userSchedule.timeZone 重新传入,但该值与外部传入的 organizerTimeZone 语义相同。重复赋值造成代码冗余,且若两者不一致,将破坏时间一致性,引入潜在 bug。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 517

💬 详细说明:

  • 在 looseHostAvailability 处理逻辑中,organizerTimeZone 从 userSchedule.timeZone 重新传入,但该值与外部传入的 organizerTimeZone 语义相同。重复赋值造成代码冗余,且若两者不一致,将破坏时间一致性,引入潜在 bug。

📝 问题代码:

organizerTimeZone: userSchedule.timeZone

💡 修复建议:

统一使用外部传入的 organizerTimeZone,移除此处的重复赋值,确保时间上下文一致。

✅ 修复示例:

organizerTimeZone

🔗 参考链接

time: slot.time,
busy,
...availabilityCheckProps,
organizerTimeZone: userSchedule?.timeZone,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

在 selectedSlots 处理逻辑中,organizerTimeZone 从 userSchedule.timeZone 传入,但该值应与全局 organizerTimeZone 保持一致。若 userSchedule.timeZone 为空或不一致,将导致时间偏移错误,影响可用性判断。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 585

💬 详细说明:

  • 在 selectedSlots 处理逻辑中,organizerTimeZone 从 userSchedule.timeZone 传入,但该值应与全局 organizerTimeZone 保持一致。若 userSchedule.timeZone 为空或不一致,将导致时间偏移错误,影响可用性判断。

📝 问题代码:

organizerTimeZone: userSchedule?.timeZone

💡 修复建议:

统一使用外部传入的 organizerTimeZone,避免局部变量干扰,确保时间逻辑一致性。

✅ 修复示例:

organizerTimeZone

🔗 参考链接

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants