updates
This commit is contained in:
@@ -1,3 +1,191 @@
|
||||
export function getAssetVariables() {
|
||||
const http = require('node:http');
|
||||
const https = require('node:https');
|
||||
const { URL } = require('node:url');
|
||||
const { assetCategoryManager } = require('../../datasets/assetData');
|
||||
|
||||
}
|
||||
function toNumber(value, fallback = 1) {
|
||||
const result = Number(value);
|
||||
return Number.isFinite(result) && result > 0 ? result : fallback;
|
||||
}
|
||||
|
||||
function toArray(value = []) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.filter((item) => typeof item !== 'undefined' && item !== null);
|
||||
}
|
||||
if (typeof value === 'string' && value.trim()) {
|
||||
return [value.trim()];
|
||||
}
|
||||
if (typeof value === 'number') {
|
||||
return [value];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function findModelMetadata(selection = {}) {
|
||||
if (!selection) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const categoryKey = selection.softwareType || 'measurement';
|
||||
if (!assetCategoryManager.hasCategory(categoryKey)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const suppliers = assetCategoryManager.getCategory(categoryKey).suppliers || [];
|
||||
const supplierMatch = (entry, value) => {
|
||||
if (!entry || !value) return false;
|
||||
const key = value.toString().toLowerCase();
|
||||
return (
|
||||
(entry.id && entry.id.toLowerCase() === key) ||
|
||||
(entry.name && entry.name.toLowerCase() === key)
|
||||
);
|
||||
};
|
||||
|
||||
const supplier = suppliers.find((item) => supplierMatch(item, selection.supplier));
|
||||
const types = supplier?.types || [];
|
||||
const type = types.find((item) => supplierMatch(item, selection.assetType));
|
||||
const models = type?.models || [];
|
||||
const model = models.find((item) => supplierMatch(item, selection.model));
|
||||
|
||||
return model || null;
|
||||
}
|
||||
|
||||
function buildAssetPayload({ assetSelection = {}, registrationDefaults = {} }) {
|
||||
const defaults = {
|
||||
profileId: 1,
|
||||
locationId: 1,
|
||||
processId: 1,
|
||||
status: 'actief',
|
||||
childAssets: [],
|
||||
...registrationDefaults
|
||||
};
|
||||
|
||||
const metadata = assetSelection.modelMetadata || findModelMetadata(assetSelection) || {};
|
||||
const rawName = assetSelection.assetName || assetSelection.name || assetSelection.assetType || assetSelection.model;
|
||||
const assetName = (rawName || 'Measurement asset').toString();
|
||||
const assetDescription = (assetSelection.assetDescription || assetSelection.description || assetName).toString();
|
||||
|
||||
const payload = {
|
||||
profile_id: toNumber(defaults.profileId, 1),
|
||||
location_id: toNumber(defaults.locationId, 1),
|
||||
process_id: toNumber(defaults.processId, 1),
|
||||
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,
|
||||
child_assets: toArray(defaults.childAssets)
|
||||
};
|
||||
|
||||
const tagNumber = typeof assetSelection.tagNumber === 'string' && assetSelection.tagNumber.trim()
|
||||
? assetSelection.tagNumber.trim()
|
||||
: null;
|
||||
|
||||
return {
|
||||
payload,
|
||||
tagNumber,
|
||||
isUpdate: Boolean(tagNumber)
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeHeaders(headers = {}, body = '') {
|
||||
const normalized = { ...headers };
|
||||
if (!Object.prototype.hasOwnProperty.call(normalized, 'Content-Length')) {
|
||||
normalized['Content-Length'] = Buffer.byteLength(body);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function prepareUrl(baseUrl = '', path = '') {
|
||||
const trimmedBase = (baseUrl || '').replace(/\/+$/g, '').replace(/\\/g, '/');
|
||||
const trimmedPath = path.startsWith('/') ? path : `/${path}`;
|
||||
if (!trimmedBase) {
|
||||
return trimmedPath;
|
||||
}
|
||||
return `${trimmedBase}${trimmedPath}`;
|
||||
}
|
||||
|
||||
function sendHttpRequest(url, method, headers = {}, body = '') {
|
||||
const parsedUrl = new URL(url, 'http://localhost');
|
||||
const agent = parsedUrl.protocol === 'https:' ? https : http;
|
||||
const requestOptions = {
|
||||
method,
|
||||
hostname: parsedUrl.hostname,
|
||||
port: parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80),
|
||||
path: `${parsedUrl.pathname}${parsedUrl.search}`,
|
||||
headers: normalizeHeaders(headers, body)
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = agent.request(requestOptions, (res) => {
|
||||
let raw = '';
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', (chunk) => { raw += chunk; });
|
||||
res.on('end', () => resolve({ status: res.statusCode, body: raw }));
|
||||
});
|
||||
|
||||
req.on('error', reject);
|
||||
if (body) {
|
||||
req.write(body);
|
||||
}
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
function parseApiResponse(raw, status) {
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
return {
|
||||
success: parsed.success === true,
|
||||
data: parsed.data || null,
|
||||
message: parsed.message || (status >= 400 ? `HTTP ${status}` : 'Result returned')
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
data: raw,
|
||||
message: `Unable to decode asset API response: ${error.message}`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function syncAsset({ assetSelection = {}, registrationDefaults = {}, apiConfig = {}, nodeContext = {} }) {
|
||||
const { payload, tagNumber, isUpdate } = buildAssetPayload({ assetSelection, registrationDefaults });
|
||||
if (!apiConfig || !apiConfig.baseUrl) {
|
||||
const message = 'Asset API configuration is missing';
|
||||
console.warn('[assetUtils] ' + message, { nodeContext });
|
||||
return { success: false, data: null, message };
|
||||
}
|
||||
|
||||
const path = isUpdate && tagNumber && typeof apiConfig.updatePath === 'function'
|
||||
? apiConfig.updatePath(tagNumber)
|
||||
: apiConfig.registerPath;
|
||||
const url = prepareUrl(apiConfig.baseUrl, path);
|
||||
const method = isUpdate ? 'PUT' : 'POST';
|
||||
const headers = apiConfig.headers || {};
|
||||
|
||||
console.info('[assetUtils] Sending asset update', { nodeContext, method, url });
|
||||
|
||||
try {
|
||||
const response = await sendHttpRequest(url, method, headers, JSON.stringify(payload));
|
||||
const parsed = parseApiResponse(response.body, response.status);
|
||||
return {
|
||||
success: parsed.success,
|
||||
data: parsed.data,
|
||||
message: parsed.message
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('[assetUtils] Asset API request failed', error, { nodeContext });
|
||||
return {
|
||||
success: false,
|
||||
data: null,
|
||||
message: `Asset API request error: ${error.message}`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
syncAsset,
|
||||
buildAssetPayload,
|
||||
findModelMetadata
|
||||
};
|
||||
Reference in New Issue
Block a user