diff --git a/api/src/paths/batch/{id}/execute.ts b/api/src/paths/batch/{id}/execute.ts index 52aa56407..d5db361ea 100644 --- a/api/src/paths/batch/{id}/execute.ts +++ b/api/src/paths/batch/{id}/execute.ts @@ -149,7 +149,7 @@ function execBatch(): RequestHandler { } catch (error) { defaultLog.error(error); return res.status(400).json({ - message: 'Batch update exec failed', + message: 'Batch update exec failed, error: ' + error.message, request: req.body, count: 1, namespace: 'batch', diff --git a/api/src/utils/batch/execution.ts b/api/src/utils/batch/execution.ts index f0f4d27c3..03bed8201 100644 --- a/api/src/utils/batch/execution.ts +++ b/api/src/utils/batch/execution.ts @@ -101,81 +101,91 @@ export const BatchExecutionService = { if (statusQueryResult.rowCount !== 1) { throw new Error('Batch not in executable status'); } - for (const [index, row] of validatedBatchData.rows.entries()) { - let errorRow = false; - if (row.rowValidationResult.find((vr) => !vr.valid)) { - errorRow = true; - } else { - Object.values(row.data).forEach((propertyValue: any) => { - if ( - (propertyValue.validationMessages.length > 0 && - propertyValue.validationMessages.find((vm) => vm.severity === 'error')) || - row.RowValidationResult - ) { - errorRow = true; - } - }); - } - if (errorRow && errorRowsBehaviour === 'Skip') continue; - - const { id: activityId, shortId, payload, geog } = _mapToDBObject( - row, - desiredFinalStatus, - template.type, - template.subtype, - userInfo - ); - - let guid = null; - if (userInfo?.idir_userid !== null) { - guid = userInfo?.idir_userid.toLowerCase() + '@idir'; - } else if (userInfo?.bceid_userid !== null) { - guid = userInfo?.bceid_userid.toLowerCase() + '@bceid-business'; - } - const qc = { - text: `INSERT INTO activity_incoming_data (activity_id, short_id, activity_payload, batch_id, activity_type, + + await dbConnection.query('BEGIN;'); + + try { + for (const [index, row] of validatedBatchData.rows.entries()) { + let errorRow = false; + if (row.rowValidationResult.find((vr) => !vr.valid)) { + errorRow = true; + } else { + Object.values(row.data).forEach((propertyValue: any) => { + if ( + (propertyValue.validationMessages.length > 0 && + propertyValue.validationMessages.find((vm) => vm.severity === 'error')) || + row.RowValidationResult + ) { + errorRow = true; + } + }); + } + if (errorRow && errorRowsBehaviour === 'Skip') continue; + + const { id: activityId, shortId, payload, geog } = _mapToDBObject( + row, + desiredFinalStatus, + template.type, + template.subtype, + userInfo + ); + + let guid = null; + if (userInfo?.idir_userid !== null) { + guid = userInfo?.idir_userid.toLowerCase() + '@idir'; + } else if (userInfo?.bceid_userid !== null) { + guid = userInfo?.bceid_userid.toLowerCase() + '@bceid-business'; + } + const qc = { + text: `INSERT INTO activity_incoming_data (activity_id, short_id, activity_payload, batch_id, activity_type, activity_subtype, form_status, created_by, updated_by, created_by_with_guid, updated_by_with_guid, geog, row_number, species_positive, species_negative, species_treated) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)`, - values: [ - activityId, - shortId, - payload, - id, - template.type, - template.subtype, - errorRow ? errorRowsBehaviour : desiredFinalStatus, - userInfo?.preferred_username, - userInfo?.preferred_username, - guid, - guid, - geog, - index, - JSON.stringify(payload['species_positive']), - JSON.stringify(payload['species_negative']), - JSON.stringify(payload['species_treated']) - ] - }; - - defaultLog.debug({ - message: 'executing insert for batch', - params: { - qc - } - }); + values: [ + activityId, + shortId, + payload, + id, + template.type, + template.subtype, + errorRow ? errorRowsBehaviour : desiredFinalStatus, + userInfo?.preferred_username, + userInfo?.preferred_username, + guid, + guid, + geog, + index, + JSON.stringify(payload['species_positive']), + JSON.stringify(payload['species_negative']), + JSON.stringify(payload['species_treated']) + ] + }; - try { - await dbConnection.query(qc); - } catch (e) { defaultLog.debug({ - message: 'error executing insert for batch error->' + JSON.stringify(e) + message: 'executing insert for batch', + params: { + qc + } }); - throw e; + + try { + await dbConnection.query(qc); + } catch (e) { + defaultLog.debug({ + message: 'error executing insert for batch error->' + JSON.stringify(e) + }); + throw e; + } } + } catch (e) { + await dbConnection.query('ROLLBACK;'); + throw e; } + await dbConnection.query('COMMIT;'); + await dbConnection.query({ text: `UPDATE batch_uploads diff --git a/app/src/components/batch-upload/BatchDetail.tsx b/app/src/components/batch-upload/BatchDetail.tsx index 35aef51fc..58f2ab46e 100644 --- a/app/src/components/batch-upload/BatchDetail.tsx +++ b/app/src/components/batch-upload/BatchDetail.tsx @@ -152,7 +152,7 @@ const BatchGlobalValidationErrors = ({ batch }) => { }; const BatchDetail = ({ id }) => { - const { working, error, item: batch } = useSelector(selectBatch); + const { working, error, item: batch, errorMessage } = useSelector(selectBatch); const dispatch = useDispatch(); useEffect(() => { @@ -164,7 +164,7 @@ const BatchDetail = ({ id }) => { return ; } if (error) { - return ; + return <>{ errorMessage }; } if (batch == null) { return No batch found; diff --git a/app/src/state/reducers/batch.ts b/app/src/state/reducers/batch.ts index bf3fd3e3a..faf47e0f8 100644 --- a/app/src/state/reducers/batch.ts +++ b/app/src/state/reducers/batch.ts @@ -158,6 +158,7 @@ function createBatchReducer() { ...state, working: false, error: true, + errorMessage: `Could not execute batch ${JSON.stringify(action.payload?.message, null, 2)}`, item: null }; case BATCH_EXECUTE_REQUEST: diff --git a/app/src/state/sagas/batch.ts b/app/src/state/sagas/batch.ts index 6d6527ebe..2849386c0 100644 --- a/app/src/state/sagas/batch.ts +++ b/app/src/state/sagas/batch.ts @@ -13,7 +13,7 @@ import { BATCH_TEMPLATE_DOWNLOAD_REQUEST, BATCH_TEMPLATE_DOWNLOAD_SUCCESS, BATCH_TEMPLATE_LIST_REQUEST, - BATCH_TEMPLATE_LIST_SUCCESS, BATCH_UPDATE_REQUEST, BATCH_UPDATE_SUCCESS, BATCH_DELETE_ERROR + BATCH_TEMPLATE_LIST_SUCCESS, BATCH_UPDATE_REQUEST, BATCH_UPDATE_SUCCESS, BATCH_DELETE_ERROR, BATCH_EXECUTE_ERROR } from '../actions'; import { Http } from '@capacitor-community/http'; import { actions } from 'components/map/LayerPicker/JSON/actions'; @@ -189,7 +189,7 @@ function* executeBatch(action) { const { requestHeaders } = yield select(selectAuth); const { id } = action.payload; - const { data } = yield Http.request({ + const {data, status } = yield Http.request({ method: 'POST', url: configuration.API_BASE + `/api/batch/${id}/execute`, headers: { @@ -202,9 +202,16 @@ function* executeBatch(action) { } }); - yield put({ type: BATCH_EXECUTE_SUCCESS, payload: data }); - yield put({ type: BATCH_RETRIEVE_REQUEST, payload: { id } }); + if(!(status < 200 || status > 299)) + { + yield put({ type: BATCH_EXECUTE_SUCCESS, payload: data }); + yield put({ type: BATCH_RETRIEVE_REQUEST, payload: { id } }); + } + else + { + yield put({ type: BATCH_EXECUTE_ERROR, payload: data }) + } }; function* batchSaga() {