Materials
The property tables that give a material its identity — substance, form, dimension, finish, grade, and type.
A material is an item of type Material used as raw stock. Structured property tables define its substance, form, dimension, and optional finish, grade, and type. Carbon uses these values to generate the material's identity, display name, and code.
Each material row (material table) carries only foreign keys into these lookups: materialSubstanceId, materialFormId, dimensionId, finishId, gradeId, and materialTypeId. All six are nullable, so a material can be as loosely or tightly specified as you need.
The property tables
Six lookup tables compose a material. Substance and form are independent; the remaining choices are scoped by one or both and therefore cascade.
name and a code.name and a code.isMetric.name and a code.The lookups cascade
Substance and form stand alone. Grade and finish are picked from the list for the chosen substance; dimension from the list for the chosen form; type from the intersection of both. Change the substance and the grade or finish list you can pick from changes with it. This is why the material form on new-material screens fills top down.
Scope: system-wide or per company
Carbon provides a starter taxonomy. Each lookup has a nullable companyId. Rows with companyId null are system values visible to every company; rows with a company ID are company-specific additions.
Uniqueness is enforced per scope so a system value and a company value never collide:
Substance and form carry more; the rest are lean
Only materialSubstance and materialForm have a code, custom fields, and audit columns. materialDimension, materialFinish, materialGrade, and materialType are lean lookups with no custom fields and no audit trail, and their seeded ids are human-readable (like steel-1018) rather than generated keys.
How a material references them
A material links to its item positionally, not through a foreign key. When you create one, Carbon inserts the item row first with type set to Material, then inserts the material row using the item's readable id as material.id. There is no itemId column. The two are joined on item.readableId = material.id within a company, so a material's part number is its material id.
Because the join is on the readable id, one material can span several item records: separate revisions, and a separate item per stock size. The sizes you assign become selectable variants on jobs and purchase orders, each its own item row sharing the material's id.
Only substance and form are required to generate a material
When Carbon generates the material and its ids, materialSubstanceId and materialFormId are required; dimension, finish, grade, and type are optional. A material is minimally "a substance in a form" and everything else refines it.
Naming and uniqueness
Carbon composes a material's display name from substance, form, and optional finish, grade, and dimension names. Substance, form, and type codes compose the material code. Property combinations provide a structured identity rather than relying on free text.
Because dimensions belong to forms and grades and finishes belong to substances, a valid material is always an internally consistent set of choices. You cannot pick a bar dimension for a sheet, or a stainless grade for aluminum, because those lists are filtered to the parent you already chose.