# Attributes

**Audience:** ERP users who are familiar with Action Target's system but are new to PlanetTogether.
**Scope:** Phase 1 — attribute definitions, attribute codes, and operation attribute links.
**Related stories:** US-004 (Resource, Capability, and Attribute Maintenance Tools).

---

## 1. What Attributes Do in PlanetTogether

Attributes are custom data properties that can be attached to job operations. They give the scheduler a way to describe *what kind of work* an operation is — beyond which machine and labor pool it needs — so PlanetTogether can group, sequence, and schedule setup or cleanout time intelligently.

Phase 1 uses attributes for two purposes:

**Sequence optimization (batching):** When PT builds a schedule, it can minimize the number of setup changeovers by grouping consecutive operations that share the same attribute value on the same resource. An attribute with `UseInSequencing = true` becomes available to the PT Sequence Planning board's optimize factors. Schedulers can weight each attribute and configure how many optimization points to award for grouping similar work together.

**Setup and cleanout time:** When an attribute value changes between two consecutive operations on the same resource, PT can automatically schedule a setup or cleanout block between them. The `AttributeTrigger` property controls *when* the timer fires (e.g., always, when the code changes, when a numeric value rises), and `AttributeType` controls whether the time is counted as Setup or Clean time.

An attribute can serve both purposes at the same time, or just one, or purely as informational metadata visualized in the Gantt and scheduling grids.

---

## 2. The Three Layers: Attributes, Codes, and Operation Links

Working with attributes in the ERP involves three layers that build on each other:

### Layer 1 — Attribute Definition

An **Attribute** is the property type itself — a named, configurable object that describes a characteristic of work. Examples: "Steel Grade," "Coating Type," "Product Family." The attribute definition sets all the defaults: how PT should visualize it, whether it drives sequencing or setup calculations, and what duration or cost to use when it fires.

### Layer 2 — Attribute Codes

An **Attribute Code** is one allowed value for an attribute. Each attribute has a list of codes representing the discrete values it can take. For example, the "Steel Grade" attribute might have codes `A36`, `A500-B`, `AR200`, and `HRPO`.

Codes are the strings that get attached to individual operations. When two consecutive operations on the same resource carry *different* codes for the same attribute, PT can recognize the code change and trigger a setup or sequencing decision.

### Layer 3 — Operation Attribute Links

An **Operation Attribute Link** is the record that ties a specific code to a specific routing operation. It says: "When this operation runs, it should carry this attribute value."

Links live on the router — both the workbench (draft) and production sides. When a workbench router is published, its attribute links are copied forward to the production router. When a template is generated from the production router, the attribute links become rows in `aps.job_operation_attribute_source`, which PT reads for scheduling.

---

## 3. The `aps.*_source` Tables

| Table | What it holds | PT object it feeds |
|---|---|---|
| `aps.attribute_source` | Attribute definitions (one row per attribute). | `Attributes` |
| `aps.attribute_code_source` | Allowed code values per attribute. | Referenced by Operation Attributes |
| `aps.bom_operations_attributes` | Operation attribute/code links for workbench and production routers. | (join source for template generation) |
| `aps.job_operation_attribute_source` | Generated per-operation attribute rows for template MOs. | `OperationAttributes` |

`aps.attribute_code_table_source` exists in the schema but is not used in Phase 1.

---

## 4. How Data Flows to PlanetTogether

```
aps.attribute_source            →  PT Attributes import
aps.attribute_code_source       →  (read at template generation time)
aps.bom_operations_attributes   →  (read at template generation time)
        ↓  GenerateRouterTemplate
aps.job_operation_attribute_source  →  PT Operation Attributes import
```

Attribute definitions are imported into PT as Attribute objects. The code values assigned to specific operations are carried in the template's Operation Attributes rows, generated each time a template is created or regenerated for a router. PT reads both when building a scenario.

**The ERP is authoritative.** Changes made inside PT to attribute data are not written back to the ERP source tables.

---

## 5. Using the Planning Attributes Screen

The **Planning Attributes** tab is located inside the **Product Information** app. It is where you define attributes and manage their allowed code values before linking them to router operations.

Access to create, edit, and retire records requires the **Manufacturing Engineering**, **Product Data Manager**, or **IT Admin** role. Planning and scheduling leads have view-only access.

The screen contains two side-by-side grids. The Codes grid is filtered by whatever attribute is selected in the Attributes grid.

---

### Main Toolbar

| Button | What it does |
|---|---|
| **Hide / Show Attributes** | Collapses or expands the Attributes grid. |
| **Hide / Show Codes** | Collapses or expands the Codes grid. |
| **Show Inactive / Hide Inactive** | Toggles visibility of inactive attributes. Defaults to hiding them. |

---

### Attributes Grid

This grid shows all APS attribute definitions from `aps.attribute_source`.

**Columns displayed by default:** Attribute ID, Name, Description, Use in Sequencing, Active.

**Toolbar actions:**

| Action | Behavior |
|---|---|
| **Add** | Opens the attribute form in create mode. |
| **Edit** | Opens the attribute form loaded with the selected row's data. Select exactly one row first. |
| **Retire** | Prompts for confirmation, then marks the attribute inactive. Never physically deleted. |

**Attribute form fields:**

*Identity*

| Field | Required | Notes |
|---|---|---|
| Attribute ID | ✅ | Must match the ID used in PT imports. Convention: `ATTR-[ShortName]` (e.g., `ATTR-SteelGrade`). Locked after creation — retire and recreate if a change is needed. |
| Name | ✅ | Display name in PT and in ERP grids. |
| Description | | Describe what characteristic this attribute classifies. |

*PT Setup Behavior*

| Field | Notes |
|---|---|
| Trigger | Controls when a setup or cleanout fires. See the trigger table below. Leave blank when using the attribute for sequencing only. |
| Type | `Setup` or `Clean`. Defines whether the incurred time counts as setup or cleanout. Leave blank for informational or sequencing-only attributes. |
| Cleanout Grade | Integer priority for simultaneous cleanout scheduling. When multiple cleanouts fire at the same time, the highest grade wins. A cleanout also resets all triggers at or below its own grade. Only relevant when Type = `Clean`. |
| Color Code | Hex color (`#RRGGBB`) for Gantt attribute segments. |

**AttributeTrigger accepted values:**

| Trigger value | When the setup or clean fires |
|---|---|
| `Always` | Every time this operation is scheduled, regardless of what comes before it. |
| `CodeChanges` | When this attribute's code changes from one scheduled operation to the next on the same resource. |
| `NumberChanges` | When this attribute's number value changes from the previous operation to the next on the same resource. |
| `NumberHigher` | When this attribute's number value increases from the previous operation to the next. |
| `NumberLower` | When this attribute's number value decreases from the previous operation to the next. |
| `LookupByCode` | Duration is determined by an Attribute Code Table (Phase 2 only). |
| `LookupByRange` | Duration is determined by an Attribute Range Table (Setup only; Phase 2 only). |
| `Never` | This attribute is not used for setup or clean calculations. |

*Defaults*

| Field | Notes |
|---|---|
| Default Cost | Cost incurred per setup or cleanout event triggered by this attribute. Not used with lookup table triggers. |
| Default Duration (hrs) | Hours incurred per event. Not used with lookup table triggers. |

*Flags*

| Flag | Default | What it controls in PT |
|---|---|---|
| Consecutive Setup | false | When true, multiple setup steps for the operation must run sequentially rather than concurrently. Total setup time = max non-consecutive time + sum of all consecutive times. |
| Incur Resource Setup | false | When true, the sequenced setup fires even if the resource's `UseSequencedSetup` flag is false. |
| Show in Gantt | false | When true, this attribute's name and code appear in the Gantt activity block when the Attribute Segment is enabled on the label. |
| Hide in Grids | false | When true, this attribute's columns are hidden from the Activities board scheduling grids. |
| Use in Sequencing | false | When true, this attribute is available to the Sequence Planning board's optimize factors for schedule batching and grouping. |

**Selecting an attribute row:** Clicking a row selects that attribute and filters the Codes grid to show only that attribute's allowed code values.

---

### Codes Grid

This grid shows the allowed code values for the currently selected attribute, from `aps.attribute_code_source`. When no attribute is selected, this grid is empty — select an attribute row first.

**Columns displayed by default:** Code, Display Name, Description, Active.

**Toolbar actions:**

| Action | Behavior |
|---|---|
| **Add** | Opens the code form. The Attribute field is pre-filled and read-only. Disabled when no attribute is selected. |
| **Edit** | Opens the code form for the selected row. |
| **Retire** | Prompts for confirmation, then retires the code. Existing operation attribute links referencing a retired code remain historically valid — they are not automatically removed. |
| **Show Inactive / Hide Inactive** | Toggles visibility of inactive codes. |

**Code form fields:**

| Field | Required | Notes |
|---|---|---|
| Attribute | Read-only | Pre-filled from the currently selected attribute. |
| Code | ✅ | The short code string (e.g., `A36`, `COAT-POWDER`). Must be unique within the attribute. This is the value PT carries on job operations. |
| Display Name | | A longer, readable label shown in ERP dropdowns and grids. |
| Description | | Optional explanation of what this code represents. |
| Notes | | Optional internal notes. |

> **Code uniqueness:** Codes are unique within an attribute. The same code string can appear under two different attributes without conflict.

---

## 6. Linking Attributes to Operations (Routers Tab)

Attribute definitions and codes are only useful once they are attached to specific routing operations. This is done in the **Routers** tab, not the Attributes tab.

### Where to Find the Operation Attribute Links

In the Routers tab, select a workbench or production router and then select a BOM operation row. The **Operation Attributes** sub-grid below the operations grid shows the attribute/code links for that operation.

### Workbench vs. Production

Attribute links follow the same workbench/production pattern as the router itself:

| Side | What it holds | When it updates |
|---|---|---|
| **Workbench** | Draft attribute links configured before publishing. | Add/edit/retire any time the router is being edited. |
| **Production** | Published links that feed template generation. | Replaced automatically when the workbench router is published. |

Do not edit production operation attribute links directly for normal maintenance. Make changes on the workbench side, then publish.

### Operation Attribute Links Grid

**Columns displayed by default:** Attribute, Code, Active.

**Toolbar actions:**

| Action | Behavior |
|---|---|
| **Add** | Opens the link form. Disabled when no BOM operation is selected or the router is not in an editable state. |
| **Edit** | Opens the link form for the selected row. |
| **Retire** | Prompts for confirmation, then retires the link. The operation will no longer carry this attribute when the next template is generated. |

**Link form fields:**

| Field | Required | Notes |
|---|---|---|
| Attribute | ✅ | Dropdown showing active attributes. |
| Code | ✅ | Dropdown showing active codes for the selected attribute. |

> **Multiple codes per operation:** An operation can have more than one attribute link, and can have multiple links for the *same* attribute with different codes. All active links are exported as separate rows in `aps.job_operation_attribute_source`.

### How Publishing Propagates Attribute Links

When a workbench router is published:

1. All existing production operation attribute links for that router are cleared.
2. The workbench links are copied to the production side, translated through the workbench-to-production BOM operation ID map.
3. The production links are now the authoritative source for the next template generation.

After publishing, regenerate the template so PT receives the updated attribute rows.

---

## 7. Phase 1 Scope: What's Used and What's Not

| PT Feature | Phase 1 Status | Notes |
|---|---|---|
| Attribute definitions | ✅ Used | Maintained in `aps.attribute_source`. |
| Attribute codes (ERP-owned allowed values) | ✅ Used | Maintained in `aps.attribute_code_source`. |
| Operation attribute links | ✅ Used | Configured per BOM operation in the Routers tab; propagated on publish; generated into templates. |
| UseInSequencing | ✅ Used | Attributes with this flag true are eligible for sequence optimization in PT. |
| AttributeType / AttributeTrigger (Setup or Clean) | ✅ Supported | Can be configured; actual scheduling of setup/clean time also requires the resource to have `SetupIncluded = UseOperationAttributes` (for Setup) or `UseAttributeCleanouts = true` (for Clean). |
| ShowInGantt / HideInGrids / ColorCode | ✅ Supported | PT will respect these flags once attribute data is imported. |
| Attribute Code Tables (`LookupByCode` trigger) | ❌ Not used | Code Table data is not exported in Phase 1. |
| Attribute Range Tables (`LookupByRange` trigger) | ❌ Not used | Range Table data is not exported in Phase 1. |
| Number-based attribute values on operations | ❌ Not used | Phase 1 operation links carry a code (string) value only. Triggers that depend on a numeric value (`NumberChanges`, `NumberHigher`, `NumberLower`) have no effect. |

---

## 8. Summary: The Minimum You Need Before Attribute Data Can Influence Scheduling

For PT to use an attribute during scheduling:

1. ✅ An attribute definition exists and is active (`aps.attribute_source`).
2. ✅ At least one code is defined and active for that attribute (`aps.attribute_code_source`).
3. ✅ At least one BOM operation on the production router has an active link to that attribute and code (`aps.bom_operations_attributes`, `is_workbench = false`).
4. ✅ The template has been generated (or regenerated) after the production links were set — attribute rows must exist in `aps.job_operation_attribute_source`.
5. ✅ **For sequence optimization:** `UseInSequencing = true` on the attribute, and the attribute must be selected in the applicable optimize factor on the PT Sequence Planning board.
6. ✅ **For setup time:** `AttributeType = Setup`, a trigger configured, a default duration set, and the resource must have `SetupIncluded = UseOperationAttributes`.
7. ✅ **For cleanout time:** `AttributeType = Clean`, a trigger configured, a default duration set, and the resource must have `UseAttributeCleanouts = true`.

Missing any of these means the attribute is defined but has no scheduling effect in PT.