diff --git a/custom_ui/custom_fields.py b/custom_ui/custom_fields.py new file mode 100644 index 0000000..204ba7b --- /dev/null +++ b/custom_ui/custom_fields.py @@ -0,0 +1,566 @@ +custom_fields = { + "Customer": [ + dict( + fieldname="companies", + label="Companies", + fieldtype="Table", + options="Customer Company Link", + insert_after="customer_type" + ), + dict( + fieldname="quotations", + label="Quotations", + fieldtype="Table", + options="Customer Quotation Link", + insert_after="companies" + ), + dict( + fieldname="onsite_meetings", + label="On-Site Meetings", + fieldtype="Table", + options="Customer On-Site Meeting Link", + insert_after="quotations" + ), + dict( + fieldname="projects", + label="Projects", + fieldtype="Table", + options="Customer Project Link", + insert_after="onsite_meetings" + ), + dict( + fieldname="sales_orders", + label="Sales Orders", + fieldtype="Table", + options="Customer Sales Order Link", + insert_after="projects" + ), + dict( + fieldname="from_lead", + label="From Lead", + fieldtype="Link", + options="Lead", + insert_after="customer_name" + ), + dict( + fieldname="properties", + label="Properties", + fieldtype="Table", + options="Customer Address Link", + insert_after="customer_name" + ), + dict( + fieldname="contacts", + label="Contacts", + fieldtype="Table", + options="Customer Contact Link", + insert_after="properties" + ), + dict( + fieldname="primary_contact", + label="Primary Contact", + fieldtype="Link", + options="Contact", + insert_after="contacts" + ), + dict( + fieldname="tasks", + label="Tasks", + fieldtype="Table", + options="Customer Task Link", + insert_after="projects" + ) + ], + "Lead": [ + dict( + fieldname="onsite_meetings", + label="On-Site Meetings", + fieldtype="Table", + options="Lead On-Site Meeting Link", + insert_after="quotations" + ), + dict( + fieldname="custom_billing_address", + label="Custom Address", + fieldtype="Link", + options="Address", + insert_after="customer_name" + ), + dict( + fieldname="quotations", + label="Quotations", + fieldtype="Table", + options="Lead Quotation Link", + insert_after="companies" + ), + dict( + fieldname="companies", + label="Companies", + fieldtype="Table", + options="Lead Company Link", + insert_after="customer_type" + ), + dict( + fieldname="customer_type", + label="Customer Type", + fieldtype="Select", + options="Individual\nCompany\nPartnership", + insert_after="lead_name" + ), + dict( + fieldname="properties", + label="Properties", + fieldtype="Table", + options="Lead Address Link", + insert_after="customer_name" + ), + dict( + fieldname="contacts", + label="Contacts", + fieldtype="Table", + options="Lead Contact Link", + insert_after="properties" + ), + dict( + fieldname="primary_contact", + label="Primary Contact", + fieldtype="Link", + options="Contact", + insert_after="contacts" + ) + ], + "Address": [ + dict( + fieldname="primary_contact", + label="Primary Contact", + fieldtype="Link", + options="Contact", + insert_after="address_title" + ), + dict( + fieldname="projects", + label="Projects", + fieldtype="Table", + options="Address Project Link", + insert_after="onsite_meetings" + ), + dict( + fieldname="sales_orders", + label="Sales Orders", + fieldtype="Table", + options="Address Sales Order Link", + insert_after="projects" + ), + dict( + fieldname="onsite_meetings", + label="On-Site Meetings", + fieldtype="Table", + options="Address On-Site Meeting Link", + insert_after="quotations" + ), + dict( + fieldname="quotations", + label="Quotations", + fieldtype="Table", + options="Address Quotation Link", + insert_after="companies" + ), + 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" + ), + dict( + fieldname="lead_name", + label="Lead Name", + fieldtype="Data", + insert_after="custom_customer_to_bill" + ), + dict( + fieldname="customer_type", + label="Customer Type", + fieldtype="Select", + options="Customer\nLead", + insert_after="lead_name" + ), + dict( + fieldname="customer_name", + label="Customer Name", + fieldtype="Dynamic Link", + options="customer_type", + insert_after="customer_type" + ), + dict( + fieldname="contacts", + label="Contacts", + fieldtype="Table", + options="Address Contact Link", + insert_after="customer_name" + ), + dict( + fieldname="companies", + label="Companies", + fieldtype="Table", + options="Address Company Link", + insert_after="contacts" + ), + dict( + fieldname="tasks", + label="Tasks", + fieldtype="Table", + options="Address Task Link", + insert_after="projects" + ), + dict( + fieldname="custom_subdivision", + label="Subdivision", + fieldtype="Link", + options="Territory", + insert_after="address_line2" + ), + dict( + fieldname="custom_customer_to_bill", + label="Customer To Bill", + fieldtype="Link", + options="Customer", + insert_after="custom_subdivision" + ) + ], + "Contact": [ + dict( + fieldname="role", + label="Role", + fieldtype="Select", + options="Owner\nProperty Manager\nTenant\nBuilder\nNeighbor\nFamily Member\nRealtor\nOther", + insert_after="designation" + ), + dict( + fieldname="email", + label="Email", + fieldtype="Data", + insert_after="last_name", + options="Email" + ), + dict( + fieldname="customer_type", + label="Customer Type", + fieldtype="Select", + options="Customer\nLead", + insert_after="email" + ), + dict( + fieldname="customer_name", + label="Customer Name", + fieldtype="Dynamic Link", + options="customer_type", + insert_after="customer_type" + ), + dict( + fieldname="addresses", + label="Addresses", + fieldtype="Table", + options="Contact Address Link", + insert_after="customer_name" + ) + ], + "On-Site Meeting": [ + dict( + fieldname="notes", + label="Notes", + fieldtype="Small Text", + insert_after="address" + ), + dict( + fieldname="assigned_employee", + label="Assigned Employee", + fieldtype="Link", + options="Employee", + insert_after="notes" + ), + dict( + fieldname="status", + label="Status", + fieldtype="Select", + options="Unscheduled\nScheduled\nCompleted\nCancelled", + default="Unscheduled", + insert_after="start_time" + ), + dict( + fieldname="completed_by", + label="Completed By", + fieldtype="Link", + options="Employee", + insert_after="status" + ), + dict( + fieldname="company", + label="Company", + fieldtype="Link", + options="Company", + insert_after="assigned_employee" + ), + dict( + fieldname="party_type", + label="Party Type", + fieldtype="Select", + options="Customer\nLead", + insert_after="company" + ), + dict( + fieldname="party_name", + label="Party Name", + fieldtype="Dynamic Link", + options="party_type", + insert_after="party_type" + ), + dict( + fieldname="contact", + label="Contact", + fieldtype="Link", + options="Contact", + insert_after="party_name" + ), + dict( + fieldname="project_template", + label="Project Template", + fieldtype="Link", + options="Project Template", + insert_after="company" + ) + ], + "Quotation": [ + dict( + fieldname="requires_half_payment", + label="Requires Half Payment", + fieldtype="Check", + default=0, + insert_after="custom_installation_address" + ), + dict( + fieldname="custom_quotation_template", + label="Quotation Template", + fieldtype="Link", + options="Quotation Template", + insert_after="company", + description="The template used for generating this quotation." + ), + dict( + fieldname="custom_project_template", + label="Project Template", + fieldtype="Link", + options="Project Template", + insert_after="custom_quotation_template", + description="The project template to use when creating a project from this quotation.", + allow_on_submit=1 + ), + dict( + fieldname="custom_job_address", + label="Job Address", + fieldtype="Link", + options="Address", + insert_after="custom_installation_address", + description="The address where the job will be performed.", + allow_on_submit=1 + ), + dict( + fieldname="from_onsite_meeting", + label="From On-Site Meeting", + fieldtype="Link", + options="On-Site Meeting", + insert_after="custom_job_address" + ), + dict( + fieldname="from_onsite_meeting", + label="From On-Site Meeting", + fieldtype="Link", + options="On-Site Meeting", + insert_after="custom_job_address" + ), + dict( + fieldname="actual_customer_name", + label="Customer", + fieldtype="Dynamic Link", + options="customer_type", + insert_after="from_onsite_meeting", + allow_on_submit=1 + ), + dict( + fieldname="customer_type", + label="Customer Type", + fieldtype="Select", + options="Customer\nLead", + insert_after="customer_name", + allow_on_submit=1 + ) + ], + "Sales Order": [ + dict( + fieldname="requires_half_payment", + label="Requires Half Payment", + fieldtype="Check", + default=0, + insert_after="custom_installation_address" + ), + dict( + fieldname="custom_project_template", + label="Project Template", + fieldtype="Link", + options="Project Template", + description="The project template to use when creating a project from this sales order.", + insert_after="custom_installation_address", + allow_on_submit=1 + ), + dict( + fieldname="custom_job_address", + label="Job Address", + fieldtype="Link", + options="Address", + insert_after="custom_installation_address", + description="The address where the job will be performed.", + allow_on_submit=1 + ) + ], + "Project": [ + dict( + fieldname="job_address", + label="Job Address", + fieldtype="Link", + options="Address", + insert_after="project_name", + description="The address where the job is being performed." + ), + dict( + fieldname="customer", + label="Customer", + fieldtype="Link", + options="Customer", + insert_after="job_address", + description="The customer for whom the project is being executed." + ), + dict( + fieldname="expected_start_time", + label="Expected Start Time", + fieldtype="Time", + insert_after="expected_start_date" + ), + dict( + fieldname="expected_end_time", + label="Expected End Time", + fieldtype="Time", + insert_after="expected_end_date" + ), + dict( + fieldname="actual_start_time", + label="Actual Start Time", + fieldtype="Time", + insert_after="actual_start_date" + ), + dict( + fieldname="actual_end_time", + label="Actual End Time", + fieldtype="Time", + insert_after="actual_end_date" + ), + dict( + fieldname="is_scheduled", + label="Is Scheduled", + fieldtype="Check", + default=0, + insert_after="is_half_down_paid" + ), + dict( + fieldname="invoice_status", + label="Invoice Status", + fieldtype="Select", + default="Not Ready", + options="Not Ready\nReady to Invoice\nInvoice Created\nInvoice Sent", + insert_after="is_scheduled" + ), + dict( + fieldname="requires_half_payment", + label="Requires Half Payment", + fieldtype="Check", + default=0, + insert_after="expected_end_time" + ), + dict( + fieldname="is_half_down_paid", + label="Is Half Down Paid", + fieldtype="Check", + default=0, + insert_after="requires_half_payment" + ), + ], + "Project Template": [ + dict( + fieldname="company", + label="Company", + fieldtype="Link", + options="Company", + insert_after="project_type", + description="The company associated with this project template." + ), + dict( + fieldname="calendar_color", + label="Calendar Color", + fieldtype="Color", + insert_after="company" + ) + ], + "Task": [ + dict( + fieldname="project_template", + label="Project Template", + fieldtype="Link", + options="Project Template", + insert_after="project" + ) + ] +} diff --git a/custom_ui/custom_ui/doctype/address_task_link/__init__.py b/custom_ui/custom_ui/doctype/address_task_link/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/address_task_link/address_task_link.json b/custom_ui/custom_ui/doctype/address_task_link/address_task_link.json new file mode 100644 index 0000000..cddc085 --- /dev/null +++ b/custom_ui/custom_ui/doctype/address_task_link/address_task_link.json @@ -0,0 +1,43 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:21:48.230423", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "task", + "project_template" + ], + "fields": [ + { + "fieldname": "task", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Task", + "options": "Task", + "reqd": 1 + }, + { + "fieldname": "project_template", + "fieldtype": "Link", + "label": "Project Template", + "options": "Project Template" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2026-01-30 07:52:45.496993", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Address Task Link", + "owner": "Administrator", + "permissions": [], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/address_task_link/address_task_link.py b/custom_ui/custom_ui/doctype/address_task_link/address_task_link.py new file mode 100644 index 0000000..1e743b6 --- /dev/null +++ b/custom_ui/custom_ui/doctype/address_task_link/address_task_link.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class AddressTaskLink(Document): + pass diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_field/__init__.py b/custom_ui/custom_ui/doctype/bid_meeting_note_field/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_field/bid_meeting_note_field.json b/custom_ui/custom_ui/doctype/bid_meeting_note_field/bid_meeting_note_field.json new file mode 100644 index 0000000..fcf353d --- /dev/null +++ b/custom_ui/custom_ui/doctype/bid_meeting_note_field/bid_meeting_note_field.json @@ -0,0 +1,108 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:21:50.095868", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "label", + "type", + "value", + "order", + "value_doctype", + "available_options", + "include_available_options", + "row", + "column", + "conditional_on_field", + "conditional_on_value", + "doctype_label_field" + ], + "fields": [ + { + "fieldname": "label", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Label", + "reqd": 1 + }, + { + "fieldname": "type", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Type", + "options": "Data\nText\nCheck\nDate\nDatetime\nTime\nSelect\nMulti-Select\nMulti-Select w/ Quantity", + "reqd": 1 + }, + { + "fieldname": "value", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Value", + "reqd": 1 + }, + { + "fieldname": "order", + "fieldtype": "Int", + "label": "Order" + }, + { + "description": "Holds the doctype if this field is a link to either a single doctype or a list of doctypes. If this field has a value, then the Value field will hold the name(s) of the Doctype(s)", + "fieldname": "value_doctype", + "fieldtype": "Data", + "label": "Doctype" + }, + { + "fieldname": "available_options", + "fieldtype": "Small Text", + "label": "Available Options" + }, + { + "default": "0", + "fieldname": "include_available_options", + "fieldtype": "Check", + "label": "Include Available Options" + }, + { + "fieldname": "row", + "fieldtype": "Int", + "label": "Row" + }, + { + "fieldname": "column", + "fieldtype": "Int", + "label": "Column" + }, + { + "fieldname": "conditional_on_field", + "fieldtype": "Data", + "label": "Conditional On Field" + }, + { + "fieldname": "conditional_on_value", + "fieldtype": "Data", + "label": "Conditional On Value" + }, + { + "fieldname": "doctype_label_field", + "fieldtype": "Data", + "label": "Doctype Label Field" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2026-01-30 07:52:08.063602", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Bid Meeting Note Field", + "owner": "Administrator", + "permissions": [], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_field/bid_meeting_note_field.py b/custom_ui/custom_ui/doctype/bid_meeting_note_field/bid_meeting_note_field.py new file mode 100644 index 0000000..6550ba9 --- /dev/null +++ b/custom_ui/custom_ui/doctype/bid_meeting_note_field/bid_meeting_note_field.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class BidMeetingNoteField(Document): + pass diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_field_quantity/__init__.py b/custom_ui/custom_ui/doctype/bid_meeting_note_field_quantity/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_field_quantity/bid_meeting_note_field_quantity.json b/custom_ui/custom_ui/doctype/bid_meeting_note_field_quantity/bid_meeting_note_field_quantity.json new file mode 100644 index 0000000..7d35865 --- /dev/null +++ b/custom_ui/custom_ui/doctype/bid_meeting_note_field_quantity/bid_meeting_note_field_quantity.json @@ -0,0 +1,50 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:21:50.423957", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "quantity", + "meeting_note_field", + "item" + ], + "fields": [ + { + "fieldname": "quantity", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Quantity", + "reqd": 1 + }, + { + "fieldname": "meeting_note_field", + "fieldtype": "Link", + "label": "Meeting Note Field", + "options": "Bid Meeting Note Field", + "reqd": 1 + }, + { + "fieldname": "item", + "fieldtype": "Data", + "label": "Item", + "reqd": 1 + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2026-01-30 07:51:49.006161", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Bid Meeting Note Field Quantity", + "owner": "Administrator", + "permissions": [], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_field_quantity/bid_meeting_note_field_quantity.py b/custom_ui/custom_ui/doctype/bid_meeting_note_field_quantity/bid_meeting_note_field_quantity.py new file mode 100644 index 0000000..aa8a7f5 --- /dev/null +++ b/custom_ui/custom_ui/doctype/bid_meeting_note_field_quantity/bid_meeting_note_field_quantity.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class BidMeetingNoteFieldQuantity(Document): + pass diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_form/__init__.py b/custom_ui/custom_ui/doctype/bid_meeting_note_form/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_form/bid_meeting_note_form.js b/custom_ui/custom_ui/doctype/bid_meeting_note_form/bid_meeting_note_form.js new file mode 100644 index 0000000..f37f2fb --- /dev/null +++ b/custom_ui/custom_ui/doctype/bid_meeting_note_form/bid_meeting_note_form.js @@ -0,0 +1,8 @@ +// Copyright (c) 2026, Shiloh Code LLC and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Bid Meeting Note Form", { +// refresh(frm) { + +// }, +// }); diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_form/bid_meeting_note_form.json b/custom_ui/custom_ui/doctype/bid_meeting_note_form/bid_meeting_note_form.json new file mode 100644 index 0000000..23443a0 --- /dev/null +++ b/custom_ui/custom_ui/doctype/bid_meeting_note_form/bid_meeting_note_form.json @@ -0,0 +1,76 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:01:57.052796", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "title", + "project_template", + "notes", + "fields", + "company" + ], + "fields": [ + { + "fieldname": "title", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Title", + "reqd": 1 + }, + { + "fieldname": "project_template", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Project Template", + "options": "Project Template", + "reqd": 1 + }, + { + "fieldname": "notes", + "fieldtype": "Small Text", + "label": "Notes" + }, + { + "fieldname": "fields", + "fieldtype": "Table", + "label": "Fields", + "options": "Bid Meeting Note Form Field", + "reqd": 1 + }, + { + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "links": [], + "modified": "2026-01-30 07:17:51.934698", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Bid Meeting Note Form", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_form/bid_meeting_note_form.py b/custom_ui/custom_ui/doctype/bid_meeting_note_form/bid_meeting_note_form.py new file mode 100644 index 0000000..e1015a9 --- /dev/null +++ b/custom_ui/custom_ui/doctype/bid_meeting_note_form/bid_meeting_note_form.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class BidMeetingNoteForm(Document): + pass diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_form/test_bid_meeting_note_form.py b/custom_ui/custom_ui/doctype/bid_meeting_note_form/test_bid_meeting_note_form.py new file mode 100644 index 0000000..d1e341c --- /dev/null +++ b/custom_ui/custom_ui/doctype/bid_meeting_note_form/test_bid_meeting_note_form.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestBidMeetingNoteForm(FrappeTestCase): + pass diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_form_field/__init__.py b/custom_ui/custom_ui/doctype/bid_meeting_note_form_field/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_form_field/bid_meeting_note_form_field.json b/custom_ui/custom_ui/doctype/bid_meeting_note_form_field/bid_meeting_note_form_field.json new file mode 100644 index 0000000..ab9a536 --- /dev/null +++ b/custom_ui/custom_ui/doctype/bid_meeting_note_form_field/bid_meeting_note_form_field.json @@ -0,0 +1,149 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:21:49.918704", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "label", + "type", + "options", + "required", + "default_value", + "read_only", + "order", + "help_text", + "doctype_for_select", + "include_options", + "conditional_on_field", + "conditional_on_value", + "doctype_label_field", + "row", + "column" + ], + "fields": [ + { + "fieldname": "label", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Label", + "reqd": 1 + }, + { + "fieldname": "type", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Type", + "options": "Data\nText\nCheck\nDate\nDatetime\nTime\nSelect\nMulti-Select\nNumber\nMulti-Select w/ Quantity", + "reqd": 1 + }, + { + "allow_in_quick_entry": 1, + "description": "Comma separated options for select fields", + "fieldname": "options", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Options" + }, + { + "allow_in_quick_entry": 1, + "default": "0", + "fieldname": "required", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Required" + }, + { + "allow_in_quick_entry": 1, + "fieldname": "default_value", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Default Value" + }, + { + "allow_in_quick_entry": 1, + "default": "0", + "fieldname": "read_only", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Read Only" + }, + { + "allow_in_quick_entry": 1, + "fieldname": "order", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Order" + }, + { + "allow_in_quick_entry": 1, + "fieldname": "help_text", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Help Text" + }, + { + "allow_in_quick_entry": 1, + "description": "The doctype for a select or multi-select if it's options are doctypes.", + "fieldname": "doctype_for_select", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Doctype For Select" + }, + { + "default": "0", + "fieldname": "include_options", + "fieldtype": "Check", + "label": "Include Options" + }, + { + "description": "If a value is entered in this field, then the field this describes is conditional based on the value in the provided field. ", + "fieldname": "conditional_on_field", + "fieldtype": "Data", + "label": "Conditional On Field" + }, + { + "description": "The value in which conditional should evaluate to True. If no value is provided here and a value exists in Conditional On Field, then the condition will just simply be if \"truthy\" (meaning, not null, emtpy, false, or 0)", + "fieldname": "conditional_on_value", + "fieldtype": "Data", + "label": "Conditional On Value" + }, + { + "allow_in_quick_entry": 1, + "fieldname": "doctype_label_field", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Doctype Label Field" + }, + { + "allow_in_quick_entry": 1, + "fieldname": "row", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Row" + }, + { + "allow_in_quick_entry": 1, + "fieldname": "column", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Column" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2026-01-30 07:52:16.305665", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Bid Meeting Note Form Field", + "owner": "Administrator", + "permissions": [], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/bid_meeting_note_form_field/bid_meeting_note_form_field.py b/custom_ui/custom_ui/doctype/bid_meeting_note_form_field/bid_meeting_note_form_field.py new file mode 100644 index 0000000..c918765 --- /dev/null +++ b/custom_ui/custom_ui/doctype/bid_meeting_note_form_field/bid_meeting_note_form_field.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class BidMeetingNoteFormField(Document): + pass diff --git a/custom_ui/custom_ui/doctype/condition/__init__.py b/custom_ui/custom_ui/doctype/condition/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/condition/condition.js b/custom_ui/custom_ui/doctype/condition/condition.js new file mode 100644 index 0000000..aa4607b --- /dev/null +++ b/custom_ui/custom_ui/doctype/condition/condition.js @@ -0,0 +1,8 @@ +// Copyright (c) 2026, Shiloh Code LLC and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Condition", { +// refresh(frm) { + +// }, +// }); diff --git a/custom_ui/custom_ui/doctype/condition/condition.json b/custom_ui/custom_ui/doctype/condition/condition.json new file mode 100644 index 0000000..bb10d4f --- /dev/null +++ b/custom_ui/custom_ui/doctype/condition/condition.json @@ -0,0 +1,43 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:01:57.401662", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "section_break_thqn" + ], + "fields": [ + { + "fieldname": "section_break_thqn", + "fieldtype": "Section Break" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "links": [], + "modified": "2026-01-30 07:16:50.657332", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Condition", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/condition/condition.py b/custom_ui/custom_ui/doctype/condition/condition.py new file mode 100644 index 0000000..7344fbb --- /dev/null +++ b/custom_ui/custom_ui/doctype/condition/condition.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class Condition(Document): + pass diff --git a/custom_ui/custom_ui/doctype/condition/test_condition.py b/custom_ui/custom_ui/doctype/condition/test_condition.py new file mode 100644 index 0000000..42ef290 --- /dev/null +++ b/custom_ui/custom_ui/doctype/condition/test_condition.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestCondition(FrappeTestCase): + pass diff --git a/custom_ui/custom_ui/doctype/customer_address_link/__init__.py b/custom_ui/custom_ui/doctype/customer_address_link/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/customer_address_link/customer_address_link.json b/custom_ui/custom_ui/doctype/customer_address_link/customer_address_link.json new file mode 100644 index 0000000..31ded93 --- /dev/null +++ b/custom_ui/custom_ui/doctype/customer_address_link/customer_address_link.json @@ -0,0 +1,34 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:21:48.972109", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "address" + ], + "fields": [ + { + "fieldname": "address", + "fieldtype": "Link", + "label": "Address", + "options": "Address" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2026-01-30 07:52:31.110075", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Customer Address Link", + "owner": "Administrator", + "permissions": [], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/customer_address_link/customer_address_link.py b/custom_ui/custom_ui/doctype/customer_address_link/customer_address_link.py new file mode 100644 index 0000000..050ae7c --- /dev/null +++ b/custom_ui/custom_ui/doctype/customer_address_link/customer_address_link.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class CustomerAddressLink(Document): + pass diff --git a/custom_ui/custom_ui/doctype/customer_company_link/__init__.py b/custom_ui/custom_ui/doctype/customer_company_link/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/customer_company_link/customer_company_link.json b/custom_ui/custom_ui/doctype/customer_company_link/customer_company_link.json new file mode 100644 index 0000000..7c91601 --- /dev/null +++ b/custom_ui/custom_ui/doctype/customer_company_link/customer_company_link.json @@ -0,0 +1,32 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:21:48.896768", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "section_break_flvp" + ], + "fields": [ + { + "fieldname": "section_break_flvp", + "fieldtype": "Section Break" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2026-01-30 07:52:38.531992", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Customer Company Link", + "owner": "Administrator", + "permissions": [], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/customer_company_link/customer_company_link.py b/custom_ui/custom_ui/doctype/customer_company_link/customer_company_link.py new file mode 100644 index 0000000..b40b143 --- /dev/null +++ b/custom_ui/custom_ui/doctype/customer_company_link/customer_company_link.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class CustomerCompanyLink(Document): + pass diff --git a/custom_ui/custom_ui/doctype/customer_contact_link/__init__.py b/custom_ui/custom_ui/doctype/customer_contact_link/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/customer_contact_link/customer_contact_link.json b/custom_ui/custom_ui/doctype/customer_contact_link/customer_contact_link.json new file mode 100644 index 0000000..4299c50 --- /dev/null +++ b/custom_ui/custom_ui/doctype/customer_contact_link/customer_contact_link.json @@ -0,0 +1,34 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:21:49.052039", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "contact" + ], + "fields": [ + { + "fieldname": "contact", + "fieldtype": "Link", + "label": "Contact", + "options": "Contact" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2026-01-30 07:52:24.170798", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Customer Contact Link", + "owner": "Administrator", + "permissions": [], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/customer_contact_link/customer_contact_link.py b/custom_ui/custom_ui/doctype/customer_contact_link/customer_contact_link.py new file mode 100644 index 0000000..5006e32 --- /dev/null +++ b/custom_ui/custom_ui/doctype/customer_contact_link/customer_contact_link.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class CustomerContactLink(Document): + pass diff --git a/custom_ui/custom_ui/doctype/customer_task_link/__init__.py b/custom_ui/custom_ui/doctype/customer_task_link/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/customer_task_link/customer_task_link.json b/custom_ui/custom_ui/doctype/customer_task_link/customer_task_link.json new file mode 100644 index 0000000..37263a4 --- /dev/null +++ b/custom_ui/custom_ui/doctype/customer_task_link/customer_task_link.json @@ -0,0 +1,43 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:21:48.120856", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "task", + "project_template" + ], + "fields": [ + { + "fieldname": "task", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Task", + "options": "Task", + "reqd": 1 + }, + { + "fieldname": "project_template", + "fieldtype": "Link", + "label": "Project Template", + "options": "Project Template" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2026-01-30 07:52:52.271939", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Customer Task Link", + "owner": "Administrator", + "permissions": [], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/customer_task_link/customer_task_link.py b/custom_ui/custom_ui/doctype/customer_task_link/customer_task_link.py new file mode 100644 index 0000000..1747fab --- /dev/null +++ b/custom_ui/custom_ui/doctype/customer_task_link/customer_task_link.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class CustomerTaskLink(Document): + pass diff --git a/custom_ui/custom_ui/doctype/on_site_meeting/__init__.py b/custom_ui/custom_ui/doctype/on_site_meeting/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/on_site_meeting/on_site_meeting.js b/custom_ui/custom_ui/doctype/on_site_meeting/on_site_meeting.js new file mode 100644 index 0000000..f9c4448 --- /dev/null +++ b/custom_ui/custom_ui/doctype/on_site_meeting/on_site_meeting.js @@ -0,0 +1,8 @@ +// Copyright (c) 2026, Shiloh Code LLC and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("On-Site Meeting", { +// refresh(frm) { + +// }, +// }); diff --git a/custom_ui/custom_ui/doctype/on_site_meeting/on_site_meeting.json b/custom_ui/custom_ui/doctype/on_site_meeting/on_site_meeting.json new file mode 100644 index 0000000..798104d --- /dev/null +++ b/custom_ui/custom_ui/doctype/on_site_meeting/on_site_meeting.json @@ -0,0 +1,68 @@ +{ + "actions": [], + "allow_rename": 1, + "autoname": "format:{address}-{#####}", + "creation": "2026-01-30 05:04:20.781088", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "address", + "start_time", + "end_time", + "bid_notes" + ], + "fields": [ + { + "fieldname": "address", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Address", + "options": "Address", + "reqd": 1 + }, + { + "fieldname": "start_time", + "fieldtype": "Datetime", + "in_list_view": 1, + "label": "Start Time" + }, + { + "fieldname": "end_time", + "fieldtype": "Datetime", + "label": "End Time" + }, + { + "fieldname": "bid_notes", + "fieldtype": "Link", + "label": "Bid Notes", + "options": "Bid Meeting Note" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "links": [], + "modified": "2026-01-30 07:03:40.962554", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "On-Site Meeting", + "naming_rule": "Expression", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "row_format": "Dynamic", + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/on_site_meeting/on_site_meeting.py b/custom_ui/custom_ui/doctype/on_site_meeting/on_site_meeting.py new file mode 100644 index 0000000..66a3ba1 --- /dev/null +++ b/custom_ui/custom_ui/doctype/on_site_meeting/on_site_meeting.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class OnSiteMeeting(Document): + pass diff --git a/custom_ui/custom_ui/doctype/on_site_meeting/test_on_site_meeting.py b/custom_ui/custom_ui/doctype/on_site_meeting/test_on_site_meeting.py new file mode 100644 index 0000000..240abac --- /dev/null +++ b/custom_ui/custom_ui/doctype/on_site_meeting/test_on_site_meeting.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestOnSiteMeeting(FrappeTestCase): + pass diff --git a/custom_ui/custom_ui/doctype/project_task_link/__init__.py b/custom_ui/custom_ui/doctype/project_task_link/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/project_task_link/project_task_link.json b/custom_ui/custom_ui/doctype/project_task_link/project_task_link.json new file mode 100644 index 0000000..14a618a --- /dev/null +++ b/custom_ui/custom_ui/doctype/project_task_link/project_task_link.json @@ -0,0 +1,36 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:21:50.267662", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "task" + ], + "fields": [ + { + "fieldname": "task", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Task", + "options": "Task", + "reqd": 1 + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2026-01-30 07:51:59.777431", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Project Task Link", + "owner": "Administrator", + "permissions": [], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/project_task_link/project_task_link.py b/custom_ui/custom_ui/doctype/project_task_link/project_task_link.py new file mode 100644 index 0000000..c7c35ae --- /dev/null +++ b/custom_ui/custom_ui/doctype/project_task_link/project_task_link.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class ProjectTaskLink(Document): + pass diff --git a/custom_ui/custom_ui/doctype/service_address_2/__init__.py b/custom_ui/custom_ui/doctype/service_address_2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/custom_ui/doctype/service_address_2/service_address_2.js b/custom_ui/custom_ui/doctype/service_address_2/service_address_2.js new file mode 100644 index 0000000..733839d --- /dev/null +++ b/custom_ui/custom_ui/doctype/service_address_2/service_address_2.js @@ -0,0 +1,8 @@ +// Copyright (c) 2026, Shiloh Code LLC and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Service Address 2", { +// refresh(frm) { + +// }, +// }); diff --git a/custom_ui/custom_ui/doctype/service_address_2/service_address_2.json b/custom_ui/custom_ui/doctype/service_address_2/service_address_2.json new file mode 100644 index 0000000..436e2b0 --- /dev/null +++ b/custom_ui/custom_ui/doctype/service_address_2/service_address_2.json @@ -0,0 +1,145 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2026-01-30 07:01:57.571003", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "expected_end_date", + "expected_end_time", + "actual_end_date", + "actual_end_time", + "project_template", + "project", + "status", + "expected_start_date", + "expected_start_time", + "actual_start_date", + "actual_start_time", + "customer", + "company", + "service_address", + "foreman" + ], + "fields": [ + { + "fieldname": "expected_end_date", + "fieldtype": "Date", + "label": "Expected End Date" + }, + { + "fieldname": "expected_end_time", + "fieldtype": "Time", + "label": "Expected End Time" + }, + { + "fieldname": "actual_end_date", + "fieldtype": "Date", + "label": "Actual End Date" + }, + { + "fieldname": "actual_end_time", + "fieldtype": "Time", + "label": "Actual End Time" + }, + { + "fieldname": "project_template", + "fieldtype": "Link", + "label": "Project Template", + "options": "Project Template" + }, + { + "fieldname": "project", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Project", + "options": "Project", + "reqd": 1 + }, + { + "default": "Open", + "fieldname": "status", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Status", + "options": "Open\nScheduled\nStarted\nCompleted\nCanceled", + "reqd": 1 + }, + { + "fieldname": "expected_start_date", + "fieldtype": "Date", + "label": "Expected Start Date" + }, + { + "fieldname": "expected_start_time", + "fieldtype": "Time", + "label": "Expected Start Time" + }, + { + "fieldname": "actual_start_date", + "fieldtype": "Date", + "label": "Actual Start Date" + }, + { + "fieldname": "actual_start_time", + "fieldtype": "Time", + "label": "Actual Start Time" + }, + { + "fieldname": "customer", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Customer", + "options": "Customer", + "reqd": 1 + }, + { + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "options": "Company", + "reqd": 1 + }, + { + "fieldname": "service_address", + "fieldtype": "Link", + "label": "Service Address", + "options": "Address", + "reqd": 1 + }, + { + "fieldname": "foreman", + "fieldtype": "Link", + "label": "Foreman", + "options": "Employee" + } + ], + "grid_page_length": 50, + "index_web_pages_for_search": 1, + "links": [], + "modified": "2026-01-30 07:15:39.410145", + "modified_by": "Administrator", + "module": "Custom UI", + "name": "Service Address 2", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "row_format": "Dynamic", + "rows_threshold_for_grid_search": 20, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/custom_ui/custom_ui/doctype/service_address_2/service_address_2.py b/custom_ui/custom_ui/doctype/service_address_2/service_address_2.py new file mode 100644 index 0000000..8411c3a --- /dev/null +++ b/custom_ui/custom_ui/doctype/service_address_2/service_address_2.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class ServiceAddress2(Document): + pass diff --git a/custom_ui/custom_ui/doctype/service_address_2/test_service_address_2.py b/custom_ui/custom_ui/doctype/service_address_2/test_service_address_2.py new file mode 100644 index 0000000..8c60c43 --- /dev/null +++ b/custom_ui/custom_ui/doctype/service_address_2/test_service_address_2.py @@ -0,0 +1,9 @@ +# Copyright (c) 2026, Shiloh Code LLC and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestServiceAddress2(FrappeTestCase): + pass diff --git a/custom_ui/hooks.py b/custom_ui/hooks.py index e82f612..285e9b0 100644 --- a/custom_ui/hooks.py +++ b/custom_ui/hooks.py @@ -9,6 +9,7 @@ app_license = "mit" after_install = "custom_ui.install.after_install" after_migrate = "custom_ui.install.after_migrate" +after_uninstall = "custom_ui.install.after_uninstall" # on_session_creation = "custom_ui.utils.on_login_redirect" # on_login = "custom_ui.utils.on_login_redirect" page_js = { @@ -223,11 +224,10 @@ def remove_fencing_job_queue_links(doc): fixtures = [ - # {"dt": "Company"}, - # {"dt": "Account"}, - # {"dt": "Cost Center"}, - # {"dt": "Warehouse"}, - # {"dt": "Fiscal Year"}, + { + "dt": "Custom Field", + "filters": [["module", "in", ["Custom UI"]]] + }, { "dt": "Email Template", "filters": [ @@ -258,10 +258,6 @@ fixtures = [ {"dt": "Property Setter"}, {"dt": "Client Script"}, {"dt": "Server Script"}, - # {"dt": "Report"}, - # {"dt": "Print Format"}, - # {"dt": "Dashboard"}, - # {"dt": "Workspace"}, ] diff --git a/custom_ui/install.py b/custom_ui/install.py index f174979..ddd7fc1 100644 --- a/custom_ui/install.py +++ b/custom_ui/install.py @@ -87,7 +87,19 @@ def build_frontend(): frappe.log_error(message=str(e), title="Frontend Build Failed") print(f"\n❌ Frontend build failed: {e}\n") -def add_custom_fields(): + +def remove_custom_fields(custom_fields): + for doctype, fields_list in custom_fields.items(): + for field in fields_list: + name = f"{doctype}-{field['fieldname']}" + if frappe.db.exists("Custom Field", name): + frappe.delete_doc("Custom Field", name) + frappe.db.commit() + print(f"Deleted {name}") + print("Deleted custom fields from database") + + +def add_custom_fields(custom_fields): from frappe.custom.doctype.custom_field.custom_field import create_custom_fields print("\n🔧 Adding custom fields to doctypes...")