Skip to main content

Data Mapping

Users

Legacy source (auth_user table)MakerLab fieldNotes
idlegacy_idPreserved for idempotent re-runs
first_name + last_namenameConcatenated
emailemailNatural key; used for deduplication
is_superuser or is_staff = truerole = "lab_technician"
Otherwiserole = "student"Professor detection by email is approximate — to verify
username (if starts with digits)nmecStudent number extraction — to verify

Role mapping rule (schema constraint: must be one of student, professor, lab_technician):

  • is_superuser=True or is_staff=True"lab_technician"
  • All others → "student" (professor detection via email pattern is approximate)

Projects

Legacy sourceMakerLab fieldNotes
article.idlegacy_id
article.titlename
content (parsed)descriptionFirst 500 chars of plain text from wiki content
<owner> elementcreated_byFK to migrated user
Always "pending"status"draft" would violate CHECK constraint

Status mapping (schema constraint: must be one of pending, active, rejected, completed, archived):

  • All legacy projects are imported with status "pending" regardless of their wiki state.

Project members

Legacy XML elementproject_members.role
<owner>"leader"
<member>"member"
<mentor>"advisor"

Membership is derived from the project XML structure, not a separate table in the legacy data.


Equipment models

Equipment articles in the wiki contain structured markdown-like content. The extractor parses:

Wiki fieldMakerLab fieldNotes
Article titlename
** Família: **familyCategory grouping
** Sub-Família: **sub_family
** Código: **reference_code (normalized) + legacy_reference_code (exact)Código is the equipment SKU
** Preço (c/ IVA): **priceParsed as Decimal; supports formats like "8.61€"
** Fornecedor: **supplier
** Localização: **locationStored at equipment level

Deduplication: Multiple wiki revisions sharing the same Código are grouped into a single EquipmentModel. Each revision within the group becomes a separate physical asset.

Equipment items with blank Código are skipped — they cannot be used to create a model without an identifier.


Equipment assets

LegacyMakerLab/Snipe-ITNotes
Wiki article idlegacy_id in equipment
Article idAsset tag (e.g., CODIGO-1)Unique per asset
quantity field (if > 1)Multiple assets createdEach physical unit gets a sequential tag
locationequipment.location + Snipe-IT asset location
Always "available"statusAll imported equipment defaults to available

Snipe-IT entity creation

MakerLab entitySnipe-IT entityLookup key
EquipmentModelSnipe-IT Modelmodel_number (stores the Código)
EquipmentSnipe-IT Assetasset_tag
User (technician)Snipe-IT Useremail
EquipmentModel.familySnipe-IT CategoryCategory name
EquipmentModel.supplierSnipe-IT ManufacturerManufacturer name

Categories and manufacturers are dynamically created in Snipe-IT if they don't already exist. No pre-configuration is required.


Idempotency

EntityUpsert key
User (PostgreSQL)legacy_id, then email as fallback
Project (PostgreSQL)legacy_id
Equipment model (PostgreSQL)legacy_id
Equipment (PostgreSQL)legacy_id
User (Snipe-IT)email
Model (Snipe-IT)model_number (Código)
Asset (Snipe-IT)asset_tag

Running the migration twice will upsert existing records without creating duplicates.


Legacy ID columns

The following columns are added (if not already present) by the migration schema bootstrap step:

TableColumnType
userslegacy_idBIGINT NULL UNIQUE
projectslegacy_idBIGINT NULL UNIQUE
equipment_modelslegacy_idBIGINT NULL UNIQUE
equipment_modelslegacy_reference_codeTEXT NULL
equipmentlegacy_idBIGINT NULL UNIQUE

These columns are already present in the current schema (infra/db/init/schema.sql). The migration bootstrap step uses ALTER TABLE ... ADD COLUMN IF NOT EXISTS as a safety measure.