Fixed integration error from update.

This commit is contained in:
Ty Reynolds
2026-05-11 08:28:01 -04:00
parent 8a4a4b7542
commit f70c9a9321

View File

@@ -1,58 +1,129 @@
frappe.provide("ns_app.customer"); frappe.provide("ns_app.customer");
// Preserve original quick entry
const _make_quick_entry = frappe.ui.form.make_quick_entry;
console.log("NS APP CUSTOMER JS LOADED"); console.log("NS APP CUSTOMER JS LOADED");
// Override $(document).ready(() => {
frappe.ui.form.make_quick_entry = function (doctype, after_insert) {
if (doctype === "Customer") { setTimeout(() => {
console.log("NS App: Intercepted Customer Quick Entry"); const TargetClass =
frappe.ui.form.CustomerQuickEntryForm;
let customer_name = ""; if (!TargetClass) {
// Pull value from current form route options console.error(
if (frappe.route_options?.name) { "NS App: CustomerQuickEntryForm not found"
customer_name = frappe.route_options.name; );
return;
} }
// Fallback: get typed value from active link field // Prevent duplicate patching
if (!customer_name) { if (TargetClass.__ns_patched) {
const active = document.activeElement; console.log(
"NS App: already patched"
);
if (active && active.value) { return;
customer_name = active.value;
}
} }
console.log("NS App: Captured customer name:", customer_name); console.log(
"NS App: patching CustomerQuickEntryForm"
);
ns_app.customer.open_quick_entry({ frappe.ui.form.CustomerQuickEntryForm =
callback: after_insert, class extends TargetClass {
customer_name: customer_name
});
return; render_dialog() {
}
return _make_quick_entry.apply(this, arguments); console.log(
}; "NS App: render_dialog intercepted"
);
let customer_name = "";
// Route option first
if (frappe.route_options?.name) {
customer_name =
frappe.route_options.name;
}
// Focused field fallback
if (!customer_name) {
const active =
document.activeElement;
if (
active &&
active.value
) {
customer_name =
active.value;
}
}
// cur_frm fallback
if (
!customer_name &&
typeof cur_frm !==
"undefined" &&
cur_frm
) {
customer_name =
cur_frm.doc.customer ||
cur_frm.doc.party_name ||
"";
}
console.log(
"NS App: Captured customer name:",
customer_name
);
// DO NOT call super.render_dialog()
// This restores the fully custom dialog
ns_app.customer.open_quick_entry({
customer_name:
customer_name,
callback:
this.after_insert
});
}
};
TargetClass.__ns_patched = true;
console.log(
"NS App: CustomerQuickEntryForm patched successfully"
);
}, 1000);
});
ns_app.customer.open_quick_entry = function (opts = {}) { ns_app.customer.open_quick_entry = function (opts = {}) {
console.log("NS App: Custom Customer Quick Entry OPENED"); console.log(
"NS App: Custom Customer Quick Entry OPENED"
);
const d = new frappe.ui.Dialog({ const d = new frappe.ui.Dialog({
title: "New Customer", title: "New Customer",
size: "large", size: "large",
fields: [ fields: [
// ───────── CUSTOMER ───────── // ───────── CUSTOMER ─────────
{ {
fieldtype: "Section Break", fieldtype: "Section Break",
label: "Customer Information" label: "Customer Information"
@@ -63,18 +134,22 @@ ns_app.customer.open_quick_entry = function (opts = {}) {
label: "Customer Name", label: "Customer Name",
fieldtype: "Data", fieldtype: "Data",
reqd: 1, reqd: 1,
default: opts.customer_name || "", default:
description: "Enter the customer or company name" opts.customer_name || "",
description:
"Enter the customer or company name"
}, },
{ {
fieldname: "customer_type", fieldname: "customer_type",
label: "Customer Type", label: "Customer Type",
fieldtype: "Select", fieldtype: "Select",
options: "Company\nIndividual", options:
"Company\nIndividual",
default: "Company", default: "Company",
reqd: 1, reqd: 1,
description: "Select whether this customer is a company or individual" description:
"Select whether this customer is a company or individual"
}, },
{ {
@@ -84,18 +159,23 @@ ns_app.customer.open_quick_entry = function (opts = {}) {
options: "Customer Group", options: "Customer Group",
default: "Commercial", default: "Commercial",
reqd: 1, reqd: 1,
description: "Select the customer group" description:
"Select the customer group"
}, },
{ {
fieldname: "custom_send_via", fieldname: "custom_send_via",
label: "Preferred Delivery Method", label:
"Preferred Delivery Method",
fieldtype: "Select", fieldtype: "Select",
options: "mail\nemail\nfax", options:
description: "Choose how documents should be sent to the customer" "mail\nemail\nfax",
description:
"Choose how documents should be sent to the customer"
}, },
// ───────── CONTACT ───────── // ───────── CONTACT ─────────
{ {
fieldtype: "Section Break", fieldtype: "Section Break",
label: "Primary Contact" label: "Primary Contact"
@@ -106,36 +186,45 @@ ns_app.customer.open_quick_entry = function (opts = {}) {
label: "Email Address", label: "Email Address",
fieldtype: "Data", fieldtype: "Data",
options: "Email", options: "Email",
description: "Enter the customer's email address" description:
"Enter the customer's email address"
}, },
{ {
fieldname: "mobile_no", fieldname: "mobile_no",
label: "Mobile Phone Number", label:
"Mobile Phone Number",
fieldtype: "Data", fieldtype: "Data",
reqd: 1, reqd: 1,
description: "Enter the customer's mobile phone number" description:
"Enter the customer's mobile phone number"
}, },
// ───────── ADDRESS ───────── // ───────── ADDRESS ─────────
{ {
fieldtype: "Section Break", fieldtype: "Section Break",
label: "Address Information" label:
"Address Information"
}, },
{ {
fieldname: "address_line1", fieldname: "address_line1",
label: "Address Line 1", label:
"Address Line 1",
fieldtype: "Data", fieldtype: "Data",
reqd: 1, reqd: 1,
description: "Enter the street address" description:
"Enter the street address"
}, },
{ {
fieldname: "address_line2", fieldname: "address_line2",
label: "Address Line 2", label:
"Address Line 2",
fieldtype: "Data", fieldtype: "Data",
description: "Enter apartment, suite, or secondary address information" description:
"Enter apartment, suite, or secondary address information"
}, },
{ {
@@ -143,21 +232,24 @@ ns_app.customer.open_quick_entry = function (opts = {}) {
label: "ZIP Code", label: "ZIP Code",
fieldtype: "Data", fieldtype: "Data",
reqd: 1, reqd: 1,
description: "Enter the ZIP or postal code" description:
"Enter the ZIP or postal code"
}, },
{ {
fieldname: "city", fieldname: "city",
label: "City", label: "City",
fieldtype: "Data", fieldtype: "Data",
description: "Enter the city" description:
"Enter the city"
}, },
{ {
fieldname: "state", fieldname: "state",
label: "State", label: "State",
fieldtype: "Data", fieldtype: "Data",
description: "Enter the state" description:
"Enter the state"
}, },
{ {
@@ -165,40 +257,61 @@ ns_app.customer.open_quick_entry = function (opts = {}) {
label: "Country", label: "Country",
fieldtype: "Link", fieldtype: "Link",
options: "Country", options: "Country",
default: "United States", default:
description: "Select the country" "United States",
description:
"Select the country"
} }
], ],
primary_action_label: "Create Customer", primary_action_label:
"Create Customer",
primary_action(values) { primary_action(values) {
console.log("NS App: Create Customer clicked", values); console.log(
"NS App: Create Customer clicked",
values
);
d.disable_primary_action(); d.disable_primary_action();
frappe.call({ frappe.call({
method: "ns_app.api.customer.create_customer_full",
method:
"ns_app.api.customer.create_customer_full",
args: values, args: values,
callback(r) { callback(r) {
console.log("NS App: Customer created", r.message); console.log(
"NS App: Customer created",
r.message
);
d.hide(); d.hide();
frappe.show_alert({ frappe.show_alert({
message: "Customer created via NS App",
message:
"Customer created via NS App",
indicator: "green" indicator: "green"
}); });
if (opts.callback) { if (
opts.callback(r.message); opts.callback
) {
opts.callback(
r.message
);
} }
}, },
always() { always() {
d.enable_primary_action(); d.enable_primary_action();
} }
}); });
@@ -207,29 +320,38 @@ ns_app.customer.open_quick_entry = function (opts = {}) {
d.show(); d.show();
// Accessibility labels for screen readers // Accessibility labels
setTimeout(() => { setTimeout(() => {
d.fields.forEach(field => { d.fields.forEach(field => {
const control = d.get_field(field.fieldname); const control =
d.get_field(
field.fieldname
);
if (!control || !control.$input) return; if (
!control ||
!control.$input
) {
return;
}
// ARIA label
control.$input.attr( control.$input.attr(
"aria-label", "aria-label",
field.label || field.fieldname field.label ||
field.fieldname
); );
// Screen reader title
control.$input.attr( control.$input.attr(
"title", "title",
field.label || field.fieldname field.label ||
field.fieldname
); );
// Placeholder text
if (field.label) { if (field.label) {
control.$input.attr( control.$input.attr(
"placeholder", "placeholder",
field.label field.label
@@ -237,63 +359,127 @@ ns_app.customer.open_quick_entry = function (opts = {}) {
} }
}); });
console.log("NS App: Accessibility labels applied"); console.log(
"NS App: accessibility applied"
);
}, 300); }, 300);
// ZIP auto-fill // ZIP autofill
d.fields_dict.pincode.df.onchange = () => {
const zip = d.get_value("pincode"); d.fields_dict.pincode.df.onchange =
() => {
if (!zip || zip.length < 5) return; const zip =
d.get_value(
"pincode"
);
console.log("NS App: ZIP lookup", zip);
fetch(`https://api.zippopotam.us/us/${zip}`)
.then(r => r.ok ? r.json() : null)
.then(data => {
if (!data || !data.places?.length) return;
const p = data.places[0];
d.set_value("city", p["place name"]);
d.set_value("state", p["state"]);
d.set_value("country", data.country);
console.log("NS App: ZIP autofill success");
})
.catch(() => {});
};
// Prevent Enter from submitting unless primary button is focused
d.$wrapper.on("keydown", "input, select, textarea", function (e) {
if (e.key === "Enter") {
const active = document.activeElement;
// Allow Enter ONLY if primary action button is focused
if ( if (
active && !zip ||
active.classList.contains("btn-primary") zip.length < 5
) { ) {
return; return;
} }
e.preventDefault(); console.log(
"NS App: ZIP lookup",
zip
);
// Move to next field fetch(
const fields = d.$wrapper `https://api.zippopotam.us/us/${zip}`
.find("input, select, textarea") )
.filter(":visible:not([disabled])"); .then(r =>
r.ok
? r.json()
: null
)
.then(data => {
const index = fields.index(this); if (
!data ||
!data.places?.length
) {
return;
}
if (index > -1 && index + 1 < fields.length) { const p =
fields.eq(index + 1).focus(); data.places[0];
d.set_value(
"city",
p["place name"]
);
d.set_value(
"state",
p["state"]
);
d.set_value(
"country",
data.country
);
console.log(
"NS App: ZIP autofill success"
);
})
.catch(() => {});
};
// Enter navigation
d.$wrapper.on(
"keydown",
"input, select, textarea",
function (e) {
if (
e.key === "Enter"
) {
const active =
document.activeElement;
// Allow submit only
// on primary button
if (
active &&
active.classList.contains(
"btn-primary"
)
) {
return;
}
e.preventDefault();
const fields =
d.$wrapper
.find(
"input, select, textarea"
)
.filter(
":visible:not([disabled])"
);
const index =
fields.index(this);
if (
index > -1 &&
index + 1 <
fields.length
) {
fields
.eq(index + 1)
.focus();
}
} }
} }
}); );
}; };