Skip to content

2. The equipment category entity + seeded data

The entity

spk-assembly/metadata/entities/oeq_category.json (real file):

json
{
  "entity": {
    "name": "oeq_category",
    "tableName": "oeq_category",
    "label": "{\"en\":\"Equipment Category\"}",
    "category": "office-equipment",
    "icon": "category",
    "color": "#2563EB",
    "pkStrategy": "identity"
  },
  "fields": [
    { "fieldName": "category_code", "label": "\"Category Code\"", "dataType": "text", "nullable": false, "required": true, "isUnique": true, "isIndexed": true, "isDisplayField": true, "displayOrder": 1 },
    { "fieldName": "category_name", "label": "\"Category Name\"", "dataType": "text", "nullable": false, "required": true, "displayOrder": 2 },
    { "fieldName": "description", "label": "\"Description\"", "dataType": "text", "nullable": true, "required": false, "displayOrder": 3 },
    { "fieldName": "status", "label": "\"Status\"", "dataType": "enum", "nullable": false, "required": true, "isIndexed": true, "defaultValue": "ACTIVE", "typeParams": "{\"enumValues\":[\"ACTIVE\",\"INACTIVE\"]}", "displayOrder": 4 },
    { "fieldName": "seeded_by", "label": "\"Seeded By\"", "dataType": "text", "nullable": true, "required": false, "displayOrder": 5 }
  ]
}

Note the two JSON-encoding rules: entity.label is "{\"en\":\"...\"}" (an i18n object as a string), each field label is "\"...\"" (a JSON string literal). A bare string in either place fails the install.

seeded_by is a plain text column the seeder will stamp with the plugin id.

The seed data

spk-assembly/metadata/seed-data/office-equipment-categories.json (real file):

json
{
  "entity": "oeq_category",
  "keyFields": ["category_code"],
  "source": "office-equipment",
  "rows": [
    { "category_code": "LAPTOP",  "category_name": "Laptops",  "description": "Portable computers", "status": "ACTIVE", "seeded_by": "office-equipment" },
    { "category_code": "MONITOR", "category_name": "Monitors", "description": "External displays",  "status": "ACTIVE", "seeded_by": "office-equipment" },
    { "category_code": "PHONE",   "category_name": "Phones",   "description": "Mobile handsets",    "status": "ACTIVE", "seeded_by": "office-equipment" },
    { "category_code": "HEADSET", "category_name": "Headsets", "description": "Audio headsets",     "status": "ACTIVE", "seeded_by": "office-equipment" }
  ]
}
  • keyFields: ["category_code"] — the natural key. Re-installs match on this and never duplicate.
  • source: "office-equipment" — stamped into seeded_by.

Verify

bash
erp schema validate spk-assembly/metadata/entities/oeq_category.json --schema entity-definition
erp schema validate spk-assembly/metadata/seed-data/office-equipment-categories.json --schema plugin-seed-data

Both print OK — ... matches schema ....

After the module is published (chapter 8), this is what the seeding did — from the real install log:

PluginDataSeedInstaller: office-equipment-categories.json -> entity oeq_category (tenant 2): 4 created, 0 updated, 0 unchanged

and the rows are live:

bash
$ erp api get "/api/v1/entities/oeq_category/records/query?size=10"
{ "rows": [
  { "id": 1, "category_code": "LAPTOP",  "category_name": "Laptops",  "status": "ACTIVE", "seeded_by": "office-equipment" },
  { "id": 2, "category_code": "MONITOR", "category_name": "Monitors", "status": "ACTIVE", "seeded_by": "office-equipment" },
  { "id": 3, "category_code": "PHONE",   "category_name": "Phones",   "status": "ACTIVE", "seeded_by": "office-equipment" },
  { "id": 4, "category_code": "HEADSET", "category_name": "Headsets", "status": "ACTIVE", "seeded_by": "office-equipment" }
], "total": 4 }

Publish again with a fifth category and only that one is inserted — the seeder is idempotent by keyFields.

Next: 3. The equipment register entity