Rename the equipment domain to machines; retype the models catalog (ADR-011)
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:
@@ -44,7 +44,7 @@
|
||||
<small v-if="m.description" class="text-muted">{{ m.description }}</small>
|
||||
</td>
|
||||
<td>{{ m.vendor || '-' }}</td>
|
||||
<td>{{ m.machinetype || '-' }}</td>
|
||||
<td>{{ m.modeltype || '-' }}</td>
|
||||
<td>
|
||||
<a v-if="m.documentationurl" :href="m.documentationurl" target="_blank" class="btn btn-sm btn-link">
|
||||
View Docs
|
||||
@@ -108,11 +108,11 @@
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="machinetypeid">Machine Type</label>
|
||||
<select id="machinetypeid" v-model="form.machinetypeid" class="form-control">
|
||||
<label for="modeltypeid">Model Type</label>
|
||||
<select id="modeltypeid" v-model="form.modeltypeid" class="form-control">
|
||||
<option value="">Select type...</option>
|
||||
<option v-for="mt in machineTypes" :key="mt.machinetypeid" :value="mt.machinetypeid">
|
||||
{{ mt.machinetype }}
|
||||
<option v-for="mt in modelTypes" :key="mt.modeltypeid" :value="mt.modeltypeid">
|
||||
{{ mt.modeltype }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -181,7 +181,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { modelsApi, vendorsApi, machinetypesApi } from '../../api'
|
||||
import { modelsApi, vendorsApi, modeltypesApi } from '../../api'
|
||||
import PaginationBar from '../../components/PaginationBar.vue'
|
||||
import { useToast } from '../../composables/toast'
|
||||
import { apiError } from '../../utils/apiError'
|
||||
@@ -189,7 +189,7 @@ const toast = useToast()
|
||||
|
||||
const models = ref([])
|
||||
const vendors = ref([])
|
||||
const machineTypes = ref([])
|
||||
const modelTypes = ref([])
|
||||
const loading = ref(true)
|
||||
const search = ref('')
|
||||
const vendorFilter = ref('')
|
||||
@@ -208,7 +208,7 @@ const modelToDelete = ref(null)
|
||||
const form = ref({
|
||||
modelnumber: '',
|
||||
vendorid: '',
|
||||
machinetypeid: '',
|
||||
modeltypeid: '',
|
||||
description: '',
|
||||
documentationurl: '',
|
||||
imageurl: '',
|
||||
@@ -221,7 +221,7 @@ onMounted(async () => {
|
||||
await Promise.all([
|
||||
loadModels(),
|
||||
loadVendors(),
|
||||
loadMachineTypes()
|
||||
loadModelTypes()
|
||||
])
|
||||
})
|
||||
|
||||
@@ -251,12 +251,12 @@ async function loadVendors() {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadMachineTypes() {
|
||||
async function loadModelTypes() {
|
||||
try {
|
||||
const response = await machinetypesApi.list({ perpage: 100 })
|
||||
machineTypes.value = response.data.data || []
|
||||
const response = await modeltypesApi.list({ perpage: 100 })
|
||||
modelTypes.value = response.data.data || []
|
||||
} catch (err) {
|
||||
console.error('Error loading machine types:', err)
|
||||
console.error('Error loading model types:', err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ function openModal(m = null) {
|
||||
form.value = {
|
||||
modelnumber: m.modelnumber || '',
|
||||
vendorid: m.vendorid || '',
|
||||
machinetypeid: m.machinetypeid || '',
|
||||
modeltypeid: m.modeltypeid || '',
|
||||
description: m.description || '',
|
||||
documentationurl: m.documentationurl || '',
|
||||
imageurl: m.imageurl || '',
|
||||
@@ -295,7 +295,7 @@ function openModal(m = null) {
|
||||
form.value = {
|
||||
modelnumber: '',
|
||||
vendorid: '',
|
||||
machinetypeid: '',
|
||||
modeltypeid: '',
|
||||
description: '',
|
||||
documentationurl: '',
|
||||
imageurl: '',
|
||||
@@ -318,7 +318,7 @@ async function saveModel() {
|
||||
try {
|
||||
const data = { ...form.value }
|
||||
if (!data.vendorid) data.vendorid = null
|
||||
if (!data.machinetypeid) data.machinetypeid = null
|
||||
if (!data.modeltypeid) data.modeltypeid = null
|
||||
|
||||
if (editingModel.value) {
|
||||
await modelsApi.update(editingModel.value.modelnumberid, data)
|
||||
|
||||
Reference in New Issue
Block a user