Add the printedparts plugin: 3D-printed parts storefront and kiosk

Catalog with photos and append-only print-file revisions, a stock
ledger attributing every take/restock/adjust to a badge-resolved
employee, a touch kiosk (scan bin, scan badge, keypad quantity) with a
deliberately open decrement-only take endpoint, 1x0.5in CODE128 bin
labels, low-stock email alerts to selected users, roles, or addresses,
and stock/consumption/by-person reports with a cache-vs-ledger
reconcile. Ships disabled; enable per site. Contract 0.13.0 adds the
mailer and the User/Role models to the plugin surface.
This commit is contained in:
2026-07-17 09:29:01 -04:00
parent 2fda94f67a
commit 11c8d79ba4
35 changed files with 3231 additions and 3 deletions

View File

@@ -65,6 +65,14 @@ const routes = [
name: 'shopfloor',
component: () => import('../views/ShopfloorDashboard.vue')
},
{
// Touch kiosk for taking 3D-printed parts: scan bin, scan badge, keypad.
// Open on purpose - see the decision record in the printedparts proposal.
path: '/parts-kiosk',
name: 'parts-kiosk',
component: () => import('../views/printedparts/PartsKiosk.vue'),
meta: { plugin: 'printedparts' }
},
{
path: '/tv',
name: 'tv',
@@ -109,6 +117,14 @@ const routes = [
component: () => import('../views/print/USBLabelBatch.vue'),
meta: { plugin: 'usb' }
},
{
// Unlike the other print pages this one requires login: it lists the
// whole catalog, which is printedparts.view-gated at the API.
path: '/print/printedparts-labels',
name: 'print-printedparts-labels',
component: () => import('../views/print/PrintedPartsLabels.vue'),
meta: { requiresAuth: true, plugin: 'printedparts' }
},
{
path: '/',
component: AppLayout,

View File

@@ -0,0 +1,41 @@
/**
* Printedparts plugin routes.
*
* Auto-discovered by the router via import.meta.glob, so no registration
* edit is needed. Every route carries meta.plugin 'printedparts' so the ADR-009
* guard redirects to the dashboard when the printedparts backend plugin is
* disabled. Form routes add requiresAuth so anonymous users cannot reach
* create or edit.
*/
export default [
{
path: 'printedparts',
name: 'printedparts',
component: () => import('../../views/printedparts/PrintedItemsList.vue'),
meta: { requiresAuth: true, plugin: 'printedparts' }
},
{
path: 'printedparts/new',
name: 'printedparts-new',
component: () => import('../../views/printedparts/PrintedItemForm.vue'),
meta: { requiresAuth: true, plugin: 'printedparts' }
},
{
path: 'printedparts/:id',
name: 'printedparts-detail',
component: () => import('../../views/printedparts/PrintedItemDetail.vue'),
meta: { requiresAuth: true, plugin: 'printedparts' }
},
{
path: 'printedparts/:id/edit',
name: 'printedparts-edit',
component: () => import('../../views/printedparts/PrintedItemForm.vue'),
meta: { requiresAuth: true, plugin: 'printedparts' }
},
{
path: 'settings/printedparts',
name: 'settings-printedparts',
component: () => import('../../views/settings/PrintedPartsSettings.vue'),
meta: { requiresAuth: true, requiresAdmin: true, plugin: 'printedparts' }
}
]