update creation

This commit is contained in:
Casey 2026-01-07 08:50:03 -06:00
parent 97241f14ea
commit a96832c21b
4 changed files with 119 additions and 71 deletions

View File

@ -189,7 +189,7 @@ def get_clients_table_data(filters={}, sortings=[], page=1, page_size=10):
customer_name = "N/A"
elif not customer_name and customer_links:
print("DEBUG: No customer to bill. Customer links found:", customer_links)
customer_name = frappe.get_value("Lead", customer_links[0].link_name, "lead_name") if is_lead else customer_links[0].link_name
customer_name = frappe.get_value("Lead", customer_links[0].link_name, "custom_customer_name") if is_lead else customer_links[0].link_name
tableRow["id"] = address["name"]
tableRow["customer_name"] = customer_name
tableRow["address"] = (
@ -213,10 +213,15 @@ def get_clients_table_data(filters={}, sortings=[], page=1, page_size=10):
@frappe.whitelist()
def upsert_client(data):
"""Create or update a client (customer and address)."""
"""Create a client (customer and address)."""
try:
data = json.loads(data)
print("#####DEBUG: Upsert client data received:", data)
print("#####DEBUG: Create client data received:", data)
customer_name = data.get("customer_name")
contacts = data.get("contacts", [])
# Check for existing address
if address_exists(
data.get("address_line1"),
data.get("address_line2"),
@ -227,37 +232,28 @@ def upsert_client(data):
return build_error_response("This address already exists. Please use a different address or search for the address to find the associated client.", 400)
# Handle customer creation/update
print("#####DEBUG: Checking for existing customer with name:", data.get("customer_name"))
customer = frappe.db.exists("Customer", {"customer_name": data.get("customer_name")})
if not customer:
print("#####DEBUG: No existing customer found. Checking for existing lead")
customer = frappe.db.exists("Lead", {"lead_name": data.get("customer_name")})
if not customer:
print("#####DEBUG: No existing lead found. Creating new lead.")
primary_contact = next((c for c in data.get("contacts", []) if c.get("is_primary")), None)
if not primary_contact:
return build_error_response("Primary contact information is required to create a new customer.", 400)
print("#####DEBUG: Primary contact found:", primary_contact)
client_doc = create_lead({
"lead_name": data.get("customer_name"),
"first_name": primary_contact.get("first_name"),
"last_name": primary_contact.get("last_name"),
"email_id": primary_contact.get("email"),
"phone": primary_contact.get("phone_number"),
"customer_type": data.get("customer_type"),
"company": data.get("company")
})
else:
print("#####DEBUG: Existing lead found:", customer)
client_doc = frappe.get_doc("Lead", customer)
else:
print("#####DEBUG: Existing customer found:", customer)
client_doc = frappe.get_doc("Customer", customer)
client_doc = check_and_get_client_doc(customer_name)
if not client_doc:
print("#####DEBUG: Creating new lead.")
customer_type = data.get("customer_type", "Individual")
primary_contact = find_primary_contact_or_throw(contacts)
lead_data = {
"first_name": primary_contact.get("first_name"),
"last_name": primary_contact.get("last_name"),
"email_id": primary_contact.get("email"),
"phone": primary_contact.get("phone_number"),
"company": data.get("company"),
"custom_customer_name": customer_name,
"customer_type": customer_type
}
if customer_type == "Company":
lead_data["company_name"] = data.get("customer_name")
client_doc = create_lead(lead_data)
print(f"#####DEBUG: {client_doc.doctype}:", client_doc.as_dict())
# Handle address creation
address_doc = create_address({
"address_title": build_address_title(data.get("customer_name"), data),
"address_title": build_address_title(customer_name, data),
"address_line1": data.get("address_line1"),
"address_line2": data.get("address_line2"),
"city": data.get("city"),
@ -268,7 +264,7 @@ def upsert_client(data):
#Handle contact creation
contact_docs = []
for contact_data in data.get("contacts", []):
for contact_data in contacts:
if isinstance(contact_data, str):
contact_data = json.loads(contact_data)
print("#####DEBUG: Processing contact data:", contact_data)
@ -283,8 +279,6 @@ def upsert_client(data):
contact_doc = create_contact({
"first_name": contact_data.get("first_name"),
"last_name": contact_data.get("last_name"),
# "email_id": contact_data.get("email"),
# "phone": contact_data.get("phone_number"),
"role": contact_data.get("contact_role", "Other"),
"custom_email": contact_data.get("email"),
"is_primary_contact":1 if contact_data.get("is_primary", False) else 0,
@ -362,7 +356,11 @@ def check_and_get_client_doc(client_name):
customer = frappe.get_doc("Customer", client_name)
else:
print("DEBUG: Client not found as Customer. Checking Lead.")
lead_name = frappe.db.get_all("Lead", pluck="name", filters={"lead_name": client_name})
lead_name = frappe.db.get_all("Lead", pluck="name", filters={"company_name": client_name})
if not lead_name:
lead_name = frappe.db.get_all("Lead", pluck="name", filters={"lead_name": client_name})
if not lead_name:
lead_name = frappe.db.get_all("Lead", pluck="name", filters={"custom_customer_name": client_name})
if lead_name:
print("DEBUG: Client found as Lead.")
customer = frappe.get_doc("Lead", lead_name[0])
@ -387,4 +385,11 @@ def get_customer_or_lead(client_name):
return frappe.get_doc("Customer", client_name)
else:
lead_name = frappe.db.get_all("Lead", pluck="name", filters={"lead_name": client_name})[0]
return frappe.get_doc("Lead", lead_name)
return frappe.get_doc("Lead", lead_name)
def find_primary_contact_or_throw(contacts):
for contact in contacts:
if contact.get("is_primary"):
print("#####DEBUG: Primary contact found:", contact)
return contact
raise ValueError("No primary contact found in contacts list.")

View File

@ -169,7 +169,7 @@ def build_address_title(customer_name, address_data):
def map_lead_client(client_data):
mappings = {
"lead_name": "customer_name",
"custom_customer_name": "customer_name",
"customer_type": "customer_type",
"territory": "territory",
"company_name": "company"

View File

@ -22,6 +22,16 @@
class="w-full"
/>
</div>
<div class="form-field full-width checkbox-row">
<input
type="checkbox"
id="isBilling"
v-model="localFormData.isBillingAddress"
:disabled="isSubmitting"
style="margin-top: 0"
/>
<label for="isBilling">Is Billing Address</label>
</div>
<div class="form-field">
<label for="zipcode"> Zip Code <span class="required">*</span> </label>
<InputText
@ -59,7 +69,7 @@
</template>
<script setup>
import { ref, computed } from "vue";
import { ref, computed, onMounted } from "vue";
import InputText from "primevue/inputtext";
import Api from "../../api";
import { useNotificationStore } from "../../stores/notifications-primevue";
@ -88,6 +98,12 @@ const localFormData = computed({
set: (value) => emit("update:formData", value),
});
onMounted(() => {
if (localFormData.value.isBillingAddress === undefined) {
localFormData.value.isBillingAddress = true;
}
});
const zipcodeLookupDisabled = ref(true);
const handleZipcodeInput = async (event) => {
@ -181,6 +197,17 @@ const handleZipcodeInput = async (event) => {
width: 100% !important;
}
.form-field.checkbox-row {
flex-direction: row;
align-items: center;
gap: 0.5rem;
}
.form-field.checkbox-row label {
margin-bottom: 0;
cursor: pointer;
}
@media (max-width: 768px) {
.form-grid {
grid-template-columns: 1fr;

View File

@ -3,40 +3,8 @@
<div class="form-section">
<div class="section-header">
<h3>Client Information</h3>
<label class="toggle-container" v-if="!isEditMode">
<v-switch v-model="isNewClient" color="success" />
<span class="toggle-label">New Client</span>
</label>
</div>
<div class="form-grid">
<div class="form-field">
<label for="customer-name"> Customer Name <span class="required">*</span> </label>
<div class="input-with-button">
<InputText
id="customer-name"
v-model="localFormData.customerName"
:disabled="isSubmitting || isEditMode"
placeholder="Enter customer name"
class="w-full"
/>
<Button
label="Check Client"
size="small"
icon="pi pi-user-check"
class="check-btn"
@click="checkCustomerExists"
:disabled="isSubmitting || !localFormData.customerName.trim()"
>Check</Button>
<Button
v-if="!isNewClient && !isEditMode"
@click="searchCustomers"
:disabled="isSubmitting || !localFormData.customerName.trim()"
size="small"
icon="pi pi-search"
class="search-btn"
></Button>
</div>
</div>
<div class="form-field">
<label for="customer-type"> Customer Type <span class="required">*</span> </label>
<Select
@ -48,6 +16,34 @@
class="w-full"
/>
</div>
<div class="form-field">
<label for="customer-name"> Customer Name <span class="required">*</span> </label>
<div class="input-with-button">
<InputText
id="customer-name"
v-model="localFormData.customerName"
:disabled="isSubmitting || isEditMode || localFormData.customerType !== 'Company'"
placeholder="Enter customer name"
class="w-full"
/>
<Button
label="Check Client"
size="small"
icon="pi pi-user-check"
class="check-btn"
@click="checkCustomerExists"
:disabled="isSubmitting"
>Check</Button>
<Button
v-if="!isNewClient && !isEditMode"
@click="searchCustomers"
:disabled="isSubmitting || !localFormData.customerName.trim()"
size="small"
icon="pi pi-search"
class="search-btn"
></Button>
</div>
</div>
</div>
</div>
@ -147,6 +143,23 @@ watch(isNewClient, (newValue) => {
emit("newClientToggle", newValue);
});
// Watch for changes that affect customer name
watch(
() => localFormData.value,
(newData) => {
if (newData.customerType === "Individual" && newData.contacts && newData.contacts.length > 0) {
const primary = newData.contacts.find((c) => c.isPrimary) || newData.contacts[0];
const firstName = primary.firstName || "";
const lastName = primary.lastName || "";
const fullName = `${firstName} ${lastName}`.trim();
if (fullName !== newData.customerName) {
newData.customerName = fullName;
}
}
},
{ deep: true },
);
const searchCustomers = async () => {
const searchTerm = localFormData.value.customerName.trim();
if (!searchTerm) return;
@ -172,8 +185,11 @@ const searchCustomers = async () => {
};
const checkCustomerExists = async () => {
const searchTerm = localFormData.value.customerName.trim();
if (!searchTerm) return;
const searchTerm = (localFormData.value.customerName || "").trim();
if (!searchTerm) {
notificationStore.addWarning("Please ensure a customer name is entered before checking.");
return;
}
try {
const client = await Api.getClient(searchTerm);