255 lines
11 KiB
Python
255 lines
11 KiB
Python
import frappe
|
|
import json
|
|
from custom_ui.db_utils import build_error_response, build_success_response, process_filters, process_sorting
|
|
from custom_ui.services import DbService, ClientService, AddressService, ContactService
|
|
|
|
@frappe.whitelist()
|
|
def get_week_bid_meetings(week_start, week_end, company):
|
|
"""Get On-Site Meetings scheduled within a specific week."""
|
|
try:
|
|
meetings = frappe.db.get_all(
|
|
"On-Site Meeting",
|
|
fields=["*"],
|
|
filters=[
|
|
["status", "!=", "Cancelled"],
|
|
["start_time", ">=", week_start],
|
|
["start_time", "<=", week_end],
|
|
["company", "=", company]
|
|
],
|
|
order_by="start_time asc"
|
|
)
|
|
for meeting in meetings:
|
|
address_doc = AddressService.get_or_throw(meeting["address"])
|
|
meeting["address"] = address_doc.as_dict()
|
|
contact_doc = ContactService.get_or_throw(meeting["contact"]) if meeting.get("contact") else None
|
|
meeting["contact"] = contact_doc.as_dict() if contact_doc else None
|
|
return build_success_response(meetings)
|
|
except Exception as e:
|
|
frappe.log_error(message=str(e), title="Get Week On-Site Meetings Failed")
|
|
return build_error_response(str(e), 500)
|
|
|
|
@frappe.whitelist()
|
|
def get_bid_meeting_note_form(project_template):
|
|
bid_meeting_note_form_name = frappe.db.get_value("Project Template", project_template, "bid_meeting_note_form")
|
|
if not bid_meeting_note_form_name:
|
|
return build_error_response(f"No Bid Meeting Note Form configured for Project Template '{project_template}'", 404)
|
|
try:
|
|
note_form = frappe.get_doc("Bid Meeting Note Form", bid_meeting_note_form_name)
|
|
return build_success_response(note_form.as_dict())
|
|
except Exception as e:
|
|
frappe.log_error(message=str(e), title="Get Bid Meeting Note Form Failed")
|
|
return build_error_response(str(e), 500)
|
|
|
|
@frappe.whitelist()
|
|
def get_bid_meetings(fields=["*"], filters={}, company=None):
|
|
"""Get paginated On-Site Meetings with filtering and sorting support."""
|
|
try:
|
|
print("DEBUG: Raw bid meeting options received:", filters)
|
|
|
|
processed_filters = process_filters(filters)
|
|
|
|
meetings = frappe.db.get_all(
|
|
"On-Site Meeting",
|
|
fields=fields,
|
|
filters=processed_filters,
|
|
order_by="creation desc"
|
|
)
|
|
for meeting in meetings:
|
|
address_doc = frappe.get_doc("Address", meeting["address"])
|
|
meeting["address"] = address_doc.as_dict()
|
|
|
|
return build_success_response(
|
|
meetings
|
|
)
|
|
except Exception as e:
|
|
frappe.log_error(message=str(e), title="Get On-Site Meetings Failed")
|
|
return build_error_response(str(e), 500)
|
|
|
|
@frappe.whitelist()
|
|
def get_bid_meeting_note(name):
|
|
"""Get a specific Bid Meeting Note by name."""
|
|
try:
|
|
note = frappe.get_doc("Bid Meeting Note", name)
|
|
return build_success_response(note.as_dict())
|
|
except frappe.DoesNotExistError:
|
|
return build_error_response(f"Bid Meeting Note '{name}' does not exist.", 404)
|
|
except Exception as e:
|
|
frappe.log_error(message=str(e), title="Get Bid Meeting Note Failed")
|
|
return build_error_response(str(e), 500)
|
|
|
|
@frappe.whitelist()
|
|
def get_unscheduled_bid_meetings(company):
|
|
"""Get On-Site Meetings that are unscheduled."""
|
|
try:
|
|
meetings = frappe.db.get_all(
|
|
"On-Site Meeting",
|
|
fields=["*"],
|
|
filters={"status": "Unscheduled", "company": company},
|
|
order_by="creation desc"
|
|
)
|
|
for meeting in meetings:
|
|
address_doc = AddressService.get_or_throw(meeting["address"])
|
|
meeting["address"] = address_doc.as_dict()
|
|
# client_doc = ClientService.get_client_doctype(meeting["party_name"])
|
|
# meeting["client"] = client_doc.as_dict() if client_doc else None
|
|
contact_doc = ContactService.get_or_throw(meeting["contact"]) if meeting.get("contact") else None
|
|
meeting["contact"] = contact_doc.as_dict() if contact_doc else None
|
|
return build_success_response(meetings)
|
|
except Exception as e:
|
|
frappe.log_error(message=str(e), title="Get Unscheduled On-Site Meetings Failed")
|
|
return build_error_response(str(e), 500)
|
|
|
|
@frappe.whitelist()
|
|
def submit_bid_meeting_note_form(bid_meeting, project_template, fields, form_template):
|
|
"""Submit Bid Meeting Note Form data for a specific On-Site Meeting."""
|
|
if isinstance(fields, str):
|
|
fields = json.loads(fields)
|
|
try:
|
|
print(f"DEBUG: Submitting Bid Meeting Note Form for meeting='{bid_meeting}' from template='{form_template}' with fields='{fields}'")
|
|
|
|
meeting = DbService.get_or_throw("On-Site Meeting", bid_meeting)
|
|
|
|
# Update fields on the meeting
|
|
meeting_note_field_docs = [{
|
|
"label": field.get("label"),
|
|
"type": field.get("type"),
|
|
"value": json.dumps(field.get("value")) if isinstance(field.get("value"), (list, dict)) else field.get("value"),
|
|
"row": field.get("row"),
|
|
"column": field.get("column"),
|
|
"value_doctype": field.get("doctype_for_select"),
|
|
"available_options": field.get("options"),
|
|
"include_available_options": field.get("include_available_options", False),
|
|
"conditional_on_field": field.get("conditional_on_field"),
|
|
"conditional_on_value": field.get("conditional_on_value"),
|
|
"doctype_label_field": field.get("doctype_label_field")
|
|
} for field in fields]
|
|
new_bid_meeting_note_doc = frappe.get_doc({
|
|
"doctype": "Bid Meeting Note",
|
|
"bid_meeting": bid_meeting,
|
|
"project_template": project_template,
|
|
"form_template": form_template,
|
|
"fields": meeting_note_field_docs
|
|
})
|
|
new_bid_meeting_note_doc.insert(ignore_permissions=True)
|
|
for field_row, field in zip(new_bid_meeting_note_doc.fields, fields):
|
|
print(f"DEBUG: {field_row.label} - {field.get('label')}")
|
|
if not isinstance(field.get("value"), list):
|
|
continue
|
|
for item in field["value"]:
|
|
if not isinstance(item, dict):
|
|
continue
|
|
new_bid_meeting_note_doc.append("quantities", {
|
|
"meeting_note_field": field_row.name,
|
|
"item": item.get("item"),
|
|
"quantity": item.get("quantity")
|
|
})
|
|
new_bid_meeting_note_doc.save(ignore_permissions=True)
|
|
meeting.bid_notes = new_bid_meeting_note_doc.name
|
|
meeting.status = "Completed"
|
|
meeting.save()
|
|
frappe.db.commit()
|
|
|
|
return build_success_response(meeting.as_dict())
|
|
except frappe.DoesNotExistError:
|
|
return build_error_response(f"On-Site Meeting '{bid_meeting}' does not exist.", 404)
|
|
except Exception as e:
|
|
frappe.log_error(message=str(e), title="Submit Bid Meeting Note Form Failed")
|
|
return build_error_response(str(e), 500)
|
|
|
|
@frappe.whitelist()
|
|
def get_bid_meeting(name):
|
|
"""Get a specific On-Site Meeting by name."""
|
|
try:
|
|
meeting = frappe.get_doc("On-Site Meeting", name)
|
|
meeting_dict = meeting.as_dict()
|
|
|
|
# Get the full address data
|
|
if meeting_dict.get("address"):
|
|
address_doc = AddressService.get_or_throw(meeting_dict["address"])
|
|
meeting_dict["address"] = address_doc.as_dict()
|
|
if meeting_dict.get("contact"):
|
|
contact_doc = ContactService.get_or_throw(meeting_dict["contact"])
|
|
meeting_dict["contact"] = contact_doc.as_dict()
|
|
if meeting_dict.get("bid_notes"):
|
|
bid_meeting_note_doc = frappe.get_doc("Bid Meeting Note", meeting_dict["bid_notes"])
|
|
meeting_dict["bid_notes"] = bid_meeting_note_doc.as_dict()
|
|
|
|
return build_success_response(meeting_dict)
|
|
except frappe.DoesNotExistError:
|
|
return build_error_response(f"On-Site Meeting '{name}' does not exist.", 404)
|
|
except Exception as e:
|
|
frappe.log_error(message=str(e), title="Get On-Site Meeting Failed")
|
|
return build_error_response(str(e), 500)
|
|
|
|
|
|
@frappe.whitelist()
|
|
def create_bid_meeting(data):
|
|
"""Create a new On-Site Meeting with Unscheduled status."""
|
|
if isinstance(data, str):
|
|
data = json.loads(data)
|
|
try:
|
|
print(f"DEBUG: Creating meeting with data='{data}'")
|
|
|
|
address_doc = DbService.get_or_throw("Address", data.get("address"))
|
|
|
|
# Create the meeting with Unscheduled status
|
|
meeting = frappe.get_doc({
|
|
"doctype": "On-Site Meeting",
|
|
"address": address_doc.name,
|
|
"notes": data.get("notes") or "",
|
|
"status": "Unscheduled",
|
|
"company": data.get("company"),
|
|
"contact": data.get("contact"),
|
|
"party_type": address_doc.customer_type,
|
|
"party_name": address_doc.customer_name,
|
|
"project_template": data.get("project_template")
|
|
})
|
|
meeting.insert(ignore_permissions=True)
|
|
# ClientService.append_link(address_doc.customer_name, "onsite_meetings", "onsite_meeting", meeting.name)
|
|
# AddressService.append_link(address_doc.name, "onsite_meetings", "onsite_meeting", meeting.name)
|
|
meeting.flags.ignore_permissions = True
|
|
frappe.db.commit()
|
|
|
|
# Clear any auto-generated messages from Frappe
|
|
frappe.local.message_log = []
|
|
|
|
print(f"DEBUG: Meeting created successfully: {meeting.name}")
|
|
|
|
return build_success_response(meeting.as_dict())
|
|
except Exception as e:
|
|
frappe.log_error(message=str(e), title="Create On-Site Meeting Failed")
|
|
return build_error_response(str(e), 500)
|
|
|
|
@frappe.whitelist()
|
|
def update_bid_meeting(name, data):
|
|
"""Update an existing On-Site Meeting."""
|
|
try:
|
|
if isinstance(data, str):
|
|
data = json.loads(data)
|
|
|
|
meeting = frappe.get_doc("On-Site Meeting", name)
|
|
|
|
# Only update fields that are explicitly provided in the data
|
|
for key, value in data.items():
|
|
print(f"DEBUG: Updating field '{key}' to value '{value}'")
|
|
if key == "address" and value is not None:
|
|
# Convert full address to address name
|
|
value = frappe.db.get_value("Address", {"full_address": value}, "name")
|
|
meeting.set(key, value)
|
|
elif key in ["assigned_employee", "completed_by"] and value is not None:
|
|
# Convert employee name to employee ID
|
|
value = frappe.db.get_value("Employee", {"employee_name": value}, "name")
|
|
meeting.set(key, value)
|
|
else:
|
|
# For all other fields, set the value as-is (including None to clear fields)
|
|
meeting.set(key, value)
|
|
print(f"DEBUG: Field '{key}' updated to '{meeting.get(key)}'")
|
|
meeting.save()
|
|
frappe.db.commit()
|
|
|
|
return build_success_response(meeting.as_dict())
|
|
except frappe.DoesNotExistError:
|
|
return build_error_response(f"On-Site Meeting '{name}' does not exist.", 404)
|
|
except Exception as e:
|
|
return build_error_response(str(e), 500)
|
|
|