import frappe import json from datetime import datetime def parse_date(val): """Parse various date formats from the CRM spreadsheet""" if not val: return None if isinstance(val, datetime): return val.date() if isinstance(val, str): val = val.strip() if not val or val.lower() in ['nan', 'none', 'null']: return None # Handle format like "9/8/0206" -> year 2006 if '/' in val: parts = val.split('/') if len(parts) == 3: month, day, year = parts year = year.strip() # Fix 4-digit years starting with 02xx -> 20xx if len(year) == 4 and year.startswith('02'): year = '20' + year[2:] # Fix 2-digit years elif len(year) == 2: year_int = int(year) if year_int < 50: year = '20' + year else: year = '19' + year try: return datetime(int(year), int(month), int(day)).date() except: return None return None def run(): print("=== CRM Import Fix & Continue ===") # Load parsed data with open("/tmp/crm_records.json") as f: records = json.load(f) print(f"Total parsed records: {len(records)}") # Get already imported records existing = frappe.get_all("Customer Record", fields=["name"], pluck="name") existing_set = set(existing) print(f"Already imported: {len(existing_set)}") # Get supplier names supplier_names = set(frappe.get_all("Supplier", fields=["name"], pluck="name")) # Fix existing bad records print("\nFixing existing records with bad dates...") fixed = 0 for rec_num in existing_set: doc = frappe.get_doc("Customer Record", rec_num) changed = False # Check and fix dates date_fields = ['date_created', 'contacted_date', 'follow_up_date', 'last_pu_date'] for df in date_fields: val = doc.get(df) if val and isinstance(val, str): parsed = parse_date(val) if parsed: doc.set(df, parsed) changed = True else: # Can't parse, clear it doc.set(df, None) changed = True if changed: doc.save(ignore_permissions=True) fixed += 1 if fixed: frappe.db.commit() print(f"Fixed {fixed} existing records") # Import remaining records remaining = [r for r in records if r["record_number"] not in existing_set] print(f"\nImporting remaining {len(remaining)} records...") created = 0 errors = [] for rec in remaining: try: doc = frappe.new_doc("Customer Record") doc.record_number = rec["record_number"] doc.company_name = rec.get("company_name") or "" # Match supplier if rec["record_number"] in supplier_names: doc.supplier = rec["record_number"] doc.customer_number = rec["record_number"] doc.contact_persons = "\n".join(rec.get("contact_persons", [])) doc.email_address = "\n".join(rec.get("emails", [])) doc.phone_numbers = "\n".join(rec.get("phone_numbers", [])) doc.customer_address = rec.get("address") or "" doc.city = rec.get("city") or "" doc.state = rec.get("state") or "" doc.zip = str(rec.get("zip") or "") # Parse dates properly doc.date_created = parse_date(rec.get("date_created")) doc.contacted_date = parse_date(rec.get("contacted_date")) doc.follow_up_date = parse_date(rec.get("follow_up_date")) doc.last_pu_date = parse_date(rec.get("last_pu_date")) doc.notes = rec.get("notes") or "" doc.comments = rec.get("comments") or "" doc.hours_operation = rec.get("hours_operation") or "" doc.save(ignore_permissions=True) created += 1 if created % 500 == 0: print(f" ... {created} remaining records imported") frappe.db.commit() except Exception as e: errors.append(f"{rec['record_number']}: {str(e)}") if len(errors) > 20: print(f"Too many errors ({len(errors)}), stopping. Last: {e}") break frappe.db.commit() print(f"\nImport complete: {created} additional records created") if errors: print(f"Errors ({len(errors)}):") for e in errors[:10]: print(f" {e}") total = frappe.db.count("Customer Record") print(f"Total Customer Records now: {total}") return {"status": "ok", "created": created, "errors": len(errors), "total": total}