diff --git a/src/configs/assetApiConfig.js b/src/configs/assetApiConfig.js index bb2290e..f6428df 100644 --- a/src/configs/assetApiConfig.js +++ b/src/configs/assetApiConfig.js @@ -6,6 +6,7 @@ module.exports = { baseUrl: BASE_URL, registerPath: '/assets/store', updatePath: (tag) => `/assets/${encodeURIComponent(tag)}/edit`, + updateMethod: 'POST', headers: { accept: 'application/json', Authorization: AUTHORIZATION, diff --git a/src/helper/assetUtils.js b/src/helper/assetUtils.js index 957864f..8f76907 100644 --- a/src/helper/assetUtils.js +++ b/src/helper/assetUtils.js @@ -65,6 +65,8 @@ function buildAssetPayload({ assetSelection = {}, registrationDefaults = {} }) { const assetName = (rawName || 'Measurement asset').toString(); const assetDescription = (assetSelection.assetDescription || assetSelection.description || assetName).toString(); + const modelId = metadata.product_model_id ?? metadata.id ?? assetSelection.modelId ?? assetSelection.model ?? null; + const payload = { profile_id: toNumber(defaults.profileId, 1), location_id: toNumber(defaults.locationId, 1), @@ -72,11 +74,62 @@ function buildAssetPayload({ assetSelection = {}, registrationDefaults = {} }) { asset_name: assetName, asset_description: assetDescription, asset_status: (assetSelection.assetStatus || defaults.status || 'actief').toString(), - product_model_id: metadata.product_model_id || metadata.id || assetSelection.model || null, - product_model_uuid: metadata.product_model_uuid || metadata.uuid || metadata.id || assetSelection.model || null, + product_model_id: modelId, + product_model_uuid: metadata.product_model_uuid || metadata.uuid || null, child_assets: toArray(defaults.childAssets) }; + const validation = []; + const missing = []; + const tooLong = []; + const invalid = []; + + if (!payload.asset_name) { + missing.push('asset_name'); + } else if (payload.asset_name.length > 100) { + tooLong.push('asset_name'); + } + + if (!payload.asset_status) { + missing.push('asset_status'); + } else if (payload.asset_status.length > 20) { + tooLong.push('asset_status'); + } + + if (!Number.isInteger(payload.location_id)) { + invalid.push('location_id'); + } + if (!Number.isInteger(payload.process_id)) { + invalid.push('process_id'); + } + if (!Number.isInteger(payload.profile_id)) { + invalid.push('profile_id'); + } + + if (!Number.isInteger(payload.product_model_id)) { + invalid.push('product_model_id'); + } + + if (!Array.isArray(payload.child_assets)) { + invalid.push('child_assets'); + } + + if (missing.length) { + validation.push(`missing: ${missing.join(', ')}`); + } + if (tooLong.length) { + validation.push(`too long: ${tooLong.join(', ')}`); + } + if (invalid.length) { + validation.push(`invalid type: ${invalid.join(', ')}`); + } + + if (validation.length) { + console.warn('[assetUtils] payload validation', validation.join(' | ')); + } else { + console.info('[assetUtils] payload validation ok'); + } + const tagNumber = typeof assetSelection.tagNumber === 'string' && assetSelection.tagNumber.trim() ? assetSelection.tagNumber.trim() : null; @@ -161,7 +214,7 @@ async function syncAsset({ assetSelection = {}, registrationDefaults = {}, apiCo ? apiConfig.updatePath(tagNumber) : apiConfig.registerPath; const url = prepareUrl(apiConfig.baseUrl, path); - const method = isUpdate ? 'PUT' : 'POST'; + const method = isUpdate ? (apiConfig.updateMethod || 'PUT') : 'POST'; const headers = apiConfig.headers || {}; console.info('[assetUtils] Sending asset update', { nodeContext, method, url }); diff --git a/src/menu/asset.js b/src/menu/asset.js index 2739e50..d84bd81 100644 --- a/src/menu/asset.js +++ b/src/menu/asset.js @@ -1,4 +1,5 @@ const { assetCategoryManager } = require('../../datasets/assetData'); +const assetApiConfig = require('../configs/assetApiConfig.js'); class AssetMenu { constructor({ manager = assetCategoryManager, softwareType = null } = {}) { @@ -67,7 +68,11 @@ class AssetMenu { return { categories: selectedCategories, - defaultCategory: categoryKey + defaultCategory: categoryKey, + apiConfig: { + url: `${assetApiConfig.baseUrl}/apis/products/PLC/integration/`, + headers: { ...assetApiConfig.headers } + } }; } @@ -107,13 +112,7 @@ class AssetMenu { const menuAsset = window.EVOLV.nodes.${nodeName}.menuData.asset || {}; const categories = menuAsset.categories || {}; const defaultCategory = menuAsset.defaultCategory || Object.keys(categories)[0] || null; - const apiConfig = menuAsset.apiConfig || { - url: 'http://localhost:8000/apis/products/PLC/integration/', - headers: { - accept: 'application/json', - Authorization: '4a49332a-fc3e-11f0-bf0a-9457f8d645d9' - } - }; + const apiConfig = menuAsset.apiConfig || {}; const elems = { supplier: document.getElementById('node-input-supplier'), type: document.getElementById('node-input-assetType'), @@ -133,7 +132,7 @@ class AssetMenu { function normalizeModel(model = {}) { return { - id: model.id || model.name, + id: model.id ?? model.name, name: model.name, units: model.units || [] }; @@ -261,7 +260,7 @@ class AssetMenu { ); const activeSupplier = suppliers.find( - (supplier) => (supplier.id || supplier.name) === node.supplier + (supplier) => String(supplier.id || supplier.name) === String(node.supplier) ); const types = activeSupplier ? activeSupplier.types : []; populate( @@ -273,7 +272,7 @@ class AssetMenu { ); const activeType = types.find( - (type) => (type.id || type.name) === node.assetType + (type) => String(type.id || type.name) === String(node.assetType) ); const models = activeType ? activeType.models : []; populate( @@ -285,10 +284,11 @@ class AssetMenu { ); const activeModel = models.find( - (model) => (model.id || model.name) === node.model + (model) => String(model.id || model.name) === String(node.model) ); if (activeModel) { node.modelMetadata = activeModel; + node.modelName = activeModel.name; } populate( elems.unit, @@ -376,7 +376,7 @@ class AssetMenu { const category = getActiveCategory(); const supplier = category ? category.suppliers.find( - (item) => (item.id || item.name) === elems.supplier.value + (item) => String(item.id || item.name) === String(elems.supplier.value) ) : null; const types = supplier ? supplier.types : []; @@ -396,12 +396,12 @@ class AssetMenu { const category = getActiveCategory(); const supplier = category ? category.suppliers.find( - (item) => (item.id || item.name) === elems.supplier.value + (item) => String(item.id || item.name) === String(elems.supplier.value) ) : null; const type = supplier ? supplier.types.find( - (item) => (item.id || item.name) === elems.type.value + (item) => String(item.id || item.name) === String(elems.type.value) ) : null; const models = type ? type.models : []; @@ -426,20 +426,21 @@ class AssetMenu { const category = getActiveCategory(); const supplier = category ? category.suppliers.find( - (item) => (item.id || item.name) === elems.supplier.value + (item) => String(item.id || item.name) === String(elems.supplier.value) ) : null; const type = supplier ? supplier.types.find( - (item) => (item.id || item.name) === elems.type.value + (item) => String(item.id || item.name) === String(elems.type.value) ) : null; const model = type ? type.models.find( - (item) => (item.id || item.name) === elems.model.value + (item) => String(item.id || item.name) === String(elems.model.value) ) : null; node.modelMetadata = model; + node.modelName = model ? model.name : ''; populate( elems.unit, model ? model.units || [] : [], @@ -634,6 +635,9 @@ class AssetMenu { acc[field] = node[field]; return acc; }, {}); + if (node.modelMetadata && typeof node.modelMetadata.id !== 'undefined') { + saved.modelId = node.modelMetadata.id; + } console.log('[AssetMenu] save result:', saved); if (errors.length === 0 && this.syncAsset) {