# On-schedule Rules

An on-schedule rule defines a set of changes that are applied according to a set schedule. For example, you can periodically check for issues with specific attribute values and notify a user or a group. These rules replace the scheduled rules that were used in older workflows.

On-schedule rules are executed by a special workflow user. This is a system user account that is granted a full set of permissions. The permissions for this account cannot be modified. The workflow user account is not included in the license restrictions and is not displayed in the Users list.

## Sample On-schedule Rule

This rule executes every day at 10:00. The rule checks for unresolved issues that are assigned and contain a value in the Due Date field. If the due date is in the past, a notification is sent to the assignee.

```JAVASCRIPT
        
    const notificationText = 'Issue became overdue on <i>{0}</i>:', formattedDate +
    ' <a href="' + issue.url + '">' + issue.summary + '</a><p style="color: gray;font-size: 12px;margin-top: 1em;border-top: 1px solid #D4D5D6">' +
    'Sincerely yours, YouTrack' + '</p>';
    userToNotify.notify('[YouTrack, Issue is overdue]', notificationText);
},

```

> **Warning: Localized Messages**
> The original workflow script provided by YouTrack uses the `workflow.i18n` function. This is an internal function that is only meant to be used to reference localized message strings. To ensure that you can copy and customize this workflow code, we have removed this function from the sample. If you are editing the default workflow and want to customize any message text, we recommend that you remove these functions from your code as well.
>
>
>
> To learn more about localized messages in workflows, see [Localized Workflow Messages](Workflow-Localization.html).

The components that define this on-schedule rule are as follows:

* Again, the script starts with a `require` statement that references the `entities` module in the workflow API. This means that everything that is contained in this module can be accessed in this script with the `entities` variable.

* For this rule, the `exports.rule` property uses the `Issue.onSchedule` method. This exports the script that follows the declaration as an on-schedule rule.

* The body of the rule itself contains definitions for the following properties:

| Property | Description |
| --- | --- |
| title | An optional human-readable title. The title is only visible in the administrative interface. |
| search |    A search query that determines which issues are processed by this rule. It can be a string that uses the syntax for a standard YouTrack search query (see [Search                   and Commands Attributes](https://www.jetbrains.com.cn/en-us/help/youtrack/cloud/?Search-and-Command-Attributes)) or a function that recalculates a search string every time the rule is triggered.     When you use a function, reference it by name. For example, `search: getSearchExpression`.     We strongly recommend that you make the search expression as concrete as possible, instead of adding conditions inside the action.   |
| cron | The schedule for applying the rule, specified as a [Java cron expression](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html).     In this example, the expression triggers this rule every day at 10:00 in the time zone that is set for your YouTrack server.     > **Note: Cron Expression Format** > YouTrack evaluates cron expressions using the Quartz Job Scheduling Library. To ensure that your cron expressions are interpreted correctly: > > > > * Specify values for six fields (second, minute, hour, day of the month, month, day of the week), not five. > > * Specify the day of the week as a value between 1 and 7, where 1 represents Sunday. It also accepts three-letter abbreviations for SUN-SAT. Expressions that use values between 0 and 7 where both 0 and 7 represent Sunday will not be parsed as expected. > > > > If a malformed cron expression prevents the rule from being scheduled, the error is recorded in workflow logs. For troubleshooting tips, see [Troubleshooting Workflows](troubleshooting-workflows.html).                  The Due Date field stores the date and time as 12:00 UTC. If, for example, your office is in California (UTC-7) and you want your users to be notified for all issues that are due in less than two days, you need to offset the due date by seven hours. For more information, see [Working with Dates and Times](workflow-working-with-dates-times.html).                 |
| muteUpdateNotifications | A flag that determines whether update notifications are sent for changes applied by this rule. If you want to apply updates without sending notifications, set to `true`.     When `true`, this property also suppresses notifications for cascading changes that are applied in the same transaction. For example, when updates that are applied by the on-schedule rule trigger updates from one or more on-change rules, the entire set of changes is applied without sending notifications.     The value for this property does not affect notifications that are explicitly sent, as with the .notify method that is used in this example.     This property is not relevant to this example, as the rule does not apply any issue changes. Even if it were set to `true`, the email notification that is sent using the `.notify` method is still delivered.   |
| modifyUpdatedProperties | A flag that determines whether the changes applied by this rule will update the value for the `updated` and `updated by` properties in the issue. If you want to update these properties, set this flag to `true`.     Available since 2023.1    |
| guard | A function that determines the conditions for executing the rule. If the guard condition is not met, the action specified in the rule is not applied to an issue. |
| action | The actions that should be applied to each issue that matches the search condition. This action is triggered separately for each issue. The action itself is performed by the workflow user account.     In this example, we use the `Assignee.notify` method to warn the current assignee that the issue is overdue.   |
| requirements | The list of entities that are required for the rule to execute without errors. This property ensures that rules can be attached to projects safely.     In this example, the requirements ensure that both the Assignee and Due Date fields store the correct types and are available in the project to which the rule is attached. If either field is absent, an error is shown in the Workflows list. The rule cannot be enabled until the required fields are attached.   |

## Store State Between Scheduled Runs

Standalone workflows don't have dedicated local storage. When a scheduled rule needs to remember a small amount of state between runs, you can store this data in a dedicated issue and use the `search` property to select this issue as the rule target. This dedicated issue is sometimes called an anchor issue.

Use this approach only for small amounts of non-sensitive workflow state. For example, you can store the date of the last notification or a list of issue IDs that were already included in a report. If you package the workflow as an app or need structured app-owned data storage, use [app global storage](apps-extension-properties.html#global-storage) instead.

> **Note: Anchor Issue Limitations**
> Don't use an anchor issue to store secrets, large datasets, or data that can be updated concurrently by several rules. The stored data is part of the issue description and can be changed manually by anyone who can update the anchor issue.

Procedure: To store state in an anchor issue:

1. Create a dedicated issue in the project where the workflow is attached.

2. Make the issue visible only to the users who maintain the workflow.

3. Use the issue description to store a small JSON object.

4. Set the `search` property of the on-schedule rule so it only matches the anchor issue.

5. In the rule action, read and update the JSON object stored in `ctx.issue.description`.

The following rule runs once a day and sends the project lead a list of issues that are pending review. The rule uses the anchor issue description to remember which issues have already been reported.

```JAVASCRIPT
const entities = require('@jetbrains/youtrack-scripting-api/entities');
const search = require('@jetbrains/youtrack-scripting-api/search');

exports.rule = entities.Issue.onSchedule({
  title: 'Notify project lead about pending reviews',
  search: 'issue id: DEMO-1',
  cron: '0 0 9 ? * MON-FRI',
  action: (ctx) => {
    const anchor = ctx.issue;
    const storedState = anchor.description ? JSON.parse(anchor.description) : {};
    const reportedIssues = storedState.reportedIssues || {};

    const issues = search.search(
      anchor.project,
      'State: {Pending Review} #Unresolved',
      ctx.currentUser
    );
    const issuesToReport = [];

    issues.forEach((issue) => {
      if (!reportedIssues[issue.id]) {
        issuesToReport.push(issue);
        reportedIssues[issue.id] = true;
      }
    });

    if (issuesToReport.length) {
      const issueList = issuesToReport.map((issue) => issue.id + ' ' + issue.summary).join('\n');
      anchor.project.leader.notify('Issues pending review', issueList);
    }

    anchor.description = JSON.stringify({
      reportedIssues: reportedIssues,
      updated: Date.now()
    }, null, 2);
  }
});
```

