feat: CRM integration - customer intake, service invoice generation, COR print format\n\n- Added customer-intake page (search/create customers, create pallets)\n- Added whitelisted generate_service_invoice() API for native Sales Invoice creation\n- Added COR logo image asset\n- Removed stale fixtures/doctype.json (was causing bench migrate failures)
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
@frappe.whitelist()
|
||||
def search_customers(q=""):
|
||||
if not q or len(q) < 2:
|
||||
return []
|
||||
q = q.strip().lower()
|
||||
customers = frappe.db.sql("""
|
||||
SELECT c.name, c.customer_name, c.customer_number, c.phone, c.email_id,
|
||||
a.address_line1, a.city, a.state, a.pincode
|
||||
FROM tabCustomer c
|
||||
LEFT JOIN tabDynamic Link dl ON dl.link_doctype = 'Customer' AND dl.link_name = c.name AND dl.parenttype = 'Address'
|
||||
LEFT JOIN tabAddress a ON a.name = dl.parent
|
||||
WHERE LOWER(c.customer_name) LIKE %s OR LOWER(c.customer_number) LIKE %s OR LOWER(c.phone) LIKE %s
|
||||
ORDER BY c.customer_name
|
||||
LIMIT 20
|
||||
""", ("%" + q + "%", "%" + q + "%", "%" + q + "%"), as_dict=True)
|
||||
return customers
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_customer(name):
|
||||
if not name:
|
||||
return {}
|
||||
cust = frappe.get_doc("Customer", name)
|
||||
result = cust.as_dict()
|
||||
addr = frappe.db.sql("""
|
||||
SELECT a.address_line1, a.city, a.state, a.pincode, a.phone
|
||||
FROM tabAddress a
|
||||
JOIN tabDynamic Link dl ON dl.parent = a.name AND dl.link_doctype = 'Customer' AND dl.link_name = %s
|
||||
LIMIT 1
|
||||
""", (name,), as_dict=True)
|
||||
if addr:
|
||||
result.update({
|
||||
"address_line1": addr[0].address_line1,
|
||||
"city": addr[0].city,
|
||||
"state": addr[0].state,
|
||||
"pincode": addr[0].pincode,
|
||||
"address_phone": addr[0].phone
|
||||
})
|
||||
return result
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_customer_from_intake(data):
|
||||
data = frappe.parse_json(data)
|
||||
if not data.get("customer_name"):
|
||||
frappe.throw(_("Customer name required"))
|
||||
customer = frappe.new_doc("Customer")
|
||||
customer.customer_name = data.get("customer_name")
|
||||
customer.customer_group = data.get("customer_group", "IT Recycling")
|
||||
customer.customer_type = "Company"
|
||||
customer.customer_number = data.get("customer_number")
|
||||
customer.phone = data.get("phone")
|
||||
customer.email_id = data.get("email_id")
|
||||
customer.legacy_notes = data.get("legacy_notes")
|
||||
customer.hours_of_operation = data.get("hours_of_operation")
|
||||
customer.contact_persons = data.get("contact_persons")
|
||||
customer.save()
|
||||
if data.get("address_line1") or data.get("city"):
|
||||
addr = frappe.new_doc("Address")
|
||||
addr.address_title = customer.customer_name
|
||||
addr.address_type = "Billing"
|
||||
addr.address_line1 = data.get("address_line1", "Unknown")
|
||||
addr.city = data.get("city", "Unknown")
|
||||
addr.state = data.get("state", "")
|
||||
addr.pincode = data.get("pincode", "")
|
||||
addr.country = "United States"
|
||||
addr.append("links", {"link_doctype": "Customer", "link_name": customer.name})
|
||||
addr.save()
|
||||
return {"status": "ok", "customer": customer.name}
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_pallet(data):
|
||||
data = frappe.parse_json(data)
|
||||
if not data.get("customer"):
|
||||
frappe.throw(_("Customer required"))
|
||||
pallet = frappe.new_doc("Pallet")
|
||||
pallet.customer = data.get("customer")
|
||||
pallet.customer_number = data.get("customer_number")
|
||||
pallet.status = "Open"
|
||||
pallet.save()
|
||||
return {"status": "ok", "pallet": pallet.name}
|
||||
Reference in New Issue
Block a user