This commit is contained in:
seb
2026-10-28 00:08:45 +01:00
parent fab291f68e
commit 96d0ae6742
88 changed files with 3871 additions and 5334 deletions

View File

@@ -58,45 +58,30 @@ const CLUSTERS = [
label: 'Session & Real-Time Hub',
automats: ['authAutomat', 'sseAutomat'],
},
{
id: 'company_basedata',
label: 'Company & Consolidated Base Data',
automats: ['companyAutomat'],
},
{
id: 'catalog_products',
label: 'Catalog & Products',
automats: ['categoryAutomat', 'categoryViewAutomat', 'artikelAutomat', 'articleDetailAutomat', 'brandAutomat', 'unitAutomat'],
automats: ['categoryAutomat', 'categoryViewAutomat', 'artikelAutomat', 'articleDetailAutomat'],
},
{
id: 'search_indexing',
label: 'Search & Indexing',
automats: ['articleIndexAutomat', 'articleSearchAutomat'],
},
{
id: 'properties_attributes',
label: 'Properties & Attributes',
automats: ['propertyAutomat', 'attributeAutomat'],
},
{
id: 'purchasing_logistics',
label: 'Suppliers & Deliveries',
automats: ['supplierAutomat', 'deliveryAutomat', 'deliveryEditorAutomat'],
label: 'Deliveries & Inbound',
automats: ['deliveryAutomat', 'deliveryEditorAutomat'],
},
{
id: 'sales_crm',
label: 'Sales & CRM',
automats: ['quoteAutomat', 'orderAutomat', 'entityAutomat', 'customergroupAutomat'],
},
{
id: 'inventory_storage',
label: 'Inventory & Warehousing',
automats: ['warehouseAutomat'],
},
{
id: 'finance_config',
label: 'Company & Finance',
automats: ['companyAutomat', 'accountAutomat', 'numberAutomat'],
},
{
id: 'hardware_pos',
label: 'POS & Hardware',
automats: ['posterminalAutomat'],
automats: ['quoteAutomat', 'orderAutomat', 'entityAutomat'],
},
{
id: 'ai_workspace',
@@ -110,8 +95,8 @@ const CLUSTERS = [
},
{
id: 'system_ui',
label: 'UI, Settings & System',
automats: ['navigationAutomat', 'userSettingsAutomat', 'helpAutomat', 'pwaAutomat', 'Legend'],
label: 'UI, Navigation & System',
automats: ['navigationAutomat', 'helpAutomat', 'pwaAutomat', 'Legend'],
},
];
@@ -136,16 +121,16 @@ const AUTOMAT_SPECS = [
{
id: 'authAutomat',
title: 'authAutomat',
subtitle: 'Session & Multi-Tenant Gateway',
subtitle: 'Always-On Session & Multi-Tenant Gateway',
entries: [
{ type: 'STATE', name: 'user: AuthUser', desc: 'Current user & company' },
{ type: 'STATE', name: 'status', desc: '\'anon\' | \'authed\' | \'loading\'' },
{ type: 'STATE', name: 'hasAuth: boolean', desc: 'Authenticated session bit', port: 'p_auth_hasAuth' },
{ type: 'STATE', name: 'hasCompany: boolean', desc: 'hasAuth && selectedCompanyId', port: 'p_auth_hasCompany' },
{ type: 'STATE', name: 'user: AuthUser', desc: 'Current user & company', port: 'p_auth_user' },
{ type: 'STATE', name: 'status', desc: '\'anon\' | \'authed\' | \'loading\'', port: 'p_auth_status' },
{ type: 'ACTION', name: 'bootstrapSession()', desc: 'Restore or fetch session' },
{ type: 'ACTION', name: 'switchCompany(id)', desc: 'Multi-tenant switch', port: 'p_auth_switchCompany' },
{ type: 'ACTION', name: 'logout()', desc: 'Clear session cookie' },
{ type: 'SELECT', name: 'selectSelectedCompanyId()', desc: 'Tenant selector' },
{ type: 'HOOK', name: 'auth/sessionEstablished', desc: 'Session ready lifecycle', port: 'p_auth_status' },
{ type: 'HOOK', name: 'auth/companyChanged', desc: 'Company change signal', port: 'p_auth_user' },
{ type: 'SELECT', name: 'selectHasAuth() / selectHasCompany()', desc: 'Auth & tenant gates' },
{ type: 'API', name: 'GET /api/auth/session', desc: 'Cookie session check' },
],
},
@@ -166,7 +151,32 @@ const AUTOMAT_SPECS = [
],
},
// 2. Catalog & Products
// 2. Company & Consolidated Base Data
{
id: 'companyAutomat',
title: 'companyAutomat',
subtitle: 'Consolidated Company & Base Data Hub',
entries: [
{ type: 'STATE', name: 'current: Company', desc: 'Tax rates, legal & root cat', port: 'p_comp_curr' },
{ type: 'STATE', name: 'numbers: NumberSeq[]', desc: 'Document number sequences', port: 'p_comp_num' },
{ type: 'STATE', name: 'terminals: Posterminal[]', desc: 'POS hardware & categories', port: 'p_comp_pos' },
{ type: 'STATE', name: 'suppliers: Supplier[]', desc: 'Vendors & supplier articles', port: 'p_comp_sup' },
{ type: 'STATE', name: 'units: Unit[]', desc: 'Allowed SI & sales units', port: 'p_comp_unit' },
{ type: 'STATE', name: 'viewerPosition / chatDrawerWidth', desc: 'Persisted user UI settings', port: 'p_comp_usr' },
{ type: 'STATE', name: 'warehouses: Warehouse[]', desc: 'Storage locations & stock', port: 'p_comp_wh' },
{ type: 'STATE', name: 'properties: PropertyName[]', desc: 'Custom text properties', port: 'p_comp_prop' },
{ type: 'STATE', name: 'customergroups: Group[]', desc: 'Pricing discount tiers', port: 'p_comp_cgrp' },
{ type: 'STATE', name: 'carriers: Carrier[]', desc: 'Shipping methods & carriers', port: 'p_comp_car' },
{ type: 'STATE', name: 'brands: Brand[]', desc: 'Catalog brands & logos', port: 'p_comp_brand' },
{ type: 'STATE', name: 'attributes: AttributeName[]', desc: 'Attributes & discrete values', port: 'p_comp_attr' },
{ type: 'STATE', name: 'accounts: Account[]', desc: 'Bank & payment ledgers', port: 'p_comp_acc' },
{ type: 'ACTION', name: 'loadAll() / reset()', desc: 'Fetch or reset all base data' },
{ type: 'SELECT', name: 'selectCompanyRootCategoryId()', desc: 'Root category pointer', port: 'p_comp_root' },
{ type: 'API', name: '/api/company, /api/brand, …', desc: '13 consolidated endpoints' },
],
},
// 3. Catalog & Products
{
id: 'categoryAutomat',
title: 'categoryAutomat',
@@ -225,35 +235,8 @@ const AUTOMAT_SPECS = [
{ type: 'API', name: 'GET /api/article/:sku/supplier', desc: 'Vendor links & prices' },
],
},
{
id: 'brandAutomat',
title: 'brandAutomat',
subtitle: 'Catalog Brands & Makers',
entries: [
{ type: 'STATE', name: 'brands: Brand[]', desc: 'Decoupled brand catalog' },
{ type: 'STATE', name: 'filteredBrands: Brand[]', desc: 'Filtered search slice' },
{ type: 'ACTION', name: 'load(silent)', desc: 'Deduplicated list fetch' },
{ type: 'ACTION', name: 'create() / rename()', desc: 'Brand mutations' },
{ type: 'ACTION', name: 'addImage() / deleteImage()', desc: 'Brand logo AVIF image' },
{ type: 'API', name: 'GET /api/brand', desc: 'Paginated brand records' },
{ type: 'SSE', name: 'brand', desc: 'SSE signal with sender tab' },
],
},
{
id: 'unitAutomat',
title: 'unitAutomat',
subtitle: 'Units of Measure (UoM)',
entries: [
{ type: 'STATE', name: 'units: Unit[]', desc: 'Allowed SI & sales units' },
{ type: 'STATE', name: 'status: \'idle\'|\'ready\'', desc: 'Load lifecycle state' },
{ type: 'ACTION', name: 'load()', desc: 'Fetch localized units' },
{ type: 'ACTION', name: 'upsert(body)', desc: 'Create or update unit' },
{ type: 'ACTION', name: 'delete(id)', desc: 'Remove unused unit' },
{ type: 'API', name: 'GET /api/unit', desc: 'Company unit directory' },
],
},
// 3. Search & Discovery
// 4. Search & Discovery
{
id: 'articleIndexAutomat',
title: 'articleIndexAutomat',
@@ -281,52 +264,11 @@ const AUTOMAT_SPECS = [
],
},
// 4. Properties & Attributes
{
id: 'propertyAutomat',
title: 'propertyAutomat',
subtitle: 'Custom Metadata Properties',
entries: [
{ type: 'STATE', name: 'properties: PropertyName[]', desc: 'Sorted company properties' },
{ type: 'ACTION', name: 'load()', desc: 'Fetch property definitions' },
{ type: 'ACTION', name: 'createProperty()', desc: 'Add new property definition' },
{ type: 'ACTION', name: 'updateProperty()', desc: 'Edit title & sort' },
{ type: 'API', name: 'GET /api/propertyname', desc: 'Company properties' },
{ type: 'SSE', name: 'propertyname', desc: 'Real-time property signal' },
],
},
{
id: 'attributeAutomat',
title: 'attributeAutomat',
subtitle: 'Product Attributes & Discrete Values',
entries: [
{ type: 'STATE', name: 'attributes: AttributeName[]', desc: 'Attributes with sorted values' },
{ type: 'ACTION', name: 'load()', desc: 'Fetch attribute definitions' },
{ type: 'ACTION', name: 'createAttribute()', desc: 'Create attribute group' },
{ type: 'ACTION', name: 'addValue() / deleteValue()', desc: 'Discrete value options' },
{ type: 'API', name: 'GET /api/attributename', desc: 'Attributes & values' },
{ type: 'SSE', name: 'attributename', desc: 'Real-time attribute signal' },
],
},
// 5. Suppliers & Deliveries
{
id: 'supplierAutomat',
title: 'supplierAutomat',
subtitle: 'Supplier Directory & Catalogs',
entries: [
{ type: 'STATE', name: 'suppliers: Supplier[]', desc: 'Active vendor list' },
{ type: 'STATE', name: 'status: \'ready\'', desc: 'Load lifecycle state' },
{ type: 'ACTION', name: 'load()', desc: 'Deduplicated fetch' },
{ type: 'ACTION', name: 'reload()', desc: 'Silent background sync' },
{ type: 'API', name: 'GET /api/supplier', desc: 'Vendor records' },
{ type: 'SSE', name: 'supplier', desc: 'Real-time supplier signal' },
],
},
// 5. Deliveries & Inbound
{
id: 'deliveryAutomat',
title: 'deliveryAutomat',
subtitle: 'createListAutomat (Deliveries)',
subtitle: 'Chunk-Paginated Deliveries',
entries: [
{ type: 'STATE', name: 'items: Delivery[]', desc: 'Company delivery receipts' },
{ type: 'STATE', name: 'status: \'ready\'', desc: 'List lifecycle state' },
@@ -355,7 +297,7 @@ const AUTOMAT_SPECS = [
{
id: 'quoteAutomat',
title: 'quoteAutomat',
subtitle: 'createListAutomat (Quotes)',
subtitle: 'Chunk-Paginated Quotes',
entries: [
{ type: 'STATE', name: 'items: Quote[]', desc: 'Sales quotes / Angebote', port: 'p_quote_items' },
{ type: 'ACTION', name: 'load() / reload()', desc: 'Deduplicated fetch' },
@@ -381,7 +323,7 @@ const AUTOMAT_SPECS = [
{
id: 'entityAutomat',
title: 'entityAutomat',
subtitle: 'createListAutomat (Entities)',
subtitle: 'Customer & Partner Directory',
entries: [
{ type: 'STATE', name: 'items: Entity[]', desc: 'Customers & partners' },
{ type: 'ACTION', name: 'load() / reload()', desc: 'Customer directory load' },
@@ -389,83 +331,8 @@ const AUTOMAT_SPECS = [
{ type: 'API', name: 'GET /api/entity', desc: 'Directory records' },
],
},
{
id: 'customergroupAutomat',
title: 'customergroupAutomat',
subtitle: 'createListAutomat (Groups)',
entries: [
{ type: 'STATE', name: 'items: Customergroup[]', desc: 'Pricing discount tiers' },
{ type: 'ACTION', name: 'load() / reload()', desc: 'Discount group load' },
{ type: 'API', name: 'GET /api/customergroup', desc: 'Pricing tiers' },
],
},
// 7. Inventory & Storage
{
id: 'warehouseAutomat',
title: 'warehouseAutomat',
subtitle: 'Warehouse Locations & Stock',
entries: [
{ type: 'STATE', name: 'warehouses: Warehouse[]', desc: 'Storage areas & bins' },
{ type: 'STATE', name: 'filteredWarehouses', desc: 'Filter search slice' },
{ type: 'ACTION', name: 'load() / reload()', desc: 'Deduplicated sync' },
{ type: 'ACTION', name: 'setFilter(query)', desc: 'Local filter query' },
{ type: 'API', name: 'GET /api/warehouse', desc: 'Warehouse listings' },
{ type: 'SSE', name: 'warehouse', desc: 'Real-time stock movement' },
],
},
// 8. Company & Finance
{
id: 'companyAutomat',
title: 'companyAutomat',
subtitle: 'Active Company Configuration',
entries: [
{ type: 'STATE', name: 'current: Company', desc: 'Tax rates & ISO language', port: 'p_comp_curr' },
{ type: 'ACTION', name: 'load() / reload()', desc: 'Fetch tenant settings' },
{ type: 'SELECT', name: 'selectCompanyTaxrate()', desc: 'Standard tax rate' },
{ type: 'SELECT', name: 'selectCompanyRootCategoryId()', desc: 'Root category pointer', port: 'p_comp_root' },
{ type: 'SELECT', name: 'selectCompanyName()', desc: 'Company legal name' },
{ type: 'API', name: 'GET /api/company/:id', desc: 'Legal & tax profile' },
],
},
{
id: 'accountAutomat',
title: 'accountAutomat',
subtitle: 'createListAutomat (Accounts)',
entries: [
{ type: 'STATE', name: 'items: Account[]', desc: 'Bank & payment ledgers' },
{ type: 'ACTION', name: 'load() / reload()', desc: 'Payment accounts load' },
{ type: 'API', name: 'GET /api/account', desc: 'Chart of accounts' },
],
},
{
id: 'numberAutomat',
title: 'numberAutomat',
subtitle: 'createListAutomat (Sequences)',
entries: [
{ type: 'STATE', name: 'items: NumberSeq[]', desc: 'Invoice/receipt counters' },
{ type: 'ACTION', name: 'load() / reload()', desc: 'Number series sync' },
{ type: 'API', name: 'GET /api/number', desc: 'Document counters' },
],
},
// 9. POS & Hardware
{
id: 'posterminalAutomat',
title: 'posterminalAutomat',
subtitle: 'POS Terminals & Gating',
entries: [
{ type: 'STATE', name: 'terminals: Posterminal[]', desc: 'Hardware terminals', port: 'p_pos_term' },
{ type: 'ACTION', name: 'load()', desc: 'Fetch POS registers' },
{ type: 'ACTION', name: 'create() / delete()', desc: 'Terminal registrations' },
{ type: 'ACTION', name: 'toggleCategory()', desc: 'Gated category filters' },
{ type: 'SELECT', name: 'selectPosterminals()', desc: 'Active registers' },
{ type: 'API', name: 'GET /api/posterminal', desc: 'Terminal device configs' },
],
},
// 10. AI Assistant & Workspace
// 7. AI Assistant & Workspace
{
id: 'chatAutomat',
title: 'chatAutomat',
@@ -497,7 +364,7 @@ const AUTOMAT_SPECS = [
],
},
// 11. Audit & Virtual Grids
// 8. Audit & Virtual Grids
{
id: 'articleHistoryGridAutomat',
title: 'articleHistoryGridAutomat',
@@ -532,7 +399,7 @@ const AUTOMAT_SPECS = [
],
},
// 12. UI, Settings & System
// 9. UI, Navigation & System
{
id: 'navigationAutomat',
title: 'navigationAutomat',
@@ -547,18 +414,6 @@ const AUTOMAT_SPECS = [
{ type: 'ACTION', name: 'clearNavigation()', desc: 'Reset on company switch' },
],
},
{
id: 'userSettingsAutomat',
title: 'userSettingsAutomat',
subtitle: 'IndexedDB User Preferences',
entries: [
{ type: 'STATE', name: 'viewerPosition: \'top\'|\'right\'', desc: 'Editor docking location' },
{ type: 'STATE', name: 'chatDrawerWidth: 460', desc: 'AI drawer pixel width', port: 'p_usr_drawer' },
{ type: 'ACTION', name: 'setViewerPosition()', desc: 'Persist docking' },
{ type: 'ACTION', name: 'setChatDrawerWidth()', desc: 'Persist drawer width' },
{ type: 'HOOK', name: 'persist: true', desc: 'Survives page reloads' },
],
},
{
id: 'helpAutomat',
title: 'helpAutomat',
@@ -595,23 +450,13 @@ const AUTOMAT_SPECS = [
*/
const EDGE_DEFS = [
// Session & Auth lifecycle
{ from: 'authAutomat', to: 'sseAutomat', label: 'bind session & cid', port: 'p_auth_user' },
{ from: 'authAutomat', to: 'companyAutomat', label: 'load company profile', port: 'p_auth_switchCompany' },
{ from: 'authAutomat', to: 'categoryAutomat', label: 'sync tree on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'brandAutomat', label: 'sync brands on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'unitAutomat', label: 'sync units on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'attributeAutomat', label: 'sync attributes on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'propertyAutomat', label: 'sync properties on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'supplierAutomat', label: 'sync suppliers on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'warehouseAutomat', label: 'sync warehouses on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'posterminalAutomat', label: 'sync terminals on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'sseAutomat', label: 'hasAuth -> connect SSE', port: 'p_auth_hasAuth' },
{ from: 'authAutomat', to: 'companyAutomat', label: 'hasCompany -> loadAll()', port: 'p_auth_hasCompany' },
{ from: 'authAutomat', to: 'categoryAutomat', label: 'sync tree on hasCompany', port: 'p_auth_hasCompany' },
{ from: 'authAutomat', to: 'deliveryAutomat', label: 'sync deliveries on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'quoteAutomat', label: 'sync quotes on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'orderAutomat', label: 'sync orders on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'entityAutomat', label: 'sync entities on authed', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'customergroupAutomat', label: 'sync customer groups', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'numberAutomat', label: 'sync number series', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'accountAutomat', label: 'sync payment accounts', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'chatAutomat', label: 'auth chat & reload', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'vfsAutomat', label: 'load company vfs', port: 'p_auth_status' },
{ from: 'authAutomat', to: 'articleHistoryGridAutomat', label: 'reload history on authed', port: 'p_auth_status' },
@@ -624,16 +469,12 @@ const EDGE_DEFS = [
{ from: 'sseAutomat', to: 'articleIndexAutomat', label: '\'articles\' sse trigger', port: 'p_sse_events' },
{ from: 'sseAutomat', to: 'artikelAutomat', label: '\'article-<sku>\' sse reload', port: 'p_sse_events' },
{ from: 'sseAutomat', to: 'articleDetailAutomat', label: 'invalidateArticle(sku)', port: 'p_sse_events' },
{ from: 'sseAutomat', to: 'warehouseAutomat', label: '\'warehouse\' sse trigger', port: 'p_sse_events' },
{ from: 'sseAutomat', to: 'supplierAutomat', label: '\'supplier\' sse trigger', port: 'p_sse_events' },
{ from: 'sseAutomat', to: 'brandAutomat', label: '\'brand\' sse trigger', port: 'p_sse_events' },
{ from: 'sseAutomat', to: 'attributeAutomat', label: '\'attributename\' sse', port: 'p_sse_events' },
{ from: 'sseAutomat', to: 'propertyAutomat', label: '\'propertyname\' sse', port: 'p_sse_events' },
{ from: 'sseAutomat', to: 'companyAutomat', label: 'warehouse/supplier/brand/attr/prop/carrier sse', port: 'p_sse_events' },
{ from: 'sseAutomat', to: 'orderAutomat', label: '\'order\'/\'shipment\' sse', port: 'p_sse_events' },
{ from: 'sseAutomat', to: 'vfsAutomat', label: '\'vfs\' sse mutation', port: 'p_sse_events' },
// Catalog, Indexing & Search pipeline
{ from: 'companyAutomat', to: 'categoryAutomat', label: 'rootCategoryId', port: 'p_comp_root' },
{ from: 'companyAutomat', to: 'categoryAutomat', label: 'rootCategoryId & terminals', port: 'p_comp_root' },
{ from: 'categoryAutomat', to: 'categoryViewAutomat', label: 'attachTree & warm slugs', port: 'p_cat_loadTree' },
{ from: 'categoryViewAutomat', to: 'articleIndexAutomat', label: 'derived union index', port: 'p_catview_collect' },
{ from: 'articleIndexAutomat', to: 'articleSearchAutomat', label: 'query index items', port: 'p_idx_items' },
@@ -643,18 +484,13 @@ const EDGE_DEFS = [
{ from: 'articleDetailAutomat', to: 'artikelAutomat', label: 'watch SKU details', port: 'p_artdet_hist' },
// Purchasing & Deliveries
{ from: 'deliveryEditorAutomat', to: 'supplierAutomat', label: 'match vendor catalog', port: 'p_deled_supplier' },
{ from: 'deliveryEditorAutomat', to: 'companyAutomat', label: 'match vendor catalog', port: 'p_deled_supplier' },
{ from: 'deliveryEditorAutomat', to: 'artikelAutomat', label: 'lookup SKU & pack units', port: 'p_deled_lines' },
{ from: 'deliveryEditorAutomat', to: 'deliveryAutomat', label: 'commit delivery receipt', port: 'p_deled_commit' },
// Sales & CRM
{ from: 'quoteAutomat', to: 'orderAutomat', label: 'convert quote to order', port: 'p_quote_items' },
{ from: 'orderAutomat', to: 'entityAutomat', label: 'customer lookup', port: 'p_order_items' },
{ from: 'companyAutomat', to: 'customergroupAutomat', label: 'poscustomergroup', port: 'p_comp_curr' },
// POS & Hardware
{ from: 'posterminalAutomat', to: 'categoryAutomat', label: 'filter enabled roots', port: 'p_pos_term' },
{ from: 'companyAutomat', to: 'posterminalAutomat', label: 'company context', port: 'p_comp_curr' },
// AI Assistant & Workspace
{ from: 'chatAutomat', to: 'vfsAutomat', label: 'inspect / edit applets', port: 'p_chat_msg' },
@@ -665,7 +501,7 @@ const EDGE_DEFS = [
{ from: 'navigationAutomat', to: 'artikelAutomat', label: 'restore last SKU', port: 'p_nav_sku' },
{ from: 'navigationAutomat', to: 'categoryAutomat', label: 'restore last category', port: 'p_nav_catslug' },
{ from: 'navigationAutomat', to: 'deliveryEditorAutomat', label: 'restore draft path', port: 'p_nav_delpath' },
{ from: 'userSettingsAutomat', to: 'chatAutomat', label: 'chatDrawerWidth', port: 'p_usr_drawer' },
{ from: 'companyAutomat', to: 'chatAutomat', label: 'chatDrawerWidth', port: 'p_comp_usr' },
{ from: 'helpAutomat', to: 'navigationAutomat', label: 'route-contextual help', port: 'p_help_active' },
// Self-loops