Standard Operating Procedure (SOP): TMS Organization Data Deletion
1. Purpose and Scope
This document outlines the standard procedure for safely extracting, backing up, and permanently deleting all data associated with a specific organization from the TMS databases (tms_booking, tms_drivers, tms_fleet, tms_planner, tms_reports, and tms_resource).
2. Prerequisites
-
Target Identification: The exact UUID of the organization to be deleted (e.g.,
org_uuid = 'b067f771-edf6-47fa-b58d-e2c6fcebd54b'). -
Database Access: Read/Write access to the
nightly(staging) andstable(production) databases. -
Personnel:
-
Data Engineer / DBA: Executes the scripts.
-
QA / Reviewer: Validates system stability post-deletion (e.g., Sanna Koskiranta-Nurmi).
-
Database Architect: Approves cascading impact (e.g., Koste Sibinovski).
3. Phase 1: Data Discovery and Extraction (SELECT)
Before any data is deleted, it must be located and backed up for compliance and review.
-
Formulate SELECT Queries: Write
SELECTstatements for every table across all microservice databases (booking,drivers,fleet,planner,reports,resource) that contain anorg_uuidor anorg_index. -
Join Linked Tables: For tables that do not have a direct organization UUID, use
JOINstatements to link back to the core table that holds the organization reference (e.g., joiningbooking_conversationtobookingtoorganization). -
Execute and Export: Run the queries against the database and export the results to standard data files (e.g., CSV).
-
Record Row Counts: Document the exact number of rows returned by each
SELECTquery. This is a critical metric for Phase 4.
4. Phase 2: Backup and Stakeholder Review
-
Secure Storage: Upload all exported data files to the designated secure Google Drive folder.
-
Stakeholder Handoff: Share the folder with the designated QA/Reviewer (Sanna) for a final review of the data slated for permanent deletion.
-
Wait for Sign-off: Do not proceed to deletion until the reviewer confirms the data is correct and safe to remove.
5. Phase 3: Query Conversion and Impact Analysis
-
Convert to DELETE: Rewrite all verified
SELECTqueries intoDELETEqueries. -
Database Architecture Review:
-
Submit the
DELETEqueries to the Database Architect (Koste) for inspection. -
Goal: Verify cascading deletion impacts. Determine if deleting a parent row will automatically drop child rows (CASCADE), or if child rows need to be explicitly deleted first to avoid database constraint errors or orphaned records.
-
Schema Verification: Clarify any ambiguous foreign keys during this step (e.g., confirming if
user_indexmaps exactly tocustomer_indexin the current schema).
6. Phase 4: Staging / Nightly Execution
All deletions must be tested in a non-production environment first.
-
Execute Deletions: Run the approved
DELETEqueries in thenightlyenvironment. -
Compare Row Counts: Ensure the number of deleted rows perfectly matches the number of rows recorded during the
SELECTphase. -
QA Regression Testing: Notify QA (Sanna) to test the application in the
nightlyenvironment. The goal is to ensure the UI, related microservices, and general application stability have not been broken by the missing data or cascading effects.
7. Phase 5: Production / Stable Execution
Proceed only after successful QA sign-off from the nightly environment.
-
Final Verification: Ensure no new data has been written for the organization since the initial extraction.
-
Execute Deletions: Run the
DELETEqueries against thestabledatabase, strictly following the execution order mandated by the DB Architect to prevent foreign key constraint violations. -
Post-Execution Audit: Re-run the initial
SELECTqueries. They should all return0rows. -
Final Confirmation: Notify the team that the organization data has been permanently purged from production.
To verify how user_index is mapped, you can query the database's information_schema.
These queries will show you exactly which table and column user_index points to, confirming if it maps to customer_index or the customer table.
PostgreSQL requires joining three different tables in the information_schema to get the full picture of a foreign key relationship.
SQL
SELECT
tc.table_name AS source_table,
kcu.column_name AS source_column,
ccu.table_name AS referenced_table,
ccu.column_name AS referenced_column,
tc.constraint_name
FROM
information_schema.table_constraints AS tc
JOIN
information_schema.key_column_usage AS kcu
ON tc.constraint_name = kcu.constraint_name
AND tc.table_schema = kcu.table_schema
JOIN
information_schema.constraint_column_usage AS ccu
ON ccu.constraint_name = tc.constraint_name
AND ccu.table_schema = tc.table_schema
WHERE
tc.constraint_type = 'FOREIGN KEY'
AND kcu.column_name = 'user_index';