fix estimate row rendering bug

This commit is contained in:
Casey 2026-02-12 08:10:56 -06:00
parent 07af3c52ea
commit b3e6e4f6a2
8 changed files with 3705 additions and 4292 deletions

View File

@ -145,7 +145,7 @@ def get_estimate(estimate_name):
est_dict["address_details"] = address_doc
est_dict["history"] = get_doc_history("Quotation", estimate_name)
est_dict["items"] = [ItemService.get_full_dict(item.item_code) for item in estimate.items]
est_dict["items"] = [{**ItemService.get_full_dict(item.item_code), **item.as_dict()} for item in estimate.items]
return build_success_response(est_dict)
except Exception as e:

View File

@ -4,6 +4,9 @@ from custom_ui.services import AddressService, ClientService, TaskService
def before_insert(doc, method):
"""Set values before inserting a Task."""
print("DEBUG: Before Insert Triggered for Task")
if doc.status == "Template":
print("DEBUG: Task is a Template, skipping project linking")
return
project_doc = frappe.get_doc("Project", doc.project)
doc.project_template = project_doc.project_template
doc.customer = project_doc.customer
@ -12,6 +15,9 @@ def before_insert(doc, method):
def after_insert(doc, method):
print("DEBUG: After Insert Triggered for Task")
if doc.status == "Template":
print("DEBUG: Task is a Template, skipping linking to Customer and Address")
return
print("DEBUG: Linking Task to Customer and Address")
AddressService.append_link_v2(
doc.custom_property, "tasks", {"task": doc.name, "project_template": doc.project_template }
@ -27,17 +33,22 @@ def after_insert(doc, method):
def before_save(doc, method):
print("DEBUG: Before Save Triggered for Task:", doc.name)
task_type_weight = frappe.get_value("Task Type", doc.type, "weight") or 0
if doc.task_weight != task_type_weight:
print(f"DEBUG: Updating Task weight from {doc.task_weight} to {task_type_weight}")
doc.task_weight = task_type_weight
event = TaskService.determine_event(doc)
if event:
task_names = [task.name for task in TaskService.get_tasks_by_project(doc.project)]
TaskService.fire_task_triggers(task_names, event, current_triggering_dict=doc.as_dict())
if doc.type:
task_type_weight = frappe.get_value("Task Type", doc.type, "weight") or 0
if doc.task_weight != task_type_weight:
print(f"DEBUG: Updating Task weight from {doc.task_weight} to {task_type_weight}")
doc.task_weight = task_type_weight
if doc.status != "Template":
event = TaskService.determine_event(doc)
if event:
task_names = [task.name for task in TaskService.get_tasks_by_project(doc.project)]
TaskService.fire_task_triggers(task_names, event, current_triggering_dict=doc.as_dict())
def after_save(doc, method):
print("DEBUG: After Save Triggered for Task:", doc.name)
if doc.status == "Template":
print("DEBUG: Task is a Template, skipping after save logic")
return
if doc.project and doc.status == "Completed":
print("DEBUG: Task is completed, checking if project has calculated 100% Progress.")
project_doc = frappe.get_doc("Project", doc.project)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,100 @@
[
{
"default_value": null,
"doc_type": "Task Depends On",
"docstatus": 0,
"doctype": "Property Setter",
"doctype_or_field": "DocType",
"field_name": null,
"is_system_generated": 0,
"modified": "2026-02-07 03:50:27.263355",
"module": null,
"name": "Task Depends On-main-field_order",
"property": "field_order",
"property_type": "Data",
"row_name": null,
"value": "[\"task\", \"custom_depends_on_doctype\", \"custom_depends_on\", \"custom_event\", \"column_break_2\", \"subject\", \"project\"]"
},
{
"default_value": null,
"doc_type": "Project",
"docstatus": 0,
"doctype": "Property Setter",
"doctype_or_field": "DocField",
"field_name": "percent_complete_method",
"is_system_generated": 0,
"modified": "2026-02-07 04:16:27.055142",
"module": null,
"name": "Project-percent_complete_method-fetch_from",
"property": "fetch_from",
"property_type": "Small Text",
"row_name": null,
"value": "project_template.custom__complete_method"
},
{
"default_value": null,
"doc_type": "Project",
"docstatus": 0,
"doctype": "Property Setter",
"doctype_or_field": "DocField",
"field_name": "percent_complete_method",
"is_system_generated": 0,
"modified": "2026-02-07 04:16:27.092804",
"module": null,
"name": "Project-percent_complete_method-fetch_if_empty",
"property": "fetch_if_empty",
"property_type": "Check",
"row_name": null,
"value": "1"
},
{
"default_value": null,
"doc_type": "Task",
"docstatus": 0,
"doctype": "Property Setter",
"doctype_or_field": "DocField",
"field_name": "description",
"is_system_generated": 0,
"modified": "2026-02-08 02:52:56.753089",
"module": null,
"name": "Task-description-fetch_from",
"property": "fetch_from",
"property_type": "Small Text",
"row_name": null,
"value": "type.description"
},
{
"default_value": null,
"doc_type": "Task",
"docstatus": 0,
"doctype": "Property Setter",
"doctype_or_field": "DocField",
"field_name": "description",
"is_system_generated": 0,
"modified": "2026-02-08 02:52:56.836830",
"module": null,
"name": "Task-description-fetch_if_empty",
"property": "fetch_if_empty",
"property_type": "Check",
"row_name": null,
"value": "1"
},
{
"default_value": null,
"doc_type": "Task Type",
"docstatus": 0,
"doctype": "Property Setter",
"doctype_or_field": "DocType",
"field_name": null,
"is_system_generated": 0,
"modified": "2026-02-09 01:29:07.457962",
"module": null,
"name": "Task Type-main-field_order",
"property": "field_order",
"property_type": "Data",
"row_name": null,
"value": "[\"weight\", \"description\", \"base_date\", \"offset_days\", \"skip_weekends\", \"skip_holidays\", \"logic_key\", \"offset_direction\", \"title\", \"days\", \"calculate_from\", \"trigger\", \"task_type_calculate_from\", \"work_type\", \"no_due_date\", \"triggering_doctype\", \"custom_completion_trigger\", \"custom_completion_trigger_doctype\", \"target_percent\"]"
},
{
"default_value": null,
"doc_type": "Contact",

View File

@ -313,5 +313,50 @@
"total_costing_amount": 0.0,
"total_expense_claim": 0.0,
"type": "Labor"
},
{
"act_end_date": null,
"act_start_date": null,
"actual_time": 0.0,
"closing_date": null,
"color": null,
"company": "Sprinklers Northwest",
"completed_by": null,
"completed_on": null,
"custom_foreman": "HR-EMP-00014",
"custom_property": null,
"customer": null,
"department": null,
"depends_on": [],
"depends_on_tasks": "",
"description": null,
"docstatus": 0,
"doctype": "Task",
"duration": 0,
"exp_end_date": null,
"exp_start_date": null,
"expected_time": 0.0,
"is_group": 0,
"is_milestone": 0,
"is_template": 1,
"issue": null,
"modified": "2026-01-23 02:29:45.172285",
"name": "TASK-2025-00007",
"old_parent": "",
"parent_task": null,
"priority": "Low",
"progress": 0.0,
"project": null,
"project_template": null,
"review_date": null,
"start": 0,
"status": "Template",
"subject": "15-Day QA",
"task_weight": 0.0,
"template_task": null,
"total_billing_amount": 0.0,
"total_costing_amount": 0.0,
"total_expense_claim": 0.0,
"type": "15 Day Warranty Follow-Up"
}
]

View File

@ -195,7 +195,8 @@ doc_events = {
"Task": {
"before_insert": "custom_ui.events.task.before_insert",
"after_insert": "custom_ui.events.task.after_insert",
"before_save": "custom_ui.events.task.before_save"
"before_save": "custom_ui.events.task.before_save",
"after_save": "custom_ui.events.task.after_save"
},
"Bid Meeting Note Form": {
"after_insert": "custom_ui.events.general.attach_bid_note_form_to_project_template"
@ -257,7 +258,7 @@ scheduler_events = {
# "custom_ui.tasks.all"
# ],
"daily": [
"custom_ui.scheduled_tasks.daily"
"custom_ui.scheduled_tasks.daily_task"
],
# "hourly": [
# "custom_ui.tasks.hourly"

View File

@ -850,11 +850,24 @@ def add_custom_fields():
meta = frappe.get_meta(doctype)
for field_spec in field_options:
fieldname = field_spec["fieldname"]
if not meta.has_field(fieldname):
missing_fields.append(f"{doctype}: {fieldname}")
else:
# Field exists, check if specs match
custom_field_name = f"{doctype}-{fieldname}"
custom_field_name = f"{doctype}-{fieldname}"
# First check if it's a regular DocType field (not a custom field)
is_regular_field = False
if frappe.db.exists("DocType", doctype):
doctype_doc = frappe.get_doc("DocType", doctype)
for df in doctype_doc.fields:
if df.fieldname == fieldname:
is_regular_field = True
break
if is_regular_field:
# It's a regular DocType field, skip it completely
continue
# Check if field exists in meta or as a custom field
if meta.has_field(fieldname) or frappe.db.exists("Custom Field", custom_field_name):
# Field exists as a custom field, check if it needs updating
if frappe.db.exists("Custom Field", custom_field_name):
custom_field_doc = frappe.get_doc("Custom Field", custom_field_name)
needs_update = False
@ -870,6 +883,9 @@ def add_custom_fields():
if needs_update:
fields_to_update.append((doctype, fieldname, field_spec))
else:
# Field doesn't exist at all, add to missing
missing_fields.append(f"{doctype}: {fieldname}")
if missing_fields:
print("\n❌ Missing custom fields:")
@ -1543,7 +1559,7 @@ def create_bid_meeting_note_form_templates():
doc.title = form["title"]
doc.description = form.get("description")
doc.project_template = form.get("project_template")
frappe.set_value("Project Template", doc.project_template, "bid_meeting_note_form",doc.name)
for idx, field in enumerate(form.get("fields", []), start=1):
doc.append(
"fields",