diff --git a/cypress/e2e/1_feature_tests/5_3_Manage_Beneficiaries.js b/cypress/e2e/1_feature_tests/5_3_Manage_Beneficiaries.js index 3b296964..cc0cbe41 100644 --- a/cypress/e2e/1_feature_tests/5_3_Manage_Beneficiaries.js +++ b/cypress/e2e/1_feature_tests/5_3_Manage_Beneficiaries.js @@ -253,7 +253,15 @@ describe('Manage beneficiaries', () => { clickMergeButton(); verifyBeneficiaryRowLevel(TEST_LASTNAME1,0); verifyBeneficiaryRowLevel(TEST_LASTNAME2,1); - + + // Verify history logs for merge operation + cy.getBeneficiaryIdFromRow(TEST_LASTNAME1).then(id1 => { + cy.checkHistoryLog('people', id1, 'merged to family'); + }); + cy.getBeneficiaryIdFromRow(TEST_LASTNAME2).then(id2 => { + cy.checkHistoryLog('people', id2, 'merged to family'); + }); + //cleanup fullDeleteOfMergedUsers(); }); @@ -266,6 +274,12 @@ describe('Manage beneficiaries', () => { clickDetachButton(); verifyBeneficiaryRowLevel(TEST_LASTNAME1,0); verifyBeneficiaryRowLevel(TEST_LASTNAME2,0); + + // Verify history log for detach operation + cy.getBeneficiaryIdFromRow(TEST_LASTNAME2).then(id2 => { + cy.checkHistoryLog('people', id2, 'detached from family'); + }); + //cleanup fullDeleteTestedBeneficiaries([TEST_FIRSTNAME1,TEST_FIRSTNAME2]); }); diff --git a/cypress/support/database.js b/cypress/support/database.js index 5dd5b1b4..9ce68c68 100644 --- a/cypress/support/database.js +++ b/cypress/support/database.js @@ -27,3 +27,29 @@ Cypress.Commands.add("testauth0user", (email) => { expect(response.body).to.contain("true"); }); }); + +Cypress.Commands.add("checkHistoryLog", (tablename, recordId, expectedChange) => { + cy.request({ + method: "POST", + url: "/ajax.php?file=testhistorycheck", + body: { + tablename: tablename, + record_id: recordId, + expected_change: expectedChange + }, + form: true + }).then(response => { + expect(response.status).to.eq(200); + const body = typeof response.body === 'string' ? JSON.parse(response.body) : response.body; + expect(body.found).to.eq(true); + expect(body.count).to.be.greaterThan(0); + }); +}); + +Cypress.Commands.add("getBeneficiaryIdFromRow", (lastname) => { + return cy.getRowWithText(lastname).then($row => { + const id = $row.closest('tr').attr('data-id'); + expect(id).to.not.be.undefined; + return parseInt(id); + }); +}); diff --git a/include/people.php b/include/people.php index 020b267b..0f0c8320 100644 --- a/include/people.php +++ b/include/people.php @@ -439,6 +439,7 @@ function () use ($cmsmain, $data) { } } }); + simpleBulkSaveChangeHistory('people', $ids, 'merged to family (head: '.$oldest.')'); $success = true; $message = 'The merge has be successfully applied'; $redirect = true; @@ -464,6 +465,7 @@ function () use ($cmsmain, $data) { db_query('UPDATE people SET parent_id = NULL WHERE id = :id', ['id' => $id]); } }); + simpleBulkSaveChangeHistory('people', $ids, 'detached from family'); $redirect = true; $success = true; $message = ($success) ? 'Selected people have been detached' : 'Something went wrong'; @@ -482,7 +484,30 @@ function () use ($cmsmain, $data) { $ids = json_decode((string) $_POST['ids']); // list($success, $message, $redirect, $aftermove) = listMove($table, $ids, true, 'correctdrops'); // Refactored list move method to use a transaction block and bulk insert for the correctdrops method - [$success, $message, $redirect, $aftermove] = listBulkMove($table, $ids, true, 'bulkcorrectdrops', true); + [$success, $message, $redirect, $aftermove, $parentChanges] = listBulkMove($table, $ids, true, 'bulkcorrectdrops', true); + + // Log history for drag & drop family operations + if (!empty($parentChanges)) { + $addedToFamily = []; + $removedFromFamily = []; + + foreach ($parentChanges as $change) { + if (is_null($change['old_parent_id']) && !is_null($change['new_parent_id'])) { + // Added to family + $addedToFamily[] = $change['id']; + } elseif (!is_null($change['old_parent_id']) && is_null($change['new_parent_id'])) { + // Removed from family + $removedFromFamily[] = $change['id']; + } + } + + if (!empty($addedToFamily)) { + simpleBulkSaveChangeHistory('people', $addedToFamily, 'added to family via drag & drop'); + } + if (!empty($removedFromFamily)) { + simpleBulkSaveChangeHistory('people', $removedFromFamily, 'removed from family via drag & drop'); + } + } break; diff --git a/library/ajax/testhistorycheck.php b/library/ajax/testhistorycheck.php new file mode 100644 index 00000000..8dbc6f28 --- /dev/null +++ b/library/ajax/testhistorycheck.php @@ -0,0 +1,36 @@ + 'No permission']); +} else { + $recordId = $_POST['record_id']; + $tablename = $_POST['tablename']; + $expectedChange = $_POST['expected_change']; + + // Query history table for matching record + $historyEntries = db_array( + 'SELECT * FROM history WHERE tablename = :tablename AND record_id = :record_id AND changes LIKE :changes ORDER BY changedate DESC', + [ + 'tablename' => $tablename, + 'record_id' => $recordId, + 'changes' => '%'.$expectedChange.'%', + ] + ); + + if (count($historyEntries) > 0) { + echo json_encode(['found' => true, 'count' => count($historyEntries), 'entries' => $historyEntries]); + } else { + echo json_encode(['found' => false, 'count' => 0]); + } +} diff --git a/library/lib/list.php b/library/lib/list.php index 1bb50ebb..90a6df57 100644 --- a/library/lib/list.php +++ b/library/lib/list.php @@ -55,7 +55,8 @@ function listBulkMove($table, $ids, $regardparent = true, $hook = '', $updatetra $i = 1; $return = ''; - $hookIds = db_transaction(function () use ($ids, $hasParent, $table, $hook, $i, $updatetransactions) { + $parentChanges = []; + $hookIds = db_transaction(function () use ($ids, $hasParent, $table, $hook, $i, $updatetransactions, &$parentChanges) { $hookIds = []; $seq = []; foreach ($ids as $line) { @@ -72,6 +73,8 @@ function listBulkMove($table, $ids, $regardparent = true, $hook = '', $updatetra if ($updatetransactions && null != $new_parent_id) { db_query('UPDATE transactions SET people_id = :parent_id WHERE people_id = :id', ['parent_id' => $new_parent_id, 'id' => $id]); } + // Track parent_id changes for history logging + $parentChanges[] = ['id' => $id, 'old_parent_id' => $old_parent_id, 'new_parent_id' => $new_parent_id]; } } @@ -88,7 +91,7 @@ function listBulkMove($table, $ids, $regardparent = true, $hook = '', $updatetra $aftermove = $hook($hookIds); } - return [true, $return, false, $aftermove]; + return [true, $return, false, $aftermove, $parentChanges]; } function listRealDelete($table, $ids, $uri = false)