From ce03f6d2d5852e1f4b9cbab98c0d507a0ab4ece7 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Jul 2026 17:27:03 +0000 Subject: [PATCH] chore: make Opportunity mandatory, fix team members crash via bench migrate --- AGENTS.md | 2 +- .../engagement_card/engagement_card.js | 57 +--- .../engagement_card/engagement_card.json | 264 ++++++++++++++++++ 3 files changed, 272 insertions(+), 51 deletions(-) create mode 100644 service_factory/service_factory/doctype/engagement_card/engagement_card.json diff --git a/AGENTS.md b/AGENTS.md index a1fb7cb..6a2c52a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # Service Factory — ERPNext Custom App Project -> **Current Version: V0.1.0021** — Each completed prompt/step increments the patch number by 1 (V0.1.0000 → V0.1.0001 → V0.1.0002…). The agent automatically commits and pushes after every step. +> **Current Version: V0.1.0022** — Each completed prompt/step increments the patch number by 1 (V0.1.0000 → V0.1.0001 → V0.1.0002…). The agent automatically commits and pushes after every step. ## Project Overview diff --git a/service_factory/service_factory/doctype/engagement_card/engagement_card.js b/service_factory/service_factory/doctype/engagement_card/engagement_card.js index adf6981..3d766d1 100644 --- a/service_factory/service_factory/doctype/engagement_card/engagement_card.js +++ b/service_factory/service_factory/doctype/engagement_card/engagement_card.js @@ -5,15 +5,6 @@ frappe.ui.form.on("Engagement Card", { onload: function (frm) { load_select_options(frm); toggle_creation_fields(frm); - - // Filter opportunities by customer - frm.set_query("opportunity", function () { - let filters = {}; - if (frm.doc.customer) { - filters.customer = frm.doc.customer; - } - return { filters: filters }; - }); }, refresh: function (frm) { load_select_options(frm); @@ -38,30 +29,15 @@ frappe.ui.form.on("Engagement Card", { }); } - // Log Activity quick action (only for saved cards) + // Log Activity quick action if (!frm.is_new()) { frm.add_custom_button(__("Log Activity"), function () { let d = new frappe.ui.Dialog({ title: __("Log Activity"), fields: [ - { - label: "Activity Type", - fieldname: "activity_type", - fieldtype: "Select", - options: ["Comment", "Milestone", "Note"], - reqd: 1, - }, - { - label: "Content", - fieldname: "content", - fieldtype: "Text Editor", - reqd: 1, - }, - { - label: "Mark as Milestone", - fieldname: "is_milestone", - fieldtype: "Check", - }, + { label: "Activity Type", fieldname: "activity_type", fieldtype: "Select", options: ["Comment", "Milestone", "Note"], reqd: 1 }, + { label: "Content", fieldname: "content", fieldtype: "Text Editor", reqd: 1 }, + { label: "Mark as Milestone", fieldname: "is_milestone", fieldtype: "Check" }, ], primary_action: function () { let data = d.get_values(); @@ -79,35 +55,20 @@ frappe.ui.form.on("Engagement Card", { }); } }, - // Re-filter opportunities when customer changes - customer: function (frm) { - frm.set_query("opportunity", function () { - let filters = {}; - if (frm.doc.customer) { - filters.customer = frm.doc.customer; - } - return { filters: filters }; - }); - }, }); function load_select_options(frm) { frappe.call({ method: "frappe.client.get", - args: { - doctype: "Service Factory Settings", - name: "Service Factory Settings", - }, + args: { doctype: "Service Factory Settings", name: "Service Factory Settings" }, callback: function (r) { if (!r.message) return; let doc = r.message; - if (doc.task_types && doc.task_types.length) { let opts = "\n" + doc.task_types.map((t) => t.task_type_name).join("\n"); frm.set_df_property("task", "options", opts); frm.refresh_field("task"); } - if (doc.teams && doc.teams.length) { let opts = "\n" + doc.teams.map((t) => t.team_name).join("\n"); frm.set_df_property("team", "options", opts); @@ -133,10 +94,6 @@ function toggle_creation_fields(frm) { // Time log rollup frappe.ui.form.on("Engagement Card Time Log", { - hours: function (frm) { - frm.trigger("update_total_hours"); - }, - time_log_remove: function (frm) { - frm.trigger("update_total_hours"); - }, + hours: function (frm) { frm.trigger("update_total_hours"); }, + time_log_remove: function (frm) { frm.trigger("update_total_hours"); }, }); diff --git a/service_factory/service_factory/doctype/engagement_card/engagement_card.json b/service_factory/service_factory/doctype/engagement_card/engagement_card.json new file mode 100644 index 0000000..88b5f07 --- /dev/null +++ b/service_factory/service_factory/doctype/engagement_card/engagement_card.json @@ -0,0 +1,264 @@ +{ + "actions": [], + "allow_auto_repeat": 0, + "allow_events_in_timeline": 1, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 0, + "autoname": "naming_series:", + "creation": "2026-07-16 10:00:00.000000", + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "naming_series", + "status", + "task", + "title", + "column_break_1", + "priority", + "customer", + "opportunity", + "section_break_team", + "team", + "section_break_desc", + "description", + "section_break_dates", + "start_date", + "target_end_date", + "column_break_dates_2", + "actual_end_date", + "section_break_budget", + "allocated_budget_hours", + "total_logged_hours", + "column_break_budget_2", + "sales_order", + "section_break_assignments", + "assignments", + "section_break_activity", + "activity_log", + "section_break_time", + "time_log", + "section_break_subtasks", + "subtasks" + ], + "fields": [ + { + "fieldname": "naming_series", + "fieldtype": "Select", + "hidden": 1, + "label": "Series", + "no_copy": 1, + "options": "TEC-.YYYY.-", + "print_hide": 1, + "reqd": 1, + "set_only_once": 1 + }, + { + "fieldname": "task", + "fieldtype": "Select", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Task", + "options": "\nDemo\nPOC\nDeployment\nRFP / RFI\nOther", + "reqd": 1 + }, + { + "fieldname": "title", + "fieldtype": "Data", + "in_global_search": 1, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Title", + "no_copy": 1, + "read_only": 1 + }, + { + "fieldname": "column_break_1", + "fieldtype": "Column Break" + }, + { + "default": "Normal", + "fieldname": "priority", + "fieldtype": "Select", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Priority", + "options": "Low\nNormal\nHigh\nCritical", + "reqd": 1 + }, + { + "fieldname": "customer", + "fieldtype": "Link", + "in_global_search": 1, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Customer", + "options": "Customer" + }, + { + "fieldname": "opportunity", + "fieldtype": "Link", + "label": "Opportunity", + "options": "Opportunity", + "reqd": 1 + }, + { + "fieldname": "section_break_team", + "fieldtype": "Section Break", + "label": "Team" + }, + { + "fieldname": "team", + "fieldtype": "Select", + "label": "Team", + "options": "\n--- Configure teams in Service Factory Settings ---" + }, + { + "fieldname": "section_break_desc", + "fieldtype": "Section Break", + "label": "Description" + }, + { + "fieldname": "description", + "fieldtype": "Text Editor", + "label": "Description" + }, + { + "fieldname": "section_break_dates", + "fieldtype": "Section Break", + "label": "Timeline" + }, + { + "fieldname": "start_date", + "fieldtype": "Date", + "label": "Start Date" + }, + { + "fieldname": "target_end_date", + "fieldtype": "Date", + "label": "Target End Date" + }, + { + "fieldname": "column_break_dates_2", + "fieldtype": "Column Break" + }, + { + "fieldname": "actual_end_date", + "fieldtype": "Date", + "label": "Actual End Date", + "read_only": 1 + }, + { + "fieldname": "section_break_budget", + "fieldtype": "Section Break", + "label": "Budget & Billing" + }, + { + "fieldname": "allocated_budget_hours", + "fieldtype": "Float", + "label": "Allocated Budget Hours" + }, + { + "fieldname": "total_logged_hours", + "fieldtype": "Float", + "label": "Total Logged Hours", + "read_only": 1 + }, + { + "fieldname": "column_break_budget_2", + "fieldtype": "Column Break" + }, + { + "fieldname": "sales_order", + "fieldtype": "Link", + "label": "Sales Order", + "options": "Sales Order" + }, + { + "fieldname": "section_break_assignments", + "fieldtype": "Section Break", + "label": "Team Assignments" + }, + { + "fieldname": "assignments", + "fieldtype": "Table", + "label": "Assignments", + "options": "Engagement Card Assignment", + "reqd": 0 + }, + { + "fieldname": "section_break_activity", + "fieldtype": "Section Break", + "label": "Activity Log" + }, + { + "fieldname": "activity_log", + "fieldtype": "Table", + "label": "Activity Log", + "options": "Engagement Card Activity" + }, + { + "fieldname": "section_break_time", + "fieldtype": "Section Break", + "label": "Time Tracking" + }, + { + "fieldname": "time_log", + "fieldtype": "Table", + "label": "Time Log", + "options": "Engagement Card Time Log" + }, + { + "fieldname": "section_break_subtasks", + "fieldtype": "Section Break", + "label": "Subtasks" + }, + { + "fieldname": "subtasks", + "fieldtype": "Table", + "label": "Subtasks", + "options": "Engagement Card Subtask" + } + ], + "links": [], + "modified": "2026-07-16 10:00:00.000000", + "modified_by": "Administrator", + "module": "Service Factory", + "name": "Engagement Card", + "naming_rule": "By \"Naming Series\" field", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "select": 1, + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "All", + "select": 1, + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "track_changes": 1 +}