[Canonical page](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/resource-data/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# ResourceData

One resource that assignments book: a person, a team or a machine. It goes into [`ProjectData::resources`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>) on import, or into `resources.add` of [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/scheduling-changes.md>) for a live project. There's no constructor; build it with a struct literal. To change an existing resource, use [`ResourceUpdate`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/resource-update.md>).

## Declaration

```rust
#[derive(Clone, Debug)]
pub struct ResourceData {
    pub id: Id,
    pub capacity: Option<f64>,
    pub calendar_id: Option<Id>,
}
```

## Fields

### id

```rust
pub id: Id
```

Resource id. [`AssignmentData::resource`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/assignment-data.md#resource>) refers to it. A numeric id must be finite.

### capacity

```rust
pub capacity: Option<f64>
```

Units of work the resource can carry at once, in assignment `value` units (`1.0` = 100 %). `2.0` means two full-time assignments fit without overallocation. `None` takes [`SchedulingConfig::default_resource_capacity`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/scheduling-config.md#default_resource_capacity>) (`1.0` by default).

Default: `None`.

### calendar_id

```rust
pub calendar_id: Option<Id>
```

Working calendar of the resource. It's read only in [`CalendarMode::Resource`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/calendar-mode.md>), the default mode, where it must name a calendar in [`ProjectData::calendars`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>). In `CalendarMode::Task` and `CalendarMode::TaskInherited` the id is kept but not resolved. `None` means the resource has no calendar of its own, and its assignments work on the task calendar.

Default: `None`.

How a resource calendar combines with a task calendar is covered in [Resources and assignments](<https://docs.dhtmlx.com/planning-engine/rust/resources-and-assignment/resources-and-assignments.md>).

## Errors

An invalid field fails the import ([`Project::solve`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#solve>), [`schedule`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/schedule.md>)) with [`Err(Error::Input)`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/error.md>) at the field's path, or rejects the `resources.add` operation in [`Project::apply`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#apply>).

| Field | When it occurs | Path |
|---|---|---|
| `id` | numeric id isn't finite | `resources[i].id` |
| `capacity` | value isn't finite or is below `0` | `resources[i].capacity` |
| `calendar_id` | names no calendar, in `CalendarMode::Resource` | `resources[i].calendar_id` |

Rules that span records, such as unique resource ids, are on [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md#validation>).

## Example

```rust
use plen_core::{
    schedule, AssignmentData, DateTime, ProjectData, ResourceData, SolveOptions, TaskData,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let start = DateTime::from_ymd_hm(2026, 4, 6, 8, 0).ok_or("invalid date")?;

    let data = ProjectData {
        tasks: vec![
            TaskData {
                start_date: Some(start),
                duration: Some(2.0),
                ..TaskData::new(1)
            },
            TaskData {
                start_date: Some(start),
                duration: Some(3.0),
                ..TaskData::new(2)
            },
        ],
        resources: vec![ResourceData {
            id: "team".into(),
            capacity: Some(2.0),
            calendar_id: None,
        }],
        assignments: vec![
            AssignmentData {
                id: None,
                task: 1.into(),
                resource: "team".into(),
                value: 1.0,
                offset: None,
                duration: None,
            },
            AssignmentData {
                id: None,
                task: 2.into(),
                resource: "team".into(),
                value: 1.0,
                offset: None,
                duration: None,
            },
        ],
        ..Default::default()
    };

    let result = schedule(data, &SolveOptions::default())?;
    // Two parallel full-time assignments fit a capacity of 2.0.
    println!("{:?}", result.overallocations);
    Ok(())
}
```

## Related

- [`AssignmentData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/assignment-data.md>) - books a resource on a task
- [`CalendarData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/calendar-data.md>) - the calendar a resource can work on
- [`ResourceOverallocation`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/resources/resource-overallocation.md>) - reports where a resource's load exceeds its capacity
- [Resources and assignments](<https://docs.dhtmlx.com/planning-engine/rust/resources-and-assignment/resources-and-assignments.md>) - capacity, resource calendars and load
