Rename the equipment domain to machines; retype the models catalog (ADR-011)
All checks were successful
CI / backend (push) Successful in 23s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 8s

The equipment plugin is now the machines plugin, ending the UI-vs-code
vocabulary split while the contract is pre-1.0 and nothing external
depends on the old names.

- plugins/equipment -> plugins/machines: manifest, class, /api/machines,
  machines.* permissions, registry key (with an auto-migrating load shim
  for existing installs).
- Tables: equipment -> machines (equipmentid -> machineid) and
  equipmenttypes -> machinetypes, renamed in the plugin's own migration
  chain (machines0002rename), idempotent for both upgrading and fresh
  installs.
- The legacy core machinetypes lookup actually types the vendor MODELS
  catalog, so it is renamed losslessly to modeltypes
  (models.modeltypeid, /api/modeltypes, Model Types settings page)
  rather than collapsed, freeing the machinetypes name. Core migration
  7d17_machines_rename also flips data in place: assettypes row
  equipment -> machine, auditlog entitytype, identifier_/search_
  settings keys, permission rows, and renames alembic_version_equipment.
- Frontend: machinesApi/modeltypesApi, item.machine response shape,
  assettype value compares 'equipment' -> 'machine' (map, search,
  custom fields, relationships), routes machines.js with plugin gating
  retagged, /print/machine-badge, Machine Types (subtypes) and Model
  Types (catalog) settings pages, machines-by-type report id.
- Docs swept; ADRs left as history per the authoring rule.

Upgrade: flask db upgrade then flask plugin upgrade-all.

Verified: dev DB flipped live (262 machines, 35 modeltypes, 95 models
retyped, zero equipment tables remain); fresh scratch-MySQL install
produces the new names; 341 tests green; naming/style green; frontend
builds; live E2E on machines list/detail, PC relationships, map,
reports, and both settings pages.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-07-11 15:17:42 -04:00
parent 3c43c8d5c8
commit 48d3160bc5
84 changed files with 4755 additions and 4317 deletions

View File

@@ -7,7 +7,7 @@
<div class="card">
<div v-if="loading" class="loading">Loading...</div>
<form v-else @submit.prevent="saveEquipment">
<form v-else @submit.prevent="saveMachine">
<!-- Identity Section -->
<h3 class="form-section-title">Identity</h3>
<div class="form-row">
@@ -34,8 +34,8 @@
</div>
</div>
<div class="form-row" v-if="isEnabled('gaugelabreference', 'equipment') || isEnabled('maintenancereference', 'equipment')">
<div class="form-group" v-if="isEnabled('gaugelabreference', 'equipment')">
<div class="form-row" v-if="isEnabled('gaugelabreference', 'machine') || isEnabled('maintenancereference', 'machine')">
<div class="form-group" v-if="isEnabled('gaugelabreference', 'machine')">
<label for="gaugelabreference">Gauge Lab Reference</label>
<input
id="gaugelabreference"
@@ -46,7 +46,7 @@
<small class="form-help">Authoritative gauge lab asset reference (if tracked)</small>
</div>
<div class="form-group" v-if="isEnabled('maintenancereference', 'equipment')">
<div class="form-group" v-if="isEnabled('maintenancereference', 'machine')">
<label for="maintenancereference">Maintenance Reference</label>
<input
id="maintenancereference"
@@ -88,23 +88,23 @@
</div>
</div>
<!-- Equipment Hardware Section -->
<!-- Machine Hardware Section -->
<h3 class="form-section-title">Machine Hardware</h3>
<div class="form-row">
<div class="form-group">
<label for="equipmenttypeid">Equipment Type</label>
<label for="machinetypeid">Machine Type</label>
<select
id="equipmenttypeid"
v-model="form.equipmenttypeid"
id="machinetypeid"
v-model="form.machinetypeid"
class="form-control"
>
<option value="">Select type...</option>
<option
v-for="et in equipmentTypes"
:key="et.equipmenttypeid"
:value="et.equipmenttypeid"
v-for="mt in machineTypes"
:key="mt.machinetypeid"
:value="mt.machinetypeid"
>
{{ et.equipmenttype }}
{{ mt.machinetype }}
</option>
</select>
</div>
@@ -294,7 +294,7 @@
{{ pc.assetnumber }}{{ pc.name ? ` (${pc.name})` : '' }}
</option>
</select>
<small class="form-help">Select the PC that controls this equipment</small>
<small class="form-help">Select the PC that controls this machine</small>
</div>
<div class="form-group" v-if="controllingPcId">
@@ -312,7 +312,7 @@
{{ rt.relationshiptype }}
</option>
</select>
<small class="form-help">How the PC connects to this equipment</small>
<small class="form-help">How the PC connects to this machine</small>
</div>
</div>
@@ -328,8 +328,8 @@
></textarea>
</div>
<!-- Site-defined custom fields for equipment -->
<CustomFieldsInputs ref="customFieldsRef" :assettypeid="EQUIPMENT_ASSETTYPEID" :assetid="currentAssetId" />
<!-- Site-defined custom fields for machines -->
<CustomFieldsInputs ref="customFieldsRef" :assettypeid="MACHINE_ASSETTYPEID" :assetid="currentAssetId" />
<div v-if="error" class="error-message">{{ error }}</div>
@@ -347,7 +347,7 @@
<script setup>
import { ref, onMounted, computed, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { equipmentApi, vendorsApi, locationsApi, modelsApi, businessunitsApi, computersApi, assetsApi } from '../../api'
import { machinesApi, vendorsApi, locationsApi, modelsApi, businessunitsApi, computersApi, assetsApi } from '../../api'
import ShopFloorMap from '../../components/ShopFloorMap.vue'
import Modal from '../../components/Modal.vue'
import CustomFieldsInputs from '../../components/CustomFieldsInputs.vue'
@@ -362,8 +362,8 @@ const router = useRouter()
const isEdit = computed(() => !!route.params.id)
// Seeded asset-type id for equipment (see /api/assets/types).
const EQUIPMENT_ASSETTYPEID = 1
// Seeded asset-type id for machines (see /api/assets/types).
const MACHINE_ASSETTYPEID = 1
const customFieldsRef = ref(null)
const currentAssetId = ref(null)
@@ -380,7 +380,7 @@ const form = ref({
maintenancereference: '',
serialnumber: '',
statusid: 1,
equipmenttypeid: '',
machinetypeid: '',
vendorid: '',
modelnumberid: '',
controllervendorid: '',
@@ -394,7 +394,7 @@ const form = ref({
mapy: null
})
const equipmentTypes = ref([])
const machineTypes = ref([])
const statuses = ref([])
const vendors = ref([])
const locations = ref([])
@@ -405,9 +405,9 @@ const relationshipTypes = ref([])
const controllingPcId = ref(null)
const relationshipTypeId = ref(null)
const existingRelationshipId = ref(null)
const currentEquipment = ref(null)
const currentMachine = ref(null)
// Filter models by selected equipment vendor
// Filter models by selected machine vendor
const filteredModels = computed(() => {
if (!form.value.vendorid) return models.value
return models.value.filter(m => m.vendorid === form.value.vendorid)
@@ -443,7 +443,7 @@ onMounted(async () => {
try {
// Load reference data in parallel
const [typesRes, statusRes, vendorRes, locRes, allModels, buRes, pcsRes, relTypesRes] = await Promise.all([
equipmentApi.types.list(),
machinesApi.types.list(),
assetsApi.statuses.list(),
vendorsApi.list({ perpage: 500 }),
locationsApi.list({ perpage: 500 }),
@@ -453,7 +453,7 @@ onMounted(async () => {
assetsApi.types.list() // Used for relationship types, will fix below
])
equipmentTypes.value = typesRes.data.data || []
machineTypes.value = typesRes.data.data || []
statuses.value = statusRes.data.data || []
vendors.value = vendorRes.data.data || []
locations.value = locRes.data.data || []
@@ -479,12 +479,12 @@ onMounted(async () => {
relationshipTypeId.value = controlsType.relationshiptypeid
}
// Load equipment if editing
// Load machine if editing
if (isEdit.value) {
const response = await equipmentApi.get(route.params.id)
const response = await machinesApi.get(route.params.id)
const data = response.data.data
currentAssetId.value = data.assetid || null
currentEquipment.value = data
currentMachine.value = data
form.value = {
assetnumber: data.assetnumber || '',
@@ -493,15 +493,15 @@ onMounted(async () => {
maintenancereference: data.maintenancereference || '',
serialnumber: data.serialnumber || '',
statusid: data.statusid || 1,
equipmenttypeid: data.equipment?.equipmenttypeid || '',
vendorid: data.equipment?.vendorid || '',
modelnumberid: data.equipment?.modelnumberid || '',
controllervendorid: data.equipment?.controllervendorid || '',
controllermodelid: data.equipment?.controllermodelid || '',
machinetypeid: data.machine?.machinetypeid || '',
vendorid: data.machine?.vendorid || '',
modelnumberid: data.machine?.modelnumberid || '',
controllervendorid: data.machine?.controllervendorid || '',
controllermodelid: data.machine?.controllermodelid || '',
locationid: data.locationid || '',
businessunitid: data.businessunitid || '',
requiresmanualconfig: data.equipment?.requiresmanualconfig || false,
islocationonly: data.equipment?.islocationonly || false,
requiresmanualconfig: data.machine?.requiresmanualconfig || false,
islocationonly: data.machine?.islocationonly || false,
notes: data.notes || '',
mapx: data.mapx ?? null,
mapy: data.mapy ?? null
@@ -553,7 +553,7 @@ function clearMapPosition() {
tempMapPosition.value = null
}
async function saveEquipment() {
async function saveMachine() {
error.value = ''
saving.value = true
@@ -565,7 +565,7 @@ async function saveEquipment() {
maintenancereference: form.value.maintenancereference || null,
serialnumber: form.value.serialnumber || null,
statusid: form.value.statusid || 1,
equipmenttypeid: form.value.equipmenttypeid || null,
machinetypeid: form.value.machinetypeid || null,
vendorid: form.value.vendorid || null,
modelnumberid: form.value.modelnumberid || null,
controllervendorid: form.value.controllervendorid || null,
@@ -579,17 +579,17 @@ async function saveEquipment() {
mapy: form.value.mapy
}
let savedEquipment
let savedMachine
let assetId
if (isEdit.value) {
const response = await equipmentApi.update(route.params.id, data)
savedEquipment = response.data.data
assetId = savedEquipment.assetid
const response = await machinesApi.update(route.params.id, data)
savedMachine = response.data.data
assetId = savedMachine.assetid
} else {
const response = await equipmentApi.create(data)
savedEquipment = response.data.data
assetId = savedEquipment.assetid
const response = await machinesApi.create(data)
savedMachine = response.data.data
assetId = savedMachine.assetid
}
// Handle relationship (controlling PC)
@@ -604,10 +604,10 @@ async function saveEquipment() {
}
}
router.push(`/machines/${savedEquipment.equipment?.equipmentid || route.params.id}`)
router.push(`/machines/${savedMachine.machine?.machineid || route.params.id}`)
} catch (err) {
console.error('Error saving equipment:', err)
error.value = apiError(err, 'Failed to save equipment')
console.error('Error saving machine:', err)
error.value = apiError(err, 'Failed to save machine')
} finally {
saving.value = false
}
@@ -632,7 +632,7 @@ async function saveRelationship(assetId) {
await assetsApi.deleteRelationship(existingRelationshipId.value)
}
// Create new relationship (PC controls Equipment, so PC is source, Equipment is target)
// Create new relationship (PC controls Machine, so PC is source, Machine is target)
await assetsApi.createRelationship({
sourceassetid: controllingPcId.value,
targetassetid: assetId,