From 2b57d2df56b5b1f1d94c8694721ad7ed2cb15eb3 Mon Sep 17 00:00:00 2001 From: Westech Admin Date: Tue, 19 May 2026 18:15:09 +0000 Subject: [PATCH] Add data migration script for Serial No grades MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Run after bench migrate. Maps cosmetic_grade C# values to new grade field: - C5-C9 → High - C4 → Med - C3 → Low - C0-C2, blank → Flagged Requires: bench migrate has already created the new fields. --- .../migrations/migrate_serial_grades.py | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 westech_r2/migrations/migrate_serial_grades.py diff --git a/westech_r2/migrations/migrate_serial_grades.py b/westech_r2/migrations/migrate_serial_grades.py new file mode 100644 index 0000000..a8ae778 --- /dev/null +++ b/westech_r2/migrations/migrate_serial_grades.py @@ -0,0 +1,79 @@ +""" +Data Migration: Populate new Serial No fields from existing data. + +Run this IMMEDIATELY after `bench migrate` on production. +Requires: all new fields already exist (grade, cpu_test, ram_test, etc.) + +Maps cosmetic_grade C# values → new grade field: + C5-C9 → High + C4 → Med + C3 → Low + C0-C2, blank, anything else → Flagged +""" + +import frappe +from frappe.utils import now + +def run(): + print(f"[{now()}] Starting Serial No grade migration...") + + serials = frappe.get_all("Serial No", + fields=["name", "cosmetic_grade", "grade", "pricing_status"], + limit_page_length=0 + ) + + stats = {"high": 0, "med": 0, "low": 0, "flagged": 0, "skipped": 0, "errors": 0} + + for i, s in enumerate(serials): + try: + cosmetic = (s.cosmetic_grade or "").strip().upper() + + # Map cosmetic_grade → new grade + if cosmetic in ("C5", "C6", "C7", "C8", "C9"): + new_grade = "High" + elif cosmetic == "C4": + new_grade = "Med" + elif cosmetic == "C3": + new_grade = "Low" + else: + new_grade = "Flagged" + + # Only update if grade is blank or old value + if s.grade and s.grade in ("High", "Med", "Low", "Flagged"): + stats["skipped"] += 1 + continue + + # Determine pricing_status + if new_grade == "Flagged": + pricing_status = "Flagged" + else: + pricing_status = "Needs Pricing" + + frappe.db.set_value("Serial No", s.name, { + "grade": new_grade, + "pricing_status": pricing_status + }) + + stats[new_grade.lower()] += 1 + + if (i + 1) % 1000 == 0: + frappe.db.commit() + print(f" Processed {i + 1}/{len(serials)}...") + + except Exception as e: + stats["errors"] += 1 + frappe.log_error(f"Migration error for {s.name}: {e}", "Serial Grade Migration") + + frappe.db.commit() + + print(f"\n[{now()}] Migration complete!") + print(f" Total Serial Nos: {len(serials)}") + print(f" High: {stats['high']}") + print(f" Med: {stats['med']}") + print(f" Low: {stats['low']}") + print(f" Flagged: {stats['flagged']}") + print(f" Skipped (already new grade): {stats['skipped']}") + print(f" Errors: {stats['errors']}") + +if __name__ == "__main__": + run()