DANGER: This script (
entropy/utils/migrate_existing_ids.py) performs destructive database operations. It renames the primary keys (namecolumn) of existing Customer and Supplier documents.
- BACKUP REQUIRED: ALWAYS take a full database backup before running this script on any environment.
- TEST THOROUGHLY: Execute this script on a recent copy of your production data (a staging environment) first. Verify the results carefully.
- EXCLUSIVE ACCESS: Ensure no users are actively creating or modifying Customer or Supplier records while the migration is in progress to avoid conflicts.
- IRREVERSIBLE (without backup): Renaming primary keys is complex. Reversing the process without restoring a backup is extremely difficult and error-prone.
This script is designed to update the IDs (name) of existing Customer and Supplier records to match the new custom naming format implemented by custom_naming.py ([NAME_PREFIX][COMPANY_ABBR][SEQ_NUM]). This ensures consistency between newly created records and historical data.
custom_naming.py: The helper functions (get_name_prefix,get_company_abbr, constants) from the finalizedcustom_naming.pyscript must be present and correctly imported by this migration script. The import path (from entropy.utils.custom_naming import ...) may need adjustment based on your app structure.- Database Backup: A verified, restorable database backup is essential before proceeding.
The script is executed via the bench execute command and operates in batches for safety and scalability.
The script uses argparse for configuration via command-line arguments passed within the bench execute call.
doctype(Required): Specifies whether to migrateCustomerorSupplier.--batch-size(Optional): Number of records processed per database transaction (default: 100). Smaller batches use less memory but might be slightly slower overall.--dry-run(Optional): Highly Recommended for testing. Simulates the entire process, including ID generation and link checking, without modifying the database. Logs actions that would be taken.--yes/-y(Optional): Skips the interactive confirmation prompt. Use with extreme caution only after thorough testing and backup verification.
- To handle potentially large numbers of Customers/Suppliers without overwhelming server memory, the script fetches records in batches (controlled by
--batch-size). - It processes each batch, updates links, renames documents, and then commits the changes before fetching the next batch.
- Migration-Specific Logic: This function calculates the next available ID for an existing record during migration. It does not use the atomic counter (
_get_next_series_number_atomic) fromcustom_naming.py, as that's designed for new concurrent creations. - Finding Max Existing: For a given
name_prefixandcompany_abbrcombination (e.g., "SPAABC"):- It queries the database for the highest existing ID that matches the pattern
PREFIX+ABBR+NUMBERS(e.g.,SPAABC123). It usesLIKEandREGEXPfor accuracy. - It caches the highest number found for each prefix within the script's run to avoid repeated database queries.
- It increments the highest found number to get the next sequence number for the migration.
- If no existing formatted ID is found for that prefix, it starts the sequence at 1.
- It queries the database for the highest existing ID that matches the pattern
- Generates ID: Constructs the new ID using the prefix, abbreviation, and the determined sequence number, applying the correct padding.
- Before attempting to generate a new ID, the script checks if the
old_namealready conforms to the expectedPREFIX+ABBR+SEQUENCENUMBERformat. - If it does, the record is skipped to avoid unnecessary processing and potential errors.
- Critical Step: This is arguably the most complex part of renaming. Before
frappe.rename_docis called, this function finds all references to theold_nameacross the entire database and updates them to thenew_name. - Comprehensive Check: It handles:
- Standard
Linkfields (in standard DocTypes and Custom Fields). Dynamic Linkfields (checking both the field holding the doctype name and the field holding the document name).
- Standard
- Error Handling: Logs errors if updating links in a specific table fails but continues the overall process.
- After links are updated (or identified in dry run), this function performs the actual rename of the document's primary key (
name) in its table (tabCustomerortabSupplier). - Uses
force=Trueandignore_permissions=Truewhich are often necessary for admin-run migrations but require caution.
- Individual Record Failures: If updating links or renaming fails for a single record, the error is logged, the
failed_countis incremented, and the script proceeds to the next record in the batch. This prevents one bad record from halting the entire migration. - Batch Commits: Database changes are committed periodically after each batch. This saves progress but means a failure mid-batch won't roll back previously committed batches.
- Critical Failures: If a rename fails after links were updated (in a live run), a critical log message is generated, as manual intervention might be needed for that specific record. A final
try...exceptblock attempts to roll back the current transaction if a catastrophic error occurs.
- Simulates ID generation.
- Logs which links would be updated.
- Logs which documents would be renamed.
- Does not execute
frappe.db.sql("UPDATE ...")orfrappe.rename_doc(...). - Essential for verifying the script's logic and identifying potential issues before modifying live data.
- BACKUP YOUR DATABASE. Verify the backup is complete and restorable.
- Test on Staging (Dry Run):
bench --site your-staging-site execute entropy.utils.migrate_existing_ids.run_migration --args='{"doctype":"Customer", "dry_run":true}' bench --site your-staging-site execute entropy.utils.migrate_existing_ids.run_migration --args='{"doctype":"Supplier", "dry_run":true}'
- Review
logs/migration.logcarefully for generated IDs, skipped records, potential link updates, and any errors.
- Review
- Test on Staging (Live Run): If the dry run looks good, perform a live run on staging:
bench --site your-staging-site execute entropy.utils.migrate_existing_ids.run_migration --args='{"doctype":"Customer"}' # Will prompt for confirmation bench --site your-staging-site execute entropy.utils.migrate_existing_ids.run_migration --args='{"doctype":"Supplier"}' # Will prompt for confirmation
- Thoroughly check sample Customer/Supplier records in the UI. Verify their new IDs. Check documents that link to them (e.g., Sales Orders, Purchase Orders, Journal Entries) to ensure the links were updated correctly.
- Schedule Production Run: Plan a maintenance window when user activity is minimal.
- Execute on Production (Live Run):
# Ensure you are targeting the correct site! bench --site your-production-site execute entropy.utils.migrate_existing_ids.run_migration --args='{"doctype":"Customer"}' # Will prompt bench --site your-production-site execute entropy.utils.migrate_existing_ids.run_migration --args='{"doctype":"Supplier"}' # Will prompt # OR, if you are absolutely certain after testing (use with caution): # bench --site your-production-site execute entropy.utils.migrate_existing_ids.run_migration --args='{"doctype":"Customer", "yes":true}'
- Monitor: Closely monitor the console output and
logs/migration.logduring execution. - Verify: After completion, perform spot checks on production data similar to the staging verification.
The script uses a dedicated Frappe logger named migration. Check the logs/migration.log file for detailed information about batches, skipped records, generated IDs, successful renames, link updates, and any errors encountered.
- Minor Errors: If only a few records fail, note the
old_namefrom the logs. Manual correction might be possible (e.g., manually renaming and checking links). - Major Errors: If significant issues occur, the safest approach is typically to restore the database backup taken before the migration attempt.