# `MpxjEx.Project`
[🔗](https://github.com/rocket4ce/mpxj_ex/blob/v0.1.0/lib/mpxj_ex/project.ex#L1)

A schedule read by `MpxjEx.read/2`.

  * `:properties` - project level attributes (`:project_title`, `:start_date`,
    `:author`, `:minutes_per_day`, ...), keyed by MPXJ field name
  * `:tasks` - every task, in outline order (parents before their children)
  * `:resources`, `:assignments`, `:calendars`
  * `:relations` - every task dependency
  * `:custom_fields` - aliases given to custom fields, such as `text1` named "Role"
  * `:user_defined_fields` - fields defined by the file (Primavera UDFs, ...)
  * `:extra` - anything else MPXJ wrote (activity codes, currencies, work
    contours, ...) as decoded JSON

Entities reference each other by unique id. Since Elixir data can't hold
cyclic references, use the functions in this module to navigate:

    project = MpxjEx.read!("plan.mpp")

    for task <- MpxjEx.Project.root_tasks(project),
        child <- MpxjEx.Project.children(project, task) do
      {task.name, child.name}
    end

Functions taking a task, resource or calendar also accept its unique id.

# `t`

```elixir
@type t() :: %MpxjEx.Project{
  assignments: [MpxjEx.Assignment.t()],
  calendars: [MpxjEx.Calendar.t()],
  custom_fields: [map()],
  extra: map(),
  index: term(),
  properties: map(),
  relations: [MpxjEx.Relation.t()],
  resources: [MpxjEx.Resource.t()],
  tasks: [MpxjEx.Task.t()],
  user_defined_fields: [map()]
}
```

# `tree`

```elixir
@type tree() :: [%{task: MpxjEx.Task.t(), children: tree()}]
```

# `children`

```elixir
@spec children(t(), MpxjEx.Task.t() | integer()) :: [MpxjEx.Task.t()]
```

The direct children of a task, in outline order.

# `default_calendar`

```elixir
@spec default_calendar(t()) :: MpxjEx.Calendar.t() | nil
```

The project's default calendar.

# `field_alias`

```elixir
@spec field_alias(t(), atom(), atom() | String.t()) :: String.t() | nil
```

The alias given to a custom field, such as `"Role"` for `field_alias(project, :resource, :text1)`.

# `get_calendar`

```elixir
@spec get_calendar(t(), integer()) :: MpxjEx.Calendar.t() | nil
```

Finds a calendar by unique id.

# `get_resource`

```elixir
@spec get_resource(t(), integer()) :: MpxjEx.Resource.t() | nil
```

Finds a resource by unique id.

# `get_resource_by_id`

```elixir
@spec get_resource_by_id(t(), integer()) :: MpxjEx.Resource.t() | nil
```

Finds a resource by id.

# `get_task`

```elixir
@spec get_task(t(), integer()) :: MpxjEx.Task.t() | nil
```

Finds a task by unique id.

# `get_task_by_id`

```elixir
@spec get_task_by_id(t(), integer()) :: MpxjEx.Task.t() | nil
```

Finds a task by id (the row number shown in MS Project).

# `parent`

```elixir
@spec parent(t(), MpxjEx.Task.t() | integer()) :: MpxjEx.Task.t() | nil
```

The parent of a task, or nil for a top level task.

# `predecessors`

```elixir
@spec predecessors(t(), MpxjEx.Task.t() | integer()) :: [MpxjEx.Task.t()]
```

Tasks that a task depends on. See `MpxjEx.Task` `:predecessors` for the
dependency type and lag.

# `resource_assignments`

```elixir
@spec resource_assignments(t(), MpxjEx.Resource.t() | integer()) :: [
  MpxjEx.Assignment.t()
]
```

The task assignments of a resource.

# `root_tasks`

```elixir
@spec root_tasks(t()) :: [MpxjEx.Task.t()]
```

Top level tasks: those without a parent.

Microsoft Project files have a single root, the project summary task
(unique id 0), whose children are the tasks at outline level 1.

# `successors`

```elixir
@spec successors(t(), MpxjEx.Task.t() | integer()) :: [MpxjEx.Task.t()]
```

Tasks that depend on a task.

# `task_assignments`

```elixir
@spec task_assignments(t(), MpxjEx.Task.t() | integer()) :: [MpxjEx.Assignment.t()]
```

The resource assignments of a task.

# `task_resources`

```elixir
@spec task_resources(t(), MpxjEx.Task.t() | integer()) :: [MpxjEx.Resource.t()]
```

The resources assigned to a task.

# `task_tree`

```elixir
@spec task_tree(t()) :: tree()
```

The task hierarchy as nested maps:

    [%{task: %MpxjEx.Task{}, children: [%{task: %MpxjEx.Task{}, children: []}]}]

---

*Consult [api-reference.md](api-reference.md) for complete listing*
