feat: Customer Interaction DocType for CRM contact logs from supplemental.xlsx

This commit is contained in:
Westech Admin
2026-05-23 07:38:41 +00:00
parent 313da27e56
commit 0997de940e
6 changed files with 280 additions and 0 deletions
@@ -0,0 +1,8 @@
// Copyright (c) 2026, Westech and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Customer Interaction", {
// refresh(frm) {
// },
// });
@@ -0,0 +1,147 @@
{
"actions": [],
"autoname": "autoincrement",
"creation": "2026-05-22 11:58:31.649154",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"customer",
"customer_number",
"contact_name",
"phone_1",
"phone_2",
"email_1",
"email_2",
"address",
"city",
"zip",
"hours",
"notes",
"red_r2",
"dnc",
"raw_name",
"raw_phone1",
"raw_phone2",
"raw_email"
],
"fields": [
{
"fieldname": "customer",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Customer",
"options": "Customer",
"reqd": 1
},
{
"fieldname": "customer_number",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Customer Number"
},
{
"fieldname": "contact_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Contact Name"
},
{
"fieldname": "phone_1",
"fieldtype": "Data",
"label": "Phone 1"
},
{
"fieldname": "phone_2",
"fieldtype": "Data",
"label": "Phone 2"
},
{
"fieldname": "email_1",
"fieldtype": "Data",
"label": "Email 1"
},
{
"fieldname": "email_2",
"fieldtype": "Data",
"label": "Email 2"
},
{
"fieldname": "address",
"fieldtype": "Text",
"label": "Address"
},
{
"fieldname": "city",
"fieldtype": "Data",
"label": "City"
},
{
"fieldname": "zip",
"fieldtype": "Data",
"label": "Zip"
},
{
"fieldname": "hours",
"fieldtype": "Data",
"label": "Hours"
},
{
"fieldname": "notes",
"fieldtype": "Text",
"label": "Notes"
},
{
"fieldname": "red_r2",
"fieldtype": "Data",
"in_standard_filter": 1,
"label": "Red R2"
},
{
"default": "0",
"fieldname": "dnc",
"fieldtype": "Check",
"label": "DNC"
},
{
"fieldname": "raw_name",
"fieldtype": "Text",
"label": "Raw Name"
},
{
"fieldname": "raw_phone1",
"fieldtype": "Data",
"label": "Raw Phone 1"
},
{
"fieldname": "raw_phone2",
"fieldtype": "Data",
"label": "Raw Phone 2"
},
{
"fieldname": "raw_email",
"fieldtype": "Data",
"label": "Raw Email"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2026-05-22 11:58:31.649154",
"modified_by": "Administrator",
"module": "Westech R2",
"name": "Customer Interaction",
"naming_rule": "Autoincrement",
"owner": "Administrator",
"permissions": [],
"row_format": "Dynamic",
"rows_threshold_for_grid_search": 20,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"title_field": "contact_name",
"track_changes": 1,
"track_seen": 1
}
@@ -0,0 +1,9 @@
# Copyright (c) 2026, Westech and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class CustomerInteraction(Document):
pass
@@ -0,0 +1,9 @@
# Copyright (c) 2026, Westech and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestCustomerInteraction(FrappeTestCase):
pass
+107
View File
@@ -0,0 +1,107 @@
import frappe
import csv
def create_customer_interaction_doctype():
"""Create Customer Interaction DocType if it doesn't exist"""
if frappe.db.exists("DocType", "Customer Interaction"):
print("Customer Interaction DocType already exists")
return
doc = frappe.get_doc({
"doctype": "DocType",
"module": "Westech R2",
"name": "Customer Interaction",
"title_field": "contact_name",
"autoname": "autoincrement",
"naming_rule": "Autoincrement",
"track_changes": 1,
"track_seen": 1,
"fields": [
{"label": "Customer", "fieldname": "customer", "fieldtype": "Link", "options": "Customer", "in_list_view": 1, "reqd": 1, "in_standard_filter": 1},
{"label": "Customer Number", "fieldname": "customer_number", "fieldtype": "Data", "in_list_view": 1, "in_standard_filter": 1},
{"label": "Contact Name", "fieldname": "contact_name", "fieldtype": "Data", "in_list_view": 1},
{"label": "Phone 1", "fieldname": "phone_1", "fieldtype": "Data"},
{"label": "Phone 2", "fieldname": "phone_2", "fieldtype": "Data"},
{"label": "Email 1", "fieldname": "email_1", "fieldtype": "Data"},
{"label": "Email 2", "fieldname": "email_2", "fieldtype": "Data"},
{"label": "Address", "fieldname": "address", "fieldtype": "Text"},
{"label": "City", "fieldname": "city", "fieldtype": "Data"},
{"label": "Zip", "fieldname": "zip", "fieldtype": "Data"},
{"label": "Hours", "fieldname": "hours", "fieldtype": "Data"},
{"label": "Notes", "fieldname": "notes", "fieldtype": "Text"},
{"label": "Red R2", "fieldname": "red_r2", "fieldtype": "Data", "in_standard_filter": 1},
{"label": "DNC", "fieldname": "dnc", "fieldtype": "Check"},
{"label": "Raw Name", "fieldname": "raw_name", "fieldtype": "Text"},
{"label": "Raw Phone 1", "fieldname": "raw_phone1", "fieldtype": "Data"},
{"label": "Raw Phone 2", "fieldname": "raw_phone2", "fieldtype": "Data"},
{"label": "Raw Email", "fieldname": "raw_email", "fieldtype": "Data"},
]
})
doc.insert()
frappe.db.commit()
print(f"Created Customer Interaction DocType")
def import_contacts(csv_path):
"""Import contacts from CSV file"""
count = 0
errors = 0
with open(csv_path, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
try:
# Find customer by customer_number
customer = frappe.db.get_value("Customer", {"customer_number": row['customer_number']}, "name")
if not customer:
# Customer doesn't exist yet, skip or create placeholder
errors += 1
continue
interaction = frappe.get_doc({
"doctype": "Customer Interaction",
"customer": customer,
"customer_number": row['customer_number'],
"contact_name": row.get('contact_name', ''),
"phone_1": row.get('phone_1', ''),
"phone_2": row.get('phone_2', ''),
"email_1": row.get('email_1', ''),
"email_2": row.get('email_2', ''),
"address": row.get('address', ''),
"city": row.get('city', ''),
"zip": row.get('zip', ''),
"hours": row.get('hours', ''),
"notes": row.get('notes', ''),
"red_r2": row.get('red_r2', ''),
"dnc": 1 if row.get('dnc', '').strip() else 0,
"raw_name": row.get('raw_name', ''),
"raw_phone1": row.get('raw_phone1', ''),
"raw_phone2": row.get('raw_phone2', ''),
"raw_email": row.get('raw_email', '')
})
interaction.insert()
count += 1
if count % 500 == 0:
frappe.db.commit()
print(f"Imported {count} interactions...")
except Exception as e:
errors += 1
if errors < 10:
print(f"Error importing row {count}: {e}")
frappe.db.commit()
print(f"Import complete: {count} interactions imported, {errors} errors")
if __name__ == "__main__":
frappe.init(site="erpnext.local")
frappe.connect()
try:
create_customer_interaction_doctype()
import_contacts("/home/frappe/erpnext-bench/apps/westech_r2/westech_r2/crm_contacts_clean.csv")
finally:
frappe.destroy()