[Canonical page](<https://docs.dhtmlx.com/planning-engine/java/api/changes/assignment-update/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# AssignmentUpdate

An edit to one existing assignment of a live project. It goes in the `update` list of [`SchedulingChanges.assignments`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/scheduling-changes.md#assignments>), which [`Project#apply`](<https://docs.dhtmlx.com/planning-engine/java/api/project-apply.md>) and [`Project#preview`](<https://docs.dhtmlx.com/planning-engine/java/api/project-preview.md>) take. Create it with `new AssignmentUpdate(id)` and set the fields to change with the `withX` setters.

## Declaration

```java
package org.dhtmlx.plen;

public class AssignmentUpdate extends ValueRecord implements DeepCloneable<AssignmentUpdate>
```

## Constructors

### AssignmentUpdate(Id)

```java
public AssignmentUpdate(Id id)
```

Creates an update for the assignment with the given id. Every other field is [`Patch.missing()`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/patch.md#missing>), so the update changes nothing until a field is set.

| Name | Type | Description |
|---|---|---|
| `id` | [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | Id of the assignment to edit. Build it with `Id.num(...)` or `Id.str(...)`. |

## Fields

Every field except `id` is a [`Patch<T>`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/patch.md>). `Patch.missing()` (the default) keeps the stored value, `Patch.of(value)` sets it, and `Patch.nullValue()` clears it. The **On `nullValue()`** column shows what clearing does. For the meaning of each value, see the field of the same name on [`AssignmentData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/assignment-data.md#fields>).

| Field | Type | On `nullValue()` | Description |
|---|---|---|---|
| `id` | [`Id`](<https://docs.dhtmlx.com/planning-engine/java/api/data/id.md>) | - | Id of the assignment to edit. |
| `task` | `Patch<Id>` | rejected | Moves the assignment to another task. |
| `resource` | `Patch<Id>` | rejected | Gives the assignment to another resource. |
| `value` | `Patch<Double>` | rejected | New utilization rate. |
| `offset` | `Patch<Double>` | `null` | New start of the slice. `null` books from the task start. |
| `duration` | `Patch<Double>` | `null` | New length of the slice. `null` books up to the task end. |

Don't use `Patch.of(null)` on `task`, `resource` or `value`. It throws `NullPointerException` when the change is applied. Use `Patch.nullValue()` to clear `offset` or `duration`.

The edited assignment must still pass the [`AssignmentData` checks](<https://docs.dhtmlx.com/planning-engine/java/api/data/assignment-data.md#errors>): `value` and `duration` finite and greater than `0`, `offset` finite and `0` or greater, and `task` and `resource` naming existing records.

### Effect on dates

- `offset`, `duration` and `value` change resource load only. They never move a task.
- `task` and `resource` move dates only when the task then works on a different set of calendars, for example when the new resource has its own calendar in [`CalendarMode.RESOURCE`](<https://docs.dhtmlx.com/planning-engine/java/api/data/calendar-mode.md>).
- An assignment moved to an unscheduled task stays in the project but books no load. Its id is listed in [`ChangeEffects.droppedAssignments`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/apply-report.md#changeeffects>).

## Methods

### withId, withTask, withResource, withValue, withOffset, withDuration

```java
public AssignmentUpdate withId(Id value)
public AssignmentUpdate withTask(Patch<Id> value)
public AssignmentUpdate withResource(Patch<Id> value)
public AssignmentUpdate withValue(Patch<Double> value)
public AssignmentUpdate withOffset(Patch<Double> value)
public AssignmentUpdate withDuration(Patch<Double> value)
```

Each sets the field of the same name and returns this instance for chaining.

### deepClone

```java
public AssignmentUpdate deepClone()
```

Returns a new `AssignmentUpdate` with the same field values. `Id` and `Patch` values are immutable, so the copy is fully independent.

### copy

```java
public AssignmentUpdate copy()
```

Returns a shallow copy. Because every field holds an immutable value, it behaves like `deepClone()`.

### equals, hashCode, toString

Inherited from [`ValueRecord`](<https://docs.dhtmlx.com/planning-engine/java/api/support/value-record.md>). Two updates are equal when all six fields are equal. `toString()` lists the fields, for logging; each patch prints only its kind, e.g. `Patch{kind=VALUE}`.

## Errors

An update is one operation, at path `assignments.update[i]`. A failing update goes into [`ApplyReport.rejected`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/apply-report.md#rejected>) as a [`RejectedOperation`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/rejected-operation.md>); it isn't thrown. [`Project#apply`](<https://docs.dhtmlx.com/planning-engine/java/api/project-apply.md>) describes what a rejection does to the project.

| Message | When it occurs |
|---|---|
| `unknown assignment id` | No assignment has `id`. |
| `required field cannot be null` | `task`, `resource` or `value` is `Patch.nullValue()`. |
| a validation message | The edited assignment fails an [`AssignmentData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/assignment-data.md#errors>) check, for example an unknown `resource` or a `value` of `0`. |

## Example

Hand Ben's review to Cara and narrow it to the last day of the task.

```java
import java.util.List;
import org.dhtmlx.plen.*;

public class AssignmentUpdateExample {
  public static void main(String[] args) throws Exception {
    ProjectData data = new ProjectData()
        .withTasks(List.of(
            new TaskData(Id.num(1))
                .withStartDate(Moment.fromYmdHm(2026, 4, 6, 8, 0))
                .withDuration(5.0)))
        .withResources(List.of(
            new ResourceData().withId(Id.str("ben")),
            new ResourceData().withId(Id.str("cara"))))
        .withAssignments(List.of(
            new AssignmentData()
                .withId(Id.str("review"))
                .withTask(Id.num(1))
                .withResource(Id.str("ben"))
                .withValue(0.5)));

    Project project = new Project();
    project.solve(data, new SolveOptions());

    SchedulingChanges changes = new SchedulingChanges();
    changes.assignments.update.add(new AssignmentUpdate(Id.str("review"))
        .withResource(Patch.of(Id.str("cara")))
        .withOffset(Patch.of(4.0))
        .withDuration(Patch.of(1.0)));

    ApplyReport report = project.apply(changes);
    for (RejectedOperation rejected : report.rejected) {
      System.out.println(rejected.path + ": " + rejected.message);
    }
  }
}
```

## Related

- [`AssignmentData`](<https://docs.dhtmlx.com/planning-engine/java/api/data/assignment-data.md>) - the stored record and its checks
- [`Patch<T>`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/patch.md>) - the three-state type of every editable field
- [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/java/api/changes/scheduling-changes.md#assignments>) - the change set that carries the update
- [Split assignment work](<https://docs.dhtmlx.com/planning-engine/java/how-to/split-assignment-work.md>) - narrowing an assignment to a slice
- [Data Updates](<https://docs.dhtmlx.com/planning-engine/java/live-projects/editing-a-project.md#update-records-and-patch>) - update records in a live project
