Accept messy input#
Schedule project data that strict validation rejects, such as data exported from dhtmlxGantt with duplicate ids or missing dates, and get a list of every fix the engine made.
By default a Project uses Validation::Strict and returns Error::Input for the first invalid field. Validation::Repair applies the same coercions dhtmlxGantt applies when it imports data, then schedules the result.
Steps#
-
Create the project with repair validation:
use ; let mut project = new; -
Pass your data to
solve(Some(data), ...)as usual.Project::analyzewithSome(data)repairs supplied data the same way. The one-shotschedulefunction always uses strict validation, so use aProjecthere. -
Read the
Note::Repaired { path, message }entries inresult.notesand show them to the user, or log them.
The full example below has four kinds of problems: a duplicate id, a task with no dates, a dated constraint with no date, and a task whose start, end and duration disagree. Strict validation rejects this data. Repair schedules it:
use ;
What repair changes#
Repair reports each change below as one Note::Repaired, with the field path in path:
- Duplicate ids in
tasks,links,resources,assignmentsandcalendars: the last record replaces the earlier one and takes its position. The note is attasks[i].id, whereiis the index of the duplicate in your input. - A task with no start and no end gets
start_dateset toconfig.project_start, or to the earliest date of any task ifproject_startisn't set. - A leaf task (not a milestone) with no
durationand only one date getsduration: 1. - Start, end and duration that disagree: the dates win, and the duration becomes the working time between them. If the end is in non-working time, or the dates were computed on a different calendar, the duration is dropped and the task is resolved from its dates. An end that falls inside a pause moves to the pause start, with a second note at
tasks[i].end_date. - A summary with only one date gets the other date computed from the date and its duration.
- A dated constraint (
Snet,Snlt,Fnet,Fnlt,Mso,Mfo) withoutconstraint_dateis cleared. - Invalid
pauseson a task: the whole list is cleared, with a note attasks[i].pauses. - An invalid assignment
offsetordurationis cleared, so the assignment books the whole task.
A task that already has two of start, end and duration is valid input. Repair doesn't touch it and doesn't report it.
Only the duplicate-id notes use input indexes. Every other note indexes the deduplicated list. In the example, the two build records become one, so deploy is tasks[4] in your input but tasks[3] in its note.
What repair doesn't fix#
- An entirely undated project, with no
config.project_startand no task that has a date, still fails withError::Inputattasks[i].start_date. The engine never falls back to today's date. - Every other invalid input, such as a cycle in the
parenthierarchy or a calendar with no working time, still returnsError::Input. See Error handling. - If repair or validation fails,
solvereturnsErrand the project keeps its previous state.
Result#
The example prints the fixes, then the scheduled dates (the date lines may come in a different order):
tasks[3].id: duplicate id replaced the earlier record, retaining its position
tasks[2].constraint_type: dated constraint without date cleared
tasks[2].start_date: missing date defaulted to project anchor
tasks[2].duration: missing duration defaulted to one
tasks[3].duration: duration recomputed from supplied start and end
design 2026-01-01 00:00..2026-01-04 00:00 3
build 2026-01-01 00:00..2026-01-03 00:00 2
review 2026-01-01 00:00..2026-01-02 00:00 1
deploy 2026-01-01 00:00..2026-01-04 00:00 3
build uses the second record's duration of 2, and deploy has a duration of 3, taken from its dates. With Project::default(), the same solve call fails with Error::Input.