fix(hr): correct document-expiry date formulas — CEL has no Timestamp+int#93
Merged
Conversation
…+int
`hr_document.is_expiring_soon` and `expiry_status` used `today() + 30` /
`today() + 60` to build the reminder windows. The formula engine is CEL,
where dates are Timestamps and there is no `Timestamp + int` operator — so
`today() + 30` evaluated to null and every comparison against it silently
failed. Net effect: `is_expiring_soon` was always false and `expiry_status`
never returned the `expiring_30d` / `expiring_60d` bands (only expired / valid
/ none), so the expiry-reminder flow had nothing to fire on.
Fix — use the `daysFromNow(n)` builtin (which returns the Timestamp n days
out) instead of `today() + n`:
expires_at <= daysFromNow(30) // was (today() + 30)
expires_at <= daysFromNow(60) // was (today() + 60)
Boot-verified against a fresh dev server (@objectstack 15.1.1, 0 errors) —
the seeded documents now band correctly:
- expires in ~15d → is_expiring_soon = true, expiry_status = expiring_30d
- expires next year → is_expiring_soon = false, expiry_status = valid
- expired 10d ago → is_expired = true, expiry_status = expired
- no expiry date → expiry_status = none
Note: `hr_employee.tenure_years` has a related but distinct defect
(`floor((today() - hire_date) / 365)` — CEL has neither `Timestamp - Timestamp`
→ number nor a `floor` builtin, and the intended `daysBetween()` primitive is
declared in @objectstack/formula's type list but not wired into the runtime,
so it returns null). That one can't be fixed at the template level without a
working date-diff builtin, so it is intentionally left for a framework
follow-up rather than worked around with an unreadable bucketed ternary.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZguyAaQbyUpwMZ2gMLaAP
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug(与 compliance #92 同一类根因)
hr_document.is_expiring_soon/expiry_status用today() + 30/today() + 60来算提醒窗口。formula 引擎是 CEL,日期是 Timestamp,没有Timestamp + int运算符 —— 所以today() + 30求值为 null,针对它的比较全部静默失败。结果:is_expiring_soon永远是 false,expiry_status永远返回不了expiring_30d/expiring_60d两档(只会给 expired / valid / none)—— 到期提醒 flow 因此没有东西可触发。修复
用
daysFromNow(n)builtin(返回 n 天后的 Timestamp)替掉today() + n:验证(fresh dev server,@objectstack 15.1.1,0 错误)
seed 里的文档现在分档正确:
关于
hr_employee.tenure_years(本 PR 未改)它有一个相关但不同的缺陷:
floor((today() - hire_date) / 365)—— CEL 里Timestamp - Timestamp不是数字、也没有floorbuiltin,而本该用的daysBetween()原语虽然在@objectstack/formula的类型清单里声明了,却没有实际 wire 进运行时(实测调用返回 null)。所以这个字段在模板层面修不了(除非拿一个十几层的 bucket 三元表达式硬凑,不适合作参考代码)。已在 commit message 里留了说明,建议作为 framework 侧 follow-up(把daysBetween接上,或补一个可用的 date-diff builtin)。影响
纯模板改动,不改 framework。修 2 个到期公式;tenure 留给 framework。
Generated by Claude Code