build out client page, edit functionality, create functionality, data massager

This commit is contained in:
Casey 2025-11-19 22:25:16 -06:00
parent f510645a31
commit 34f2c110d6
15 changed files with 1571 additions and 1681 deletions

View file

@ -194,7 +194,8 @@ def get_clients_table_data(filters={}, sortings=[], page=1, page_size=10):
})
processed_filters, processed_sortings, is_or, page, page_size = process_query_conditions(filters, sortings, page, page_size)
print("DEBUG: Processed filters:", processed_filters)
print("DEBUG: Processed sortings:", processed_sortings)
# Handle count with proper OR filter support
if is_or:
count = frappe.db.sql(*get_count_or_filters("Address", processed_filters))[0][0]

View file

@ -1,8 +1,9 @@
import frappe
import requests
from urllib.parse import urlparse
import logging
allowed_hosts = ["api.zippopotam.us"] # Update this list with trusted domains as needed
allowed_hosts = ["api.zippopotam.us", "nominatim.openstreetmap.org"] # Update this list with trusted domains as needed
@frappe.whitelist(allow_guest=True)
def request(url, method="GET", data=None, headers=None):

View file

@ -5,11 +5,21 @@ from .utils import create_module
def after_install():
create_module()
add_custom_fields()
build_frontend()
def after_migrate():
add_custom_fields()
frappe.db.commit()
# Proper way to refresh metadata
frappe.clear_cache(doctype="Address")
frappe.reload_doctype("Address")
update_address_fields()
build_frontend()
def build_frontend():
app_package_path = frappe.get_app_path("custom_ui")
app_root = os.path.dirname(app_package_path)
@ -40,4 +50,231 @@ def build_frontend():
print("\n✅ Frontend build completed successfully.\n")
except subprocess.CalledProcessError as e:
frappe.log_error(message=str(e), title="Frontend Build Failed")
print(f"\n❌ Frontend build failed: {e}\n")
print(f"\n❌ Frontend build failed: {e}\n")
def add_custom_fields():
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
print("\n🔧 Adding custom fields to Address doctype...")
custom_fields = {
"Address": [
dict(
fieldname="full_address",
label="Full Address",
fieldtype="Data",
insert_after="country"
),
dict(
fieldname="latitude",
label="Latitude",
fieldtype="Float",
precision=8,
insert_after="full_address"
),
dict(
fieldname="longitude",
label="Longitude",
fieldtype="Float",
precision=8,
insert_after="latitude"
),
dict(
fieldname="onsite_meeting_scheduled",
label="On-Site Meeting Scheduled",
fieldtype="Select",
options="Not Started\nIn Progress\nCompleted",
default="Not Started",
insert_after="longitude"
),
dict(
fieldname="estimate_sent_status",
label="Estimate Sent Status",
fieldtype="Select",
options="Not Started\nIn Progress\nCompleted",
default="Not Started",
insert_after="onsite_meeting_scheduled"
),
dict(
fieldname="job_status",
label="Job Status",
fieldtype="Select",
options="Not Started\nIn Progress\nCompleted",
default="Not Started",
insert_after="estimate_sent_status"
),
dict(
fieldname="payment_received_status",
label="Payment Received Status",
fieldtype="Select",
options="Not Started\nIn Progress\nCompleted",
default="Not Started",
insert_after="job_status"
)
]
}
field_count = len(custom_fields["Address"])
print(f"📝 Creating {field_count} custom fields for Address doctype...")
try:
create_custom_fields(custom_fields)
print("✅ Custom fields added successfully!")
print(" • full_address (Data)")
print(" • latitude (Float)")
print(" • longitude (Float)")
print(" • onsite_meeting_scheduled (Select)")
print(" • estimate_sent_status (Select)")
print(" • job_status (Select)")
print(" • payment_received_status (Select)")
print("🔧 Custom fields installation complete.\n")
except Exception as e:
print(f"❌ Error creating custom fields: {str(e)}")
frappe.log_error(message=str(e), title="Custom Fields Creation Failed")
raise
def update_address_fields():
addresses = frappe.get_all("Address", pluck="name")
total_addresses = len(addresses)
if total_addresses == 0:
print("📍 No addresses found to update.")
return
print(f"\n📍 Updating fields for {total_addresses} addresses...")
# Verify custom fields exist by checking the meta
address_meta = frappe.get_meta("Address")
required_fields = ['full_address', 'custom_onsite_meeting_scheduled',
'custom_estimate_sent_status', 'custom_job_status',
'custom_payment_received_status']
missing_fields = []
for field in required_fields:
if not address_meta.has_field(field):
missing_fields.append(field)
if missing_fields:
print(f"\n❌ Missing custom fields: {', '.join(missing_fields)}")
print(" Custom fields creation may have failed. Skipping address updates.")
return
print("✅ All custom fields verified. Proceeding with address updates...")
# Field update counters
field_counters = {
'full_address': 0,
'latitude': 0,
'longitude': 0,
'custom_onsite_meeting_scheduled': 0,
'custom_estimate_sent_status': 0,
'custom_job_status': 0,
'custom_payment_received_status': 0
}
total_field_updates = 0
addresses_updated = 0
for index, name in enumerate(addresses, 1):
# Calculate progress
progress_percentage = int((index / total_addresses) * 100)
bar_length = 30
filled_length = int(bar_length * index // total_addresses)
bar = '' * filled_length + '' * (bar_length - filled_length)
# Print progress bar with field update count
print(f"\r📊 Progress: [{bar}] {progress_percentage:3d}% ({index}/{total_addresses}) | Fields Updated: {total_field_updates} - Processing: {name[:25]}...", end='', flush=True)
should_update = False
address = frappe.get_doc("Address", name)
current_address_updates = 0
current_address_updates = 0
# Use getattr with default values instead of direct attribute access
if not getattr(address, 'full_address', None):
address_parts_1 = [
address.address_line1 or "",
address.address_line2 or "",
address.city or "",
]
address_parts_2 = [
address.state or "",
address.pincode or "",
]
full_address = ", ".join([
" ".join(filter(None, address_parts_1)),
" ".join(filter(None, address_parts_2))
]).strip()
address.full_address = full_address
field_counters['full_address'] += 1
current_address_updates += 1
should_update = True
onsite_meeting = "Not Started"
estimate_sent = "Not Started"
job_status = "Not Started"
payment_received = "Not Started"
onsite_meetings = frappe.get_all("On-Site Meeting", filters={"address": address.address_title})
if onsite_meetings and onsite_meetings[0]:
onsite_meeting = "Completed"
estimates = frappe.get_all("Quotation", fields=["custom_sent"], filters={"custom_installation_address": address.address_title})
if estimates and estimates[0] and estimates[0]["custom_sent"] == 1:
estimate_sent = "Completed"
elif estimates and estimates[0]:
estimate_sent = "In Progress"
jobs = frappe.get_all("Project", fields=["status"], filters={"custom_installation_address": address.address_title, "project_template": "SNW Install"})
if jobs and jobs[0] and jobs[0]["status"] == "Completed":
job_status = "Completed"
elif jobs and jobs[0]:
job_status = "In Progress"
sales_invoices = frappe.get_all("Sales Invoice", fields=["outstanding_amount"], filters={"custom_installation_address": address.address_title})
# payments = frappe.get_all("Payment Entry", filters={"custom_installation_address": address.address_title})
if sales_invoices and sales_invoices[0] and sales_invoices[0]["outstanding_amount"] == 0:
payment_received = "Completed"
elif sales_invoices and sales_invoices[0]:
payment_received = "In Progress"
if getattr(address, 'custom_onsite_meeting_scheduled', None) != onsite_meeting:
address.custom_onsite_meeting_scheduled = onsite_meeting
field_counters['custom_onsite_meeting_scheduled'] += 1
current_address_updates += 1
should_update = True
if getattr(address, 'custom_estimate_sent_status', None) != estimate_sent:
address.custom_estimate_sent_status = estimate_sent
field_counters['custom_estimate_sent_status'] += 1
current_address_updates += 1
should_update = True
if getattr(address, 'custom_job_status', None) != job_status:
address.custom_job_status = job_status
field_counters['custom_job_status'] += 1
current_address_updates += 1
should_update = True
if getattr(address, 'custom_payment_received_status', None) != payment_received:
address.custom_payment_received_status = payment_received
field_counters['custom_payment_received_status'] += 1
current_address_updates += 1
should_update = True
if should_update:
address.save(ignore_permissions=True)
addresses_updated += 1
total_field_updates += current_address_updates
# Print completion summary
print(f"\n\n✅ Address field update completed!")
print(f"📊 Summary:")
print(f" • Total addresses processed: {total_addresses:,}")
print(f" • Addresses updated: {addresses_updated:,}")
print(f" • Total field updates: {total_field_updates:,}")
print(f"\n📝 Field-specific updates:")
print(f" • Full Address: {field_counters['full_address']:,}")
print(f" • Latitude: {field_counters['latitude']:,}")
print(f" • Longitude: {field_counters['longitude']:,}")
print(f" • On-Site Meeting Status: {field_counters['custom_onsite_meeting_scheduled']:,}")
print(f" • Estimate Sent Status: {field_counters['custom_estimate_sent_status']:,}")
print(f" • Job Status: {field_counters['custom_job_status']:,}")
print(f" • Payment Received Status: {field_counters['custom_payment_received_status']:,}")
print("📍 Address field updates complete.\n")