diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
index 6100756a6a..ceb4406170 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
+++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
@@ -117,7 +117,7 @@ class MaintenanceSchedule(TransactionBase):
self.update_amc_date(serial_nos, d.end_date)
no_email_sp = []
- if d.sales_person not in email_map:
+ if d.sales_person and d.sales_person not in email_map:
sp = frappe.get_doc("Sales Person", d.sales_person)
try:
email_map[d.sales_person] = sp.get_email_id()
@@ -131,12 +131,11 @@ class MaintenanceSchedule(TransactionBase):
).format(self.owner, "
" + "
".join(no_email_sp))
)
- scheduled_date = frappe.db.sql(
- """select scheduled_date from
- `tabMaintenance Schedule Detail` where sales_person=%s and item_code=%s and
- parent=%s""",
- (d.sales_person, d.item_code, self.name),
- as_dict=1,
+ scheduled_date = frappe.db.get_all(
+ "Maintenance Schedule Detail",
+ {"parent": self.name, "item_code": d.item_code},
+ ["scheduled_date"],
+ as_list=False,
)
for key in scheduled_date:
@@ -232,8 +231,6 @@ class MaintenanceSchedule(TransactionBase):
throw(_("Please select Start Date and End Date for Item {0}").format(d.item_code))
elif not d.no_of_visits:
throw(_("Please mention no of visits required"))
- elif not d.sales_person:
- throw(_("Please select a Sales Person for item: {0}").format(d.item_name))
if getdate(d.start_date) >= getdate(d.end_date):
throw(_("Start date should be less than end date for Item {0}").format(d.item_code))
@@ -452,20 +449,28 @@ def get_serial_nos_from_schedule(item_code, schedule=None):
def make_maintenance_visit(source_name, target_doc=None, item_name=None, s_id=None):
from frappe.model.mapper import get_mapped_doc
+ def condition(doc):
+ if s_id:
+ return doc.name == s_id
+ elif item_name:
+ return doc.item_name == item_name
+
+ return True
+
def update_status_and_detail(source, target, parent):
target.maintenance_type = "Scheduled"
- target.maintenance_schedule_detail = s_id
def update_serial(source, target, parent):
- if source.serial_and_batch_bundle:
- serial_nos = frappe.get_doc(
- "Serial and Batch Bundle", source.serial_and_batch_bundle
- ).get_serial_nos()
+ if source.item_reference:
+ if sbb := frappe.db.get_value(
+ "Maintenance Schedule Item", source.item_reference, "serial_and_batch_bundle"
+ ):
+ serial_nos = frappe.get_doc("Serial and Batch Bundle", sbb).get_serial_nos()
- if len(serial_nos) == 1:
- target.serial_no = serial_nos[0]
- else:
- target.serial_no = ""
+ if len(serial_nos) == 1:
+ target.serial_no = serial_nos[0]
+ else:
+ target.serial_no = ""
doclist = get_mapped_doc(
"Maintenance Schedule",
@@ -477,10 +482,13 @@ def make_maintenance_visit(source_name, target_doc=None, item_name=None, s_id=No
"validation": {"docstatus": ["=", 1]},
"postprocess": update_status_and_detail,
},
- "Maintenance Schedule Item": {
+ "Maintenance Schedule Detail": {
"doctype": "Maintenance Visit Purpose",
- "condition": lambda doc: doc.item_name == item_name if item_name else True,
- "field_map": {"sales_person": "service_person"},
+ "condition": condition,
+ "field_map": {
+ "sales_person": "service_person",
+ "name": "maintenance_schedule_detail",
+ },
"postprocess": update_serial,
},
},
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
index e7df4847dd..d2511b8cbc 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
@@ -56,20 +56,39 @@ class MaintenanceVisit(TransactionBase):
frappe.throw(_("Add Items in the Purpose Table"), title=_("Purposes Required"))
def validate_maintenance_date(self):
- if self.maintenance_type == "Scheduled" and self.maintenance_schedule_detail:
- item_ref = frappe.db.get_value(
- "Maintenance Schedule Detail", self.maintenance_schedule_detail, "item_reference"
- )
- if item_ref:
- start_date, end_date = frappe.db.get_value(
- "Maintenance Schedule Item", item_ref, ["start_date", "end_date"]
+ if self.maintenance_type == "Scheduled":
+ if self.maintenance_schedule_detail:
+ item_ref = frappe.db.get_value(
+ "Maintenance Schedule Detail", self.maintenance_schedule_detail, "item_reference"
)
- if get_datetime(self.mntc_date) < get_datetime(start_date) or get_datetime(
- self.mntc_date
- ) > get_datetime(end_date):
- frappe.throw(
- _("Date must be between {0} and {1}").format(format_date(start_date), format_date(end_date))
+ if item_ref:
+ start_date, end_date = frappe.db.get_value(
+ "Maintenance Schedule Item", item_ref, ["start_date", "end_date"]
)
+ if get_datetime(self.mntc_date) < get_datetime(start_date) or get_datetime(
+ self.mntc_date
+ ) > get_datetime(end_date):
+ frappe.throw(
+ _("Date must be between {0} and {1}").format(format_date(start_date), format_date(end_date))
+ )
+ else:
+ for purpose in self.purposes:
+ if purpose.maintenance_schedule_detail:
+ item_ref = frappe.db.get_value(
+ "Maintenance Schedule Detail", purpose.maintenance_schedule_detail, "item_reference"
+ )
+ if item_ref:
+ start_date, end_date = frappe.db.get_value(
+ "Maintenance Schedule Item", item_ref, ["start_date", "end_date"]
+ )
+ if get_datetime(self.mntc_date) < get_datetime(start_date) or get_datetime(
+ self.mntc_date
+ ) > get_datetime(end_date):
+ frappe.throw(
+ _("Date must be between {0} and {1}").format(
+ format_date(start_date), format_date(end_date)
+ )
+ )
def validate(self):
self.validate_serial_no()
@@ -82,6 +101,7 @@ class MaintenanceVisit(TransactionBase):
if not cancel:
status = self.completion_status
actual_date = self.mntc_date
+
if self.maintenance_schedule_detail:
frappe.db.set_value(
"Maintenance Schedule Detail", self.maintenance_schedule_detail, "completion_status", status
@@ -89,6 +109,21 @@ class MaintenanceVisit(TransactionBase):
frappe.db.set_value(
"Maintenance Schedule Detail", self.maintenance_schedule_detail, "actual_date", actual_date
)
+ else:
+ for purpose in self.purposes:
+ if purpose.maintenance_schedule_detail:
+ frappe.db.set_value(
+ "Maintenance Schedule Detail",
+ purpose.maintenance_schedule_detail,
+ "completion_status",
+ status,
+ )
+ frappe.db.set_value(
+ "Maintenance Schedule Detail",
+ purpose.maintenance_schedule_detail,
+ "actual_date",
+ actual_date,
+ )
def update_customer_issue(self, flag):
if not self.maintenance_schedule:
diff --git a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json
index ba05355553..a5a63c4c4d 100644
--- a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json
+++ b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json
@@ -17,7 +17,8 @@
"work_details",
"work_done",
"prevdoc_doctype",
- "prevdoc_docname"
+ "prevdoc_docname",
+ "maintenance_schedule_detail"
],
"fields": [
{
@@ -49,6 +50,8 @@
"options": "Serial No"
},
{
+ "fetch_from": "item_code.description",
+ "fetch_if_empty": 1,
"fieldname": "description",
"fieldtype": "Text Editor",
"in_list_view": 1,
@@ -56,7 +59,6 @@
"oldfieldname": "description",
"oldfieldtype": "Small Text",
"print_width": "300px",
- "reqd": 1,
"width": "300px"
},
{
@@ -103,12 +105,19 @@
{
"fieldname": "section_break_6",
"fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "maintenance_schedule_detail",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Maintenance Schedule Detail",
+ "options": "Maintenance Schedule Detail"
}
],
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2023-02-27 11:09:33.114458",
+ "modified": "2024-01-05 21:46:53.239830",
"modified_by": "Administrator",
"module": "Maintenance",
"name": "Maintenance Visit Purpose",
diff --git a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py
index 3686941c64..1d4dab2873 100644
--- a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py
+++ b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py
@@ -14,9 +14,10 @@ class MaintenanceVisitPurpose(Document):
if TYPE_CHECKING:
from frappe.types import DF
- description: DF.TextEditor
+ description: DF.TextEditor | None
item_code: DF.Link | None
item_name: DF.Data | None
+ maintenance_schedule_detail: DF.Data | None
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data