Skip to content

Commit

Permalink
LF-4625 Refactor Ensemble Scientific portion of addSensors controller…
Browse files Browse the repository at this point in the history
… for readability

Remove reduce in favour of more readable array methods; encapsulate all three Ensemble methods into one function; define a constant for 'Ensemble Scientific'
  • Loading branch information
kathyavini committed Jan 23, 2025
1 parent 51850ce commit 95ac33c
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 63 deletions.
104 changes: 49 additions & 55 deletions packages/api/src/controllers/sensorController.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ import PartnerReadingTypeModel from '../models/PartnerReadingTypeModel.js';
import { transaction, Model } from 'objection';

import {
createOrganization,
registerOrganizationWebhook,
bulkSensorClaim,
ENSEMBLE_BRAND,
extractEsids,
registerFarmAndClaimSensors,
unclaimSensor,
ENSEMBLE_UNITS_MAPPING,
} from '../util/ensemble.js';
Expand Down Expand Up @@ -119,7 +119,7 @@ const sensorController = {
const { user_id } = req.auth;
try {
const { access_token } = await IntegratingPartnersModel.getAccessAndRefreshTokens(
'Ensemble Scientific',
ENSEMBLE_BRAND,
);

//TODO: LF-4443 - Sensor should not use User language (unrestricted string), accept as body param or farm level detail
Expand Down Expand Up @@ -173,65 +173,59 @@ const sensorController = {
},
);
} else {
const esids = data.reduce((previous, current) => {
if (current.brand === 'Ensemble Scientific' && current.external_id) {
previous.push(current.external_id);
}
return previous;
}, []);
// Extract Ensemble Scientific sensor IDs (esids)
const esids = extractEsids(data);

let success = [];
let already_owned = [];
let does_not_exist = [];
let occupied = [];
if (esids.length > 0) {
const organization = await createOrganization(farm_id, access_token);

// register webhook for sensor readings
await registerOrganizationWebhook(farm_id, organization.organization_uuid, access_token);

// Register sensors with Ensemble
({ success, already_owned, does_not_exist, occupied } = await bulkSensorClaim(
if (esids.length > 0) {
({ success, already_owned, does_not_exist, occupied } = await registerFarmAndClaimSensors(
farm_id,
access_token,
organization.organization_uuid,
esids,
));
}
// register organization

// Filter sensors by those successfully registered and those with errors
const { registeredSensors, errorSensors } = data.reduce(
(prev, curr, idx) => {
if (success?.includes(curr.external_id) || already_owned?.includes(curr.external_id)) {
prev.registeredSensors.push(curr);
} else if (curr.brand !== 'Ensemble Scientific') {
prev.registeredSensors.push(curr);
} else if (does_not_exist?.includes(curr.external_id)) {
prev.errorSensors.push({
row: idx + 2,
column: 'External_ID',
translation_key: sensorErrors.SENSOR_DOES_NOT_EXIST,
variables: { sensorId: curr.external_id },
});
} else if (occupied?.includes(curr.external_id)) {
prev.errorSensors.push({
row: idx + 2,
column: 'External_ID',
translation_key: sensorErrors.SENSOR_ALREADY_OCCUPIED,
variables: { sensorId: curr.external_id },
});
} else {
// we know that it is an ESID but for some reason it was not returned in the expected format from the API
prev.errorSensors.push({
row: idx + 2,
column: 'External_ID',
translation_key: sensorErrors.INTERNAL_ERROR,
variables: { sensorId: curr.external_id },
});
}
return prev;
},
{ registeredSensors: [], errorSensors: [] },
);

const registeredSensors = [];
const errorSensors = [];

// Iterate over each sensor in the data array
data.forEach((sensor, index) => {
if (sensor.brand !== ENSEMBLE_BRAND) {
// All non-ESCI sensors should be considered successfully registered
registeredSensors.push(sensor);
} else if (
success.includes(sensor.external_id) ||
already_owned.includes(sensor.external_id)
) {
registeredSensors.push(sensor);
} else if (does_not_exist.includes(sensor.external_id)) {
errorSensors.push({
row: index + 2,
column: 'External_ID',
translation_key: sensorErrors.SENSOR_DOES_NOT_EXIST,
variables: { sensorId: sensor.external_id },
});
} else if (occupied.includes(sensor.external_id)) {
errorSensors.push({
row: index + 2,
column: 'External_ID',
translation_key: sensorErrors.SENSOR_ALREADY_OCCUPIED,
variables: { sensorId: sensor.external_id },
});
} else {
// We know that it is an ESID but it was not returned in the expected format from the API
errorSensors.push({
row: index + 2,
column: 'External_ID',
translation_key: sensorErrors.INTERNAL_ERROR,
variables: { sensorId: sensor.external_id },
});
}
});

// Save sensors in database
const sensorLocations = [];
Expand Down Expand Up @@ -630,7 +624,7 @@ const sensorController = {

const user_id = req.auth.user_id;
const { access_token } = await IntegratingPartnersModel.getAccessAndRefreshTokens(
'Ensemble Scientific',
ENSEMBLE_BRAND,
);
let unclaimResponse;
if (partner_name != 'No Integrating Partner' && external_id != '') {
Expand Down
34 changes: 26 additions & 8 deletions packages/api/src/util/ensemble.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ const ENSEMBLE_UNITS_MAPPING = {
},
};

const ENSEMBLE_BRAND = 'Ensemble Scientific';

// Return Ensemble Scientific IDs (esids) from sensor data
const extractEsids = (data) =>
data
.filter((sensor) => sensor.brand === 'Ensemble Scientific' && sensor.external_id)
.map((sensor) => sensor.external_id);

// Function to encapsulate the logic for claiming sensors
async function registerFarmAndClaimSensors(farm_id, access_token, esids) {
// Register farm as an organization with Ensemble
const organization = await createOrganization(farm_id, access_token);

// Create a webhook for the organization
await registerOrganizationWebhook(farm_id, organization.organization_uuid, access_token);

// Register sensors with Ensemble and return Ensemble API results
return await bulkSensorClaim(access_token, organization.organization_uuid, esids);
}

/**
* Sends a request to the Ensemble API for an organization to claim sensors
* @param {String} accessToken - a JWT token for accessing the Ensemble API
Expand Down Expand Up @@ -250,12 +270,10 @@ function isAuthError(error) {
*/
async function refreshTokens() {
try {
const { refresh_token } = await IntegratingPartners.getAccessAndRefreshTokens(
'Ensemble Scientific',
);
const { refresh_token } = await IntegratingPartners.getAccessAndRefreshTokens(ENSEMBLE_BRAND);
const response = await axios.post(ensembleAPI + '/token/refresh/', { refresh: refresh_token });
await IntegratingPartners.patchAccessAndRefreshTokens(
'Ensemble Scientific',
ENSEMBLE_BRAND,
response.data?.access,
response.data?.access,
);
Expand All @@ -281,7 +299,7 @@ async function authenticateToGetTokens() {
const password = process.env.ENSEMBLE_PASSWORD;
const response = await axios.post(ensembleAPI + '/token/', { username, password });
await IntegratingPartners.patchAccessAndRefreshTokens(
'Ensemble Scientific',
ENSEMBLE_BRAND,
response.data?.access,
response.data?.access,
);
Expand Down Expand Up @@ -330,9 +348,9 @@ async function unclaimSensor(org_id, external_id, access_token) {
}

export {
bulkSensorClaim,
registerOrganizationWebhook,
createOrganization,
ENSEMBLE_BRAND,
extractEsids,
registerFarmAndClaimSensors,
unclaimSensor,
ENSEMBLE_UNITS_MAPPING,
};

0 comments on commit 95ac33c

Please sign in to comment.