add accept estimate without sent
This commit is contained in:
parent
c56f1a2930
commit
9f9318ddef
@ -313,15 +313,11 @@ def manual_response(name, response):
|
||||
if not frappe.db.exists("Quotation", name):
|
||||
raise Exception("Estimate not found.")
|
||||
estimate = frappe.get_doc("Quotation", name)
|
||||
if estimate.docstatus != 1:
|
||||
raise Exception("Estimate must be submitted to update response.")
|
||||
accepted = True if response == "Accepted" else False
|
||||
new_status = "Estimate Accepted" if accepted else "Lost"
|
||||
|
||||
estimate.custom_response = response
|
||||
estimate.custom_current_status = new_status
|
||||
# estimate.custom_current_status = new_status
|
||||
# estimate.status = "Ordered" if accepted else "Closed"
|
||||
estimate.flags.ignore_permissions = True
|
||||
print("DEBUG: Updating estimate with response:", response, "and status:", new_status)
|
||||
estimate.save()
|
||||
|
||||
101
custom_ui/migration_data/move_primary_contact.py
Normal file
101
custom_ui/migration_data/move_primary_contact.py
Normal file
@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Move primary_contact from addresses.json to address_updates.json as {first_name, last_name}."""
|
||||
|
||||
import json
|
||||
|
||||
DATA_DIR = "/home/casey-wittrock/brotherton-bench/apps/custom_ui/custom_ui/migration_data"
|
||||
|
||||
|
||||
def extract_full_name(primary_contact_str):
|
||||
"""Extract full_name from the 'full_name-full_name' format."""
|
||||
if not primary_contact_str:
|
||||
return None
|
||||
# Format is "FullName-FullName" where the name is duplicated
|
||||
n = len(primary_contact_str)
|
||||
if n >= 3:
|
||||
mid = n // 2
|
||||
if primary_contact_str[mid] == '-' and primary_contact_str[:mid] == primary_contact_str[mid + 1:]:
|
||||
return primary_contact_str[:mid]
|
||||
# Fallback: return as-is
|
||||
return primary_contact_str
|
||||
|
||||
|
||||
def main():
|
||||
# Load contacts.json for first_name/last_name lookup
|
||||
print("Loading contacts.json...")
|
||||
with open(f"{DATA_DIR}/contacts.json", "r") as f:
|
||||
contacts = json.load(f)
|
||||
|
||||
contact_lookup = {}
|
||||
for c in contacts:
|
||||
first = c.get("first_name", "")
|
||||
last = c.get("last_name", "")
|
||||
full = f"{first} {last}".strip()
|
||||
if full:
|
||||
contact_lookup[full] = {"first_name": first, "last_name": last}
|
||||
print(f" Built contact lookup with {len(contact_lookup)} entries")
|
||||
|
||||
# Load addresses.json
|
||||
print("Loading addresses.json...")
|
||||
with open(f"{DATA_DIR}/addresses.json", "r") as f:
|
||||
addresses = json.load(f)
|
||||
|
||||
# Build map: address_title -> primary_contact info
|
||||
primary_contact_map = {}
|
||||
missing_contacts = set()
|
||||
null_contacts = 0
|
||||
found_contacts = 0
|
||||
|
||||
for addr in addresses:
|
||||
title = addr.get("address_title")
|
||||
pc_str = addr.get("primary_contact")
|
||||
if not title:
|
||||
continue
|
||||
if not pc_str:
|
||||
null_contacts += 1
|
||||
continue
|
||||
full_name = extract_full_name(pc_str)
|
||||
if full_name and full_name in contact_lookup:
|
||||
primary_contact_map[title] = contact_lookup[full_name]
|
||||
found_contacts += 1
|
||||
elif full_name:
|
||||
missing_contacts.add(full_name)
|
||||
# Still use the full_name as first_name fallback
|
||||
primary_contact_map[title] = {"first_name": full_name, "last_name": ""}
|
||||
|
||||
print(f" Found {found_contacts} primary contacts, {null_contacts} null, {len(missing_contacts)} missing from contacts.json")
|
||||
if missing_contacts:
|
||||
for c in sorted(missing_contacts)[:5]:
|
||||
print(f" - {c}")
|
||||
if len(missing_contacts) > 5:
|
||||
print(f" ... and {len(missing_contacts) - 5} more")
|
||||
|
||||
# Remove primary_contact from addresses.json
|
||||
print("\nRemoving primary_contact from addresses.json...")
|
||||
for addr in addresses:
|
||||
addr.pop("primary_contact", None)
|
||||
with open(f"{DATA_DIR}/addresses.json", "w") as f:
|
||||
json.dump(addresses, f, indent=2)
|
||||
print(" Done.")
|
||||
|
||||
# Add primary_contact to address_updates.json
|
||||
print("Adding primary_contact to address_updates.json...")
|
||||
with open(f"{DATA_DIR}/address_updates.json", "r") as f:
|
||||
address_updates = json.load(f)
|
||||
|
||||
added = 0
|
||||
for entry in address_updates:
|
||||
title = entry.get("address_title")
|
||||
if title and title in primary_contact_map:
|
||||
entry["primary_contact"] = primary_contact_map[title]
|
||||
added += 1
|
||||
|
||||
with open(f"{DATA_DIR}/address_updates.json", "w") as f:
|
||||
json.dump(address_updates, f, indent=2)
|
||||
print(f" Added primary_contact to {added} address update entries.")
|
||||
|
||||
print("\nDone!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -2,8 +2,8 @@
|
||||
<div class="estimate-page">
|
||||
<h2>{{ isNew ? 'Create Estimate' : 'View Estimate' }}</h2>
|
||||
<div v-if="!isNew && estimate" class="page-actions">
|
||||
<div v-if="estimate && estimate.customSent === 1">
|
||||
<Button label="Estimate Response" @click="showResponseModal = true" />
|
||||
<div v-if="estimate">
|
||||
<Button label="Estimate Response" @click="handleResponseClick" />
|
||||
</div>
|
||||
<Button label="Duplicate" icon="pi pi-copy" @click="duplicateEstimate" />
|
||||
</div>
|
||||
@ -245,7 +245,7 @@
|
||||
<div v-if="estimate">
|
||||
<Button label="Send Estimate" @click="initiateSendEstimate" :disabled="estimate.customSent === 1"/>
|
||||
</div>
|
||||
<div v-if="estimate && estimate.customSent === 1" class="response-status">
|
||||
<div v-if="estimate && (estimate.customSent === 1 || estimateResponse)" class="response-status">
|
||||
<h4>Customer Response:</h4>
|
||||
<span :class="getResponseClass(getResponseText(estimateResponse))">
|
||||
{{ getResponseText(estimateResponse) }}
|
||||
@ -270,6 +270,27 @@
|
||||
<Button label="Submit" @click="submitResponse"/>
|
||||
</Modal>
|
||||
|
||||
<!-- Unsent Estimate Warning Modal -->
|
||||
<Modal
|
||||
:visible="showUnsentWarningModal"
|
||||
@update:visible="showUnsentWarningModal = $event"
|
||||
@close="showUnsentWarningModal = false"
|
||||
:options="{ showActions: false }"
|
||||
>
|
||||
<template #title>Warning</template>
|
||||
<div class="modal-content">
|
||||
<p>This estimate has not been sent. Are you sure you want to manually set a response?</p>
|
||||
<div class="confirmation-buttons">
|
||||
<Button
|
||||
label="No"
|
||||
@click="showUnsentWarningModal = false"
|
||||
severity="secondary"
|
||||
/>
|
||||
<Button label="Yes" @click="confirmUnsentWarning" />
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<!-- Save Template Modal -->
|
||||
<SaveTemplateModal
|
||||
:visible="showSaveTemplateModal"
|
||||
@ -485,6 +506,7 @@ const showAddItemModal = ref(false);
|
||||
const showConfirmationModal = ref(false);
|
||||
const showDownPaymentWarningModal = ref(false);
|
||||
const showResponseModal = ref(false);
|
||||
const showUnsentWarningModal = ref(false);
|
||||
const showSaveTemplateModal = ref(false);
|
||||
const showSavePackageModal = ref(false);
|
||||
const addressSearchResults = ref([]);
|
||||
@ -820,6 +842,19 @@ const submitResponse = () => {
|
||||
showResponseModal.value = false;
|
||||
}
|
||||
|
||||
const handleResponseClick = () => {
|
||||
if (estimate.value.customSent !== 1) {
|
||||
showUnsentWarningModal.value = true;
|
||||
} else {
|
||||
showResponseModal.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
const confirmUnsentWarning = () => {
|
||||
showUnsentWarningModal.value = false;
|
||||
showResponseModal.value = true;
|
||||
};
|
||||
|
||||
const duplicateEstimate = () => {
|
||||
if (!estimate.value) return;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user