chore: check cycle based on timezone#6461
Conversation
Reviewer's GuideThis PR equips daily cycle checks and progress chart computations with timezone awareness, refactors date utilities to use moment-timezone, updates the worker schedule, and extends the general settings UI to configure and persist TIMEZONE, along with minor route/layout and chart UI tweaks. Class diagram for updated General Settings form and schemaclassDiagram
class TGeneralSettingsProps {
+string TIMEZONE
...other props
}
class generalSettingsSchema {
+TIMEZONE: string
...other schema fields
}
class SelectTimezone {
+render()
}
TGeneralSettingsProps <|-- generalSettingsSchema
GeneralSettings o-- SelectTimezone
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdds timezone-aware date handling across backend cycle utilities and workers, changes the daily cycles scheduler to run hourly, updates project/frontend chart date handling to use moment-timezone, and re-enables General settings with a TIMEZONE field and selector. Also tweaks chart active-dot visuals. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Scheduler as Scheduler (hourly)
participant Worker as operations-daily-cycles-check
participant Config as TRPC Config Service
participant OrgSvc as Orgs Service
participant Queue as Job Queue
participant DB as Cycles DB
Scheduler->>Worker: Trigger job (hourly)
alt SaaS
Worker->>OrgSvc: List orgs
loop each org
Worker->>Queue: Enqueue checkCycle { orgId, timezone? }
end
else Non-SaaS
Worker->>Config: getConfig(TIMEZONE)
Worker->>Queue: Enqueue checkCycle { timezone }
end
Queue-->>Worker: Dequeue checkCycle { timezone }
Worker->>Worker: tzToday = now.tz(timezone)
alt tzToday.hour() == 0
Worker->>Worker: compute utcStart/utcEnd for tz day
par find ended today
Worker->>DB: find cycles with endDate in [utcStart, utcEnd]
and find started today
Worker->>DB: find cycles with startDate in [utcStart, utcEnd]
end
Worker->>Queue: Enqueue per-cycle updates
else
Worker->>Worker: No-op (not midnight in tz)
end
sequenceDiagram
autonumber
actor User
participant Page as GeneralSettings Page
participant Form as React Hook Form
participant API as Config API
Page->>Form: init defaultValues { TIMEZONE = detectTimeZone(), ... }
Form-->>Page: render fields (language, currencies, TIMEZONE)
User->>Form: select/change TIMEZONE
User->>Form: submit
Form->>Page: build merged updatedConfigs (existing + form)
Page->>API: save updatedConfigs (includes TIMEZONE)
API-->>Page: success
Page->>User: toast + updated UI
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Hey there - I've reviewed your changes - here's some feedback:
- You’re mixing date-fns and moment-timezone for similar tasks—consider standardizing on one library and moving recurring timezone/date logic into shared utilities to reduce duplication and confusion.
- The cron job now fires hourly and relies on an in-job midnight check—if possible, schedule jobs at each org’s actual local midnight (e.g. by computing cron patterns per timezone) to avoid extra hourly invocations.
- You fetch the TIMEZONE config in multiple modules—extract that into a single helper or cache it at startup to DRY up the repeated TRPC calls.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- You’re mixing date-fns and moment-timezone for similar tasks—consider standardizing on one library and moving recurring timezone/date logic into shared utilities to reduce duplication and confusion.
- The cron job now fires hourly and relies on an in-job midnight check—if possible, schedule jobs at each org’s actual local midnight (e.g. by computing cron patterns per timezone) to avoid extra hourly invocations.
- You fetch the TIMEZONE config in multiple modules—extract that into a single helper or cache it at startup to DRY up the repeated TRPC calls.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Caution
Changes requested ❌
Reviewed everything up to 7aa0dfe in 2 minutes and 2 seconds. Click for details.
- Reviewed
539lines of code in13files - Skipped
0files when reviewing. - Skipped posting
17draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. backend/plugins/operation_api/src/modules/cycle/utils.ts:130
- Draft comment:
Consider adding error handling around the TRPC call for fetching the timezone to safely fall back if the config is unavailable. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
2. backend/plugins/operation_api/src/modules/cycle/utils.ts:210
- Draft comment:
Verify that removing the $dateToString conversion in the projection (using '_id' directly) yields the expected date string format. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
3. backend/plugins/operation_api/src/modules/cycle/utils.ts:238
- Draft comment:
Using moment’s tz() for cycle start/end conversion is appropriate; ensure that cycle.startDate/endDate are stored in a compatible format. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
4. backend/plugins/operation_api/src/modules/cycle/utils.ts:256
- Draft comment:
The calculation of total days using 'end.diff(start, "days") + 1' looks good; verify that the boundaries are as expected in different timezones. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment is asking the PR author to verify the behavior of the code in different timezones, which falls under asking the author to ensure the behavior is intended. This violates the rules.
5. backend/plugins/operation_api/src/worker/dailyCheckCycles.ts:56
- Draft comment:
Using utcStart and utcEnd for cycle queries ensures timezone alignment; double-check that database timestamps are in UTC. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment is asking the PR author to double-check that database timestamps are in UTC, which violates the rule against asking the author to confirm or double-check things. It does not provide a specific code suggestion or point out a specific issue with the code.
6. backend/plugins/operation_api/src/worker/index.ts:13
- Draft comment:
The job scheduler pattern was changed to '0 * * * *' (hourly). Confirm that this adjustment is intentional to support timezone-based checks. - Reason this comment was not posted:
Comment looked like it was already resolved.
7. frontend/core-ui/src/modules/app/components/SettingsRoutes.tsx:125
- Draft comment:
Uncommenting and lazy-loading GeneralSettings is appropriate; ensure its bundle size and load time remain optimized. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment is asking the author to ensure that the bundle size and load time remain optimized, which falls under the category of asking the author to ensure something is tested or verified. This violates the rules.
8. frontend/core-ui/src/modules/settings/constants/data.ts:125
- Draft comment:
The new 'General' nav item inclusion looks correct; verify that its positioning within the navigation meets design expectations. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%This comment is asking the PR author to verify the positioning of a new navigation item, which falls under asking the author to double-check or ensure something. This violates the rules.
9. frontend/core-ui/src/modules/settings/general/components/GeneralSettings.tsx:27
- Draft comment:
Merging config values using spread operators in updateCurrency is clear; consider explicit handling for missing or invalid config values. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% While the suggestion isn't wrong, it's more of a "nice to have" than a clear issue. The code works as is - undefined/null values will be handled by JavaScript's spread operator. Without seeing the types or validation requirements, we can't be certain that explicit validation is needed. The comment is somewhat speculative. The code could potentially crash if configs is null/undefined. Also, invalid values could cause issues downstream if there's no validation. The configs null case is already handled by the loading check. For validation, without seeing the full validation requirements, this suggestion is too speculative. The comment should be removed as it's more of a speculative suggestion without clear evidence that explicit validation is required.
10. frontend/core-ui/src/modules/settings/general/components/SelectTimezone.tsx:9
- Draft comment:
The SelectTimezone component neatly integrates TimezoneSelect with react-hook-form; implementation looks good. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
11. frontend/core-ui/src/modules/settings/general/hooks/useGeneralSettingsForms.tsx:18
- Draft comment:
Using detectTimeZone() for the TIMEZONE default is a solid approach; ensure it returns a valid timezone string for moment-timezone compatibility. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%This comment is purely informative and suggests ensuring compatibility without providing a specific actionable suggestion or identifying a potential issue. It violates the rule against making purely informative comments.
12. frontend/core-ui/src/modules/settings/general/schema/index.ts:13
- Draft comment:
Including TIMEZONE in the schema enhances validation; consider validating against a set of allowed timezone strings if needed. - Reason this comment was not posted:
Comment looked like it was already resolved.
13. frontend/core-ui/src/modules/types/paths/SettingsPath.ts:11
- Draft comment:
Uncommenting the General path ensures the route is available; this straightforward change is correct. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
14. frontend/core-ui/src/pages/settings/workspace/GeneralSettingsPage.tsx:7
- Draft comment:
Wrapping content in PageContainer and ScrollArea improves layout and usability; implementation looks solid. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
15. frontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsx:110
- Draft comment:
Adding an activeDot for the 'started' area enhances visual emphasis; ensure it aligns with overall chart design. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
16. frontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsx:118
- Draft comment:
Similarly, the activeDot for the 'completed' area improves data visibility; the update is consistent with design improvements. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
17. backend/plugins/operation_api/src/worker/index.ts:40
- Draft comment:
The file is missing a newline at the end. Consider adding a newline for consistency and to avoid potential issues with tooling. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% While missing newlines can cause issues with some tools, this is typically caught by linters and formatters. The comment is about a code style issue rather than the actual functional changes being made. The rules specifically state to focus on the changes in the diff and that we should assume build tools would catch such issues. The missing newline could potentially cause merge conflicts or issues with some tools, so maybe it's worth keeping the comment? No, this is exactly the kind of issue that would be caught by standard build tools and linters. It's not related to the actual code changes being made. Delete the comment. It's about a minor formatting issue that would be caught by build tools, and it's not related to the actual changes being made to the cron pattern.
Workflow ID: wflow_RegpCUdV9aY8W342
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
| export const fillMissingDays = ( | ||
| data: { date: string; started: number; completed: number }[], | ||
| baseDate: Date, | ||
| baseDate: Moment, |
There was a problem hiding this comment.
Mixing moment and date-fns in this file might lead to inconsistencies; consider unifying date handling across utility functions.
|
|
||
| const tzToday = tz(new Date(), timezone); | ||
|
|
||
| if (tzToday.hour() !== 0) { |
There was a problem hiding this comment.
Relying on tzToday.hour() === 0 might skip execution if the job isn’t triggered exactly at midnight; consider checking within a small time window.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
frontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsx (1)
17-17: Consider replacinganywith a proper type.The
statisticsprop uses theanytype, which bypasses TypeScript's type safety. Consider defining a proper interface for the statistics object structure.Example refactor:
+interface ICycleStatistics { + chartData: IGetCycleProgressChart; + // Add other statistics properties as needed +} + export const CycleProgressChart = ({ cycleId, isCompleted, statistics, }: { cycleId: string; isCompleted: boolean; - statistics: any; + statistics: ICycleStatistics; }) => {backend/plugins/operation_api/src/worker/index.ts (1)
26-29: Replace console.log with structured logger.Use a shared logger (levelled, JSON) instead of console.log for operability.
As per coding guidelines
Also applies to: 36-39
backend/plugins/operation_api/src/modules/project/utils/charUtils.ts (2)
28-38: Unify date handling; avoid mixing moment and date-fns here.fillMissingDays is moment-based, while other helpers still use date-fns with string dates. This risks type/runtime mismatches (e.g., differenceInCalendarDays(targetDate, lastDate) where lastDate is string). Prefer converting remaining helpers to moment-timezone for consistency and TZ correctness, or normalize types to Date everywhere before operations.
2-2: Use type-only import for Moment.Avoids pulling value space and clarifies intent:
-import { Moment } from 'moment-timezone'; +import type { Moment } from 'moment-timezone';backend/plugins/operation_api/src/worker/dailyCheckCycles.ts (1)
18-22: Consider deduping hourly enqueues.Hourly adds create 24 jobs/day/org; dedupe with deterministic jobId to reduce noise.
Example:
- sendWorkerQueue('operations', 'checkCycle').add('checkCycle', { - subdomain: org.subdomain, - timezone: org.timezone, - }); + const jobId = `checkCycle:${org.subdomain}:${new Date().toISOString().slice(0,10)}`; + sendWorkerQueue('operations', 'checkCycle').add( + 'checkCycle', + { subdomain: org.subdomain, timezone: org.timezone }, + { jobId, removeOnComplete: true, removeOnFail: 100 } + );Apply similarly for the non‑SaaS branch.
Also applies to: 37-41
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
backend/plugins/operation_api/src/modules/cycle/utils.ts(6 hunks)backend/plugins/operation_api/src/modules/project/utils/charUtils.ts(3 hunks)backend/plugins/operation_api/src/worker/dailyCheckCycles.ts(3 hunks)backend/plugins/operation_api/src/worker/index.ts(2 hunks)frontend/core-ui/src/modules/app/components/SettingsRoutes.tsx(2 hunks)frontend/core-ui/src/modules/settings/constants/data.ts(3 hunks)frontend/core-ui/src/modules/settings/general/components/GeneralSettings.tsx(4 hunks)frontend/core-ui/src/modules/settings/general/components/SelectTimezone.tsx(1 hunks)frontend/core-ui/src/modules/settings/general/hooks/useGeneralSettingsForms.tsx(2 hunks)frontend/core-ui/src/modules/settings/general/schema/index.ts(1 hunks)frontend/core-ui/src/modules/types/paths/SettingsPath.ts(1 hunks)frontend/core-ui/src/pages/settings/workspace/GeneralSettingsPage.tsx(1 hunks)frontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsx(2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Write concise, technical TypeScript code
Use functional and declarative programming patterns; avoid classes
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Avoid console logs
Always use absolute paths for imports
Use TypeScript for all code (no .js/.jsx)
Prefer interfaces over types for object shapes
Avoid enums; use maps instead
Use the function keyword for pure functions
Avoid unnecessary curly braces in simple conditionals; use concise syntax
Files:
backend/plugins/operation_api/src/worker/index.tsfrontend/core-ui/src/pages/settings/workspace/GeneralSettingsPage.tsxfrontend/core-ui/src/modules/settings/general/components/GeneralSettings.tsxfrontend/core-ui/src/modules/settings/general/components/SelectTimezone.tsxfrontend/core-ui/src/modules/types/paths/SettingsPath.tsfrontend/core-ui/src/modules/settings/general/schema/index.tsfrontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsxfrontend/core-ui/src/modules/settings/general/hooks/useGeneralSettingsForms.tsxbackend/plugins/operation_api/src/worker/dailyCheckCycles.tsfrontend/core-ui/src/modules/app/components/SettingsRoutes.tsxbackend/plugins/operation_api/src/modules/cycle/utils.tsfrontend/core-ui/src/modules/settings/constants/data.tsbackend/plugins/operation_api/src/modules/project/utils/charUtils.ts
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use declarative JSX
Use Shadcn UI, Radix UI, and Tailwind for components and styling
Implement responsive, mobile-first design with Tailwind CSS
Minimize useEffect and setState usage
Wrap client components in React.Suspense with a fallback
Use dynamic loading for non-critical components
Include explicit width and height (or sizes) when rendering images
Implement lazy loading for images
Limit 'use client': favor server components and Next.js SSR
Use 'use client' only for Web API access in small components
Do not use 'use client' components for data fetching or state management
Files:
frontend/core-ui/src/pages/settings/workspace/GeneralSettingsPage.tsxfrontend/core-ui/src/modules/settings/general/components/GeneralSettings.tsxfrontend/core-ui/src/modules/settings/general/components/SelectTimezone.tsxfrontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsxfrontend/core-ui/src/modules/settings/general/hooks/useGeneralSettingsForms.tsxfrontend/core-ui/src/modules/app/components/SettingsRoutes.tsx
🧬 Code graph analysis (2)
frontend/core-ui/src/modules/settings/general/components/GeneralSettings.tsx (1)
frontend/core-ui/src/modules/settings/general/components/SelectTimezone.tsx (1)
SelectTimezone(5-25)
backend/plugins/operation_api/src/modules/cycle/utils.ts (1)
backend/plugins/operation_api/src/modules/project/utils/charUtils.ts (1)
fillMissingDays(26-57)
🪛 ESLint
frontend/core-ui/src/modules/settings/general/components/GeneralSettings.tsx
[error] 68-68: Expected an assignment or function call and instead saw an expression.
(@typescript-eslint/no-unused-expressions)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Sourcery review
- GitHub Check: core-ui
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (16)
frontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsx (1)
110-110: LGTM! Clean visual enhancement for chart interactivity.The activeDot customization on both Area series improves the chart's hover interaction by providing clear visual feedback with appropriate sizing and consistent color usage from STATUS_COLORS.
Also applies to: 121-121
frontend/core-ui/src/modules/app/components/SettingsRoutes.tsx (2)
35-39: LGTM!The lazy import for GeneralSettings follows the established pattern and correctly maps to the GeneralSettingsPage module.
126-129: LGTM!The General route configuration is correctly structured and aligns with other workspace settings routes.
frontend/core-ui/src/modules/types/paths/SettingsPath.ts (1)
11-11: LGTM!The General path addition follows the existing enum pattern and is positioned appropriately.
frontend/core-ui/src/modules/settings/constants/data.ts (1)
7-7: LGTM!The General navigation entry is correctly structured with an appropriate icon and follows the established pattern for settings navigation items.
Also applies to: 124-128
frontend/core-ui/src/modules/settings/general/schema/index.ts (1)
13-13: LGTM!The TIMEZONE field addition is correctly typed as a string. The TimezoneSelect component handles the valid timezone values, making additional schema validation unnecessary.
frontend/core-ui/src/modules/settings/general/hooks/useGeneralSettingsForms.tsx (1)
2-2: LGTM!The TIMEZONE initialization using
detectTimeZone()provides a sensible default based on the user's environment.Also applies to: 18-18
frontend/core-ui/src/modules/settings/general/components/SelectTimezone.tsx (1)
1-25: LGTM!The SelectTimezone component correctly integrates with react-hook-form using
useFormContextand properly binds the TimezoneSelect control to the form field.frontend/core-ui/src/pages/settings/workspace/GeneralSettingsPage.tsx (1)
3-20: LGTM!The refactored layout using PageContainer and ScrollArea provides better structure and scrolling behavior. The constrained content width (
max-w-2xl) improves readability for settings forms.frontend/core-ui/src/modules/settings/general/components/GeneralSettings.tsx (3)
5-14: LGTM!The import reordering and additions are appropriate for the new timezone functionality and improved state management.
27-41: LGTM!The refactored
updateCurrencynow correctly merges all existing configs before overlaying new data, ensuring no config values are accidentally dropped during updates.
93-93: LGTM!The SelectTimezone component is properly integrated into the form flow.
backend/plugins/operation_api/src/worker/index.ts (1)
13-15: Hourly schedule LGTM; matches timezone gating strategy.The hourly trigger is fine, assuming checkCycle short-circuits outside local midnight.
Please confirm checkCycle returns early for non‑midnight hours to avoid unnecessary work (it should, given tzToday.hour() check).
backend/plugins/operation_api/src/modules/cycle/utils.ts (2)
192-196: Timezone-aware day bucketing via $dateToString looks correct.Properly groups by local day before summing.
134-144: Verify TIMEZONE config return shape (string vs { value }). sendTRPCMessage returns the raw TRPC result and the core service implementation isn't in this repo — confirm core.configs.getConfig returns a plain string ('UTC') or an object (e.g., { value: 'UTC' }) and update to use timezone.value or handle both cases. Locations: backend/plugins/operation_api/src/modules/cycle/utils.ts:134-144, backend/plugins/operation_api/src/worker/dailyCheckCycles.ts:26-31.backend/plugins/operation_api/src/worker/dailyCheckCycles.ts (1)
50-53: Midnight-hour guard is good.Prevents work outside local midnight; aligns with hourly schedule.
Be mindful of TZ config correctness; a wrong/empty timezone would skip processing or run at wrong hour.
| import { STATUS_TYPES } from '@/status/constants/types'; | ||
| import { differenceInCalendarDays, startOfDay } from 'date-fns'; | ||
| import { sendTRPCMessage } from 'erxes-api-shared/utils'; | ||
| import { tz } from 'moment-timezone'; |
There was a problem hiding this comment.
Fix moment-timezone import/usage (named tz is not exported).
Use default import and moment.tz(...) to avoid runtime/build errors.
Apply:
-import { tz } from 'moment-timezone';
+import moment from 'moment-timezone';
- const start = tz(new Date(cycle.startDate), timezone);
- const end = tz(new Date(cycle.endDate), timezone);
+ const start = moment.tz(new Date(cycle.startDate), timezone);
+ const end = moment.tz(new Date(cycle.endDate), timezone);Also applies to: 253-259
🤖 Prompt for AI Agents
In backend/plugins/operation_api/src/modules/cycle/utils.ts around line 4 (and
similarly lines 253-259), the code imports a named export "tz" from
'moment-timezone' which doesn't exist at runtime; replace the named import with
a default import (import moment from 'moment-timezone') and update all calls
from tz(...) to moment.tz(...), ensuring any types/aliases are adjusted
accordingly so the module uses moment.tz for timezone-aware operations.
| sendTRPCMessage, | ||
| sendWorkerQueue, | ||
| } from 'erxes-api-shared/utils'; | ||
| import { tz } from 'moment-timezone'; |
There was a problem hiding this comment.
🧩 Analysis chain
Fix moment-timezone import/usage (named tz is not exported).
Switch to default import and moment.tz(...).
-import { tz } from 'moment-timezone';
+import moment from 'moment-timezone';
- const tzToday = tz(new Date(), timezone);
+ const tzToday = moment.tz(new Date(), timezone);
- const utcStart = tzToday.startOf('day').toDate();
- const utcEnd = tzToday.endOf('day').toDate();
+ const utcStart = tzToday.startOf('day').toDate();
+ const utcEnd = tzToday.endOf('day').toDate();Scan for similar incorrect imports:
Also applies to: 48-53, 56-58
🏁 Script executed:
#!/bin/bash
rg -nP "import\s*\{\s*tz\s*\}\s*from\s*'moment-timezone'"Length of output: 197
🏁 Script executed:
#!/bin/bash
sed -n '1,50p' backend/plugins/operation_api/src/modules/cycle/utils.tsLength of output: 1323
🏁 Script executed:
#!/bin/bash
rg -nP "tz\s*\(" backend/plugins/operation_api/src/modules/cycle/utils.tsLength of output: 117
Fix moment-timezone import and usage
Replace import { tz } from 'moment-timezone'; with import moment from 'moment-timezone'; and update all tz(...) calls to moment.tz(...) in:
- backend/plugins/operation_api/src/worker/dailyCheckCycles.ts
- backend/plugins/operation_api/src/modules/cycle/utils.ts
🤖 Prompt for AI Agents
In backend/plugins/operation_api/src/worker/dailyCheckCycles.ts (around line 8)
and backend/plugins/operation_api/src/modules/cycle/utils.ts (search for tz
usage), replace the incorrect named import "import { tz } from
'moment-timezone';" with the default import "import moment from
'moment-timezone';" and update every call of tz(...) to use moment.tz(...);
ensure any existing references or typings are adjusted to use the moment
namespace (e.g., moment.tz(...)) consistently across both files.
| const timezone = configs?.find((data: any) => data.code === 'TIMEZONE'); | ||
|
|
||
| methods.setValue('dealCurrency', currencies?.value); | ||
| methods.setValue('mainCurrency', mainCurrency?.value); | ||
|
|
||
| timezone && methods.setValue('TIMEZONE', timezone?.value); |
There was a problem hiding this comment.
Fix the unused expression on line 68.
The conditional expression on line 68 is flagged by ESLint because the result is not used. While it works, it violates best practices and linting rules.
Apply this diff to use an explicit conditional:
- const timezone = configs?.find((data: any) => data.code === 'TIMEZONE');
-
methods.setValue('dealCurrency', currencies?.value);
methods.setValue('mainCurrency', mainCurrency?.value);
-
- timezone && methods.setValue('TIMEZONE', timezone?.value);
+
+ const timezone = configs?.find((data: any) => data.code === 'TIMEZONE');
+ if (timezone) {
+ methods.setValue('TIMEZONE', timezone.value);
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const timezone = configs?.find((data: any) => data.code === 'TIMEZONE'); | |
| methods.setValue('dealCurrency', currencies?.value); | |
| methods.setValue('mainCurrency', mainCurrency?.value); | |
| timezone && methods.setValue('TIMEZONE', timezone?.value); | |
| methods.setValue('dealCurrency', currencies?.value); | |
| methods.setValue('mainCurrency', mainCurrency?.value); | |
| const timezone = configs?.find((data: any) => data.code === 'TIMEZONE'); | |
| if (timezone) { | |
| methods.setValue('TIMEZONE', timezone.value); | |
| } |
🧰 Tools
🪛 ESLint
[error] 68-68: Expected an assignment or function call and instead saw an expression.
(@typescript-eslint/no-unused-expressions)
🤖 Prompt for AI Agents
In frontend/core-ui/src/modules/settings/general/components/GeneralSettings.tsx
around lines 63 to 68, the expression "timezone && methods.setValue(...)" is an
unused conditional expression flagged by ESLint; replace it with an explicit
conditional statement (e.g., if (timezone) { methods.setValue('TIMEZONE',
timezone.value); }) so the side effect is performed clearly and the lint error
is resolved.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts (1)
628-631: Consider making fillUntilTargetDate timezone-aware
Inbackend/plugins/operation_api/src/modules/project/utils/charUtils.ts,fillUntilTargetDateuses nativeDatewith date-fns (differenceInCalendarDays,addDays,format), which default to the system/local timezone. To ensuretargetDatecalculations respect your configured timezone, switch to timezone-aware utilities (e.g.zonedTimeToUtc/utcToZonedTimefrom date-fns-tz or moment-timezone).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts(5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Write concise, technical TypeScript code
Use functional and declarative programming patterns; avoid classes
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Avoid console logs
Always use absolute paths for imports
Use TypeScript for all code (no .js/.jsx)
Prefer interfaces over types for object shapes
Avoid enums; use maps instead
Use the function keyword for pure functions
Avoid unnecessary curly braces in simple conditionals; use concise syntax
Files:
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts
🧬 Code graph analysis (1)
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts (1)
backend/plugins/operation_api/src/modules/project/utils/charUtils.ts (1)
fillMissingDays(26-57)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: operation_api-ci
- GitHub Check: core-ui
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts (1)
672-672: fillFromLastDate uses date-fns on “YYYY-MM-DD” strings – no Moment conversion needed
This function deliberately mirrors the Date-basedfillMissingDaysWithStartDate(not the Moment-basedfillMissingDays), so it’s safe to leave it usingaddDays/formatunless you specifically need timezone-aware logic.
| import { differenceInCalendarDays } from 'date-fns'; | ||
| import { requireLogin } from 'erxes-api-shared/core-modules'; | ||
| import { cursorPaginate } from 'erxes-api-shared/utils'; | ||
| import moment from 'moment'; |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Verify timezone configuration is applied for timezone-aware date handling.
The changes correctly adapt to the updated fillMissingDays signature by wrapping dates with moment(). However, using moment(date) without an explicit timezone parameter defaults to the server's local timezone rather than the configured organization timezone.
According to the PR objectives, timezone configuration should be fetched (via sendTRPCMessage) and applied to date calculations. Ensure that either:
- The timezone is fetched and applied at this resolver level (e.g.,
moment.tz(date, timezone)), or - The timezone handling is implemented within
fillMissingDaysor at another layer
Without explicit timezone handling, date calculations may behave inconsistently across different server environments, defeating the purpose of timezone-aware cycle checking.
Run the following script to verify how timezone is being handled:
Also applies to: 601-601, 617-617, 645-645, 664-664
🏁 Script executed:
#!/bin/bash
# Description: Check if timezone configuration is fetched and applied in project resolvers or charUtils
# Check if timezone is fetched in this file or related files
echo "=== Checking for timezone fetching in project resolvers ==="
rg -n -C5 "sendTRPCMessage|getTimezone|timezone" --type=ts backend/plugins/operation_api/src/modules/project/
# Check how moment is used in charUtils
echo -e "\n=== Checking moment usage in charUtils ==="
rg -n -C5 "moment\.tz|moment\(" --type=ts backend/plugins/operation_api/src/modules/project/utils/charUtils.ts
# Check if fillMissingDays handles timezone internally
echo -e "\n=== Checking fillMissingDays implementation ==="
ast-grep --pattern $'export const fillMissingDays = ($$$) => {
$$$
}'Length of output: 3987
Apply organization timezone to Moment calls
Fetch the org’s timezone (e.g. via sendTRPCMessage) and replace each plain moment(date) (project.ts:11, 601, 617, 645, 664) with moment.tz(date, timezone), or embed that logic in fillMissingDays/fillUntilTargetDate, to prevent defaulting to the server’s local timezone.
🤖 Prompt for AI Agents
In
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts
around lines 11, 601, 617, 645, and 664, Moment is being called without the
organization's timezone which causes dates to default to the server local TZ;
fetch the org timezone (e.g. via sendTRPCMessage) and replace plain moment(date)
calls with moment.tz(date, timezone) or, preferably, modify
fillMissingDays/fillUntilTargetDate to accept a timezone parameter and apply
moment.tz(date, timezone) internally so all date parsing/normalization uses the
org timezone consistently.
|
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts (1)
11-11: Timezone issue flagged in previous review remains unresolved.The concern raised in the previous review is still valid:
moment(date)defaults to the server's local timezone rather than the organization's configured timezone. To ensure timezone-aware date handling per the PR objectives, fetch the organization's timezone (e.g., viasendTRPCMessage) and replacemoment(date)withmoment.tz(date, timezone), or refactorfillMissingDaysto accept and apply a timezone parameter internally.Also applies to: 601-601, 617-617, 645-645, 664-664
🧹 Nitpick comments (1)
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts (1)
11-11: Consider migrating from Moment to modern date libraries.Moment.js is in maintenance mode and its maintainers recommend alternatives (Luxon, date-fns, or Temporal) for new development. While not urgent for this PR, consider planning a migration to a modern, actively maintained date library to benefit from improved immutability, smaller bundle sizes, and ongoing feature development.
Based on learnings.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts(5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Write concise, technical TypeScript code
Use functional and declarative programming patterns; avoid classes
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Avoid console logs
Always use absolute paths for imports
Use TypeScript for all code (no .js/.jsx)
Prefer interfaces over types for object shapes
Avoid enums; use maps instead
Use the function keyword for pure functions
Avoid unnecessary curly braces in simple conditionals; use concise syntax
Files:
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts
🧬 Code graph analysis (1)
backend/plugins/operation_api/src/modules/project/graphql/resolvers/queries/project.ts (1)
backend/plugins/operation_api/src/modules/project/utils/charUtils.ts (1)
fillMissingDays(26-57)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: core-ui
- GitHub Check: Analyze (javascript-typescript)
Summary by Sourcery
Implement timezone-based cycle checking across backend and UI by scheduling hourly worker jobs, computing date ranges in the proper timezone, and adding a configurable timezone field in the general settings
New Features:
Enhancements:
Important
Implement timezone-based cycle checking and UI updates for timezone selection in settings.
dailyCheckCycles.tsandcheckCycle()to run checks at local midnight.getCycleProgressChart()inutils.tsto use organization timezone for date calculations.SelectTimezonecomponent inSelectTimezone.tsxfor timezone selection in general settings.GeneralSettingsPage.tsxto include timezone selection and adjust layout withPageContainerandScrollArea.index.tsto run hourly instead of daily.GeneralSettings.tsxto handle timezone configuration.SettingsRoutes.tsx.This description was created by
for f13ab98. You can customize this summary. It will automatically update as commits are pushed.
Summary by CodeRabbit
New Features
UI Improvements
Operational Changes