diff --git a/smart_service/apis/utils.py b/smart_service/apis/utils.py new file mode 100644 index 0000000..a5c328c --- /dev/null +++ b/smart_service/apis/utils.py @@ -0,0 +1,148 @@ +import frappe +import os + +@frappe.whitelist() +def check_img_ext(path): + if path: + ext = path.split()[-1] + if ext.lower().endswith('.jpg') or ext.lower().endswith('.jpeg'): + return True + else: + return False + else: + return False + + +@frappe.whitelist() +def check_png_ext(path): + if path: + ext = path.split()[-1] + if ext.lower().endswith('.png'): + return True + else: + return False + else: + return False + + +@frappe.whitelist() +def check_zip_ext(path): + if path: + ext = path.split()[-1] + if ext.lower().endswith('.zip'): + return True + else: + return False + else: + return False + + +@frappe.whitelist() +def check_pdf_ext(path): + if path: + ext = path.split()[-1] + if ext.lower().endswith('.pdf'): + return True + else: + return False + else: + return False + + +@frappe.whitelist() +def check_mp4_ext(path): + if path: + ext = path.split()[-1] + if ext.lower().endswith('.mp4'): + return True + else: + return False + + +def details_of_image(image_file): + try: + # Image dimension validation + import os + from PIL import Image + if image_file.startswith('/private/'): + filepath = get_absolute_path(image_file, True) + else: + filepath = get_absolute_path(image_file) + img = Image.open(filepath) + width = img.width + height = img.height + size = os.stat(filepath) + size=size[6]/1024 + return width, height,size + except Exception as e: + raise e + +def get_file_size(filepath): + if filepath.startswith('/private/'): + file_dir = get_absolute_path(filepath, True) + else: + file_dir = get_absolute_path(filepath) + + size_in_bytes = os.path.getsize(file_dir) + size_in_megabytes = size_in_bytes / (1024 * 1024) + return size_in_megabytes + + +def get_image_size(filepath): + if filepath.startswith('/private/'): + file_dir = get_absolute_path(filepath, True) + else: + file_dir = get_absolute_path(filepath) + + size_in_bytes = os.path.getsize(file_dir) + size_in_kilobytes = size_in_bytes / 1024 + return size_in_kilobytes + + +def get_absolute_path(file_name, is_private=False): + try: + if file_name.startswith('/files/'): + file_name = file_name[7:] + else: + file_name = file_name[15:] + return frappe.utils.get_bench_path() + "/sites/" + frappe.utils.get_path('private' if is_private else 'public', + 'files', file_name)[2:] + except Exception as e: + frappe.log_error("get_absolute_path", frappe.get_traceback()) + + + +def checking_image(file_url, attached_to_doctype, attached_to_field, docname, is_child=None): + try: + import time + time.sleep(1) + if docname.startswith('new'): + image_name = frappe.db.get_list("File", fields={"name"}, filters={"file_url": file_url, + "attached_to_doctype": attached_to_doctype, + "attached_to_field": attached_to_field, + "attached_to_name": docname}) + + else: + image_name = frappe.db.get_list("File", fields={"name"}, filters={"file_url": file_url, + "attached_to_doctype": attached_to_doctype, + "attached_to_field": attached_to_field}) + + image_name = frappe.db.sql(f"""select name from `tabFile` where file_url='{file_url}' and attached_to_doctype='{attached_to_doctype}' and + attached_to_field='{attached_to_field}'""",as_dict=1) + # frappe.msgprint("data-"+str(file_url)+"-"+str(attached_to_doctype)+"-"+str(attached_to_field)+"-"+str(docname)) + if not attached_to_doctype == "Symbol Scanner" and is_child != 1: + frappe.db.sql( + '''UPDATE `tab{0}` SET {2} = '' where name = "{1}"'''.format(attached_to_doctype, docname, + attached_to_field)) + frappe.db.commit() + if attached_to_doctype == "Symbol Scanner": + frappe.db.set_value( + "Symbol Scanner", "Symbol Scanner", attached_to_field, "") + + if len(image_name) > 0: + frappe.delete_doc('File', image_name[0]['name']) + return True + + except Exception as e: + frappe.log_error("Checking images", frappe.get_traceback()) + diff --git a/smart_service/phase_2/doctype/feature_finder/feature_finder.js b/smart_service/phase_2/doctype/feature_finder/feature_finder.js index 066cfab..e5773f6 100644 --- a/smart_service/phase_2/doctype/feature_finder/feature_finder.js +++ b/smart_service/phase_2/doctype/feature_finder/feature_finder.js @@ -7,12 +7,15 @@ var filter_value = 0 frappe.ui.form.on('Feature Finder', { refresh: function (frm) { + + if (!frm.doc.feature_finder_images) { $(cur_frm.fields_dict.image_html.wrapper).empty(); } if (!frm.is_new()) { custom_tab_html(frm) } + set_display_order(frm) show_images(frm) @@ -33,6 +36,10 @@ frappe.ui.form.on('Feature Finder', { // } + }, + sop_name:function(frm){ + console.log("jdi") + get_field_validation(frm) }, onload: function (frm) { if (!frm.doc.feature_finder_images) { @@ -120,7 +127,7 @@ frappe.ui.form.on('Feature Finder', { }, validate: function (frm) { - + get_field_validation(frm) //save swap child table var spec_id_dis = [] var image_id_dis = [] @@ -201,6 +208,27 @@ frappe.ui.form.on('Feature Finder', { frm.reload_doc() } }); +function get_field_validation(frm){ + var alphanum = /^[a-zA-Z]+/; + if (frm.doc.sop_name) { + if (frm.doc.sop_name.length > 1) { + if (frm.doc.sop_name.length > 50) { + frappe.msgprint(__(""+frm.doc.doctype+": Only 50 characters are allowed.")) + frappe.validated = false; + } else { + if (alphanum.test(frm.doc.sop_name) === true) { + frappe.validated = true; + } else if (frm.doc.sop_name) { + frappe.msgprint(__(""+frm.doc.doctype+": There can only be letters and alpha numerals.")); + frappe.validated = false; + } + } + } else { + frappe.msgprint(__(""+frm.doc.doctype+": Single character is not allowed.")) + frappe.validated = false; + } + } +} function set_display_order_child(doctype_name, values, frm) { if (values.length > 0) { frappe.call({ @@ -217,6 +245,7 @@ function set_display_order_child(doctype_name, values, frm) { } }) } + } function show_images(frm) { @@ -1013,20 +1042,45 @@ function custom_tab_html(frm) { primary_action_label: 'Submit', primary_action(values) { if (values && values.image) { - frappe.call({ - method: "smart_service.phase_2.doctype.feature_finder.feature_finder.insert_image_data", - args: { - doc_name: frm.doc.name, - values: values, - tab_ref: frm.doc.tab_ref - }, - callback: function (r) { - if (r.message.status == "success") { - cur_frm.reload_doc() - cur_frm.refresh() + if (values.image){ + console.log(values.image,"values.image") + frappe.call({ + method: "smart_service.phase_2.doctype.feature_finder.feature_finder.file_validation", + args: { + image: values.image, + }, + callback: function (r) { + console.log(r.message, "r.message") + if (r.message && r.message[0] == false) { + if (r.message[1] == 1) { + frappe.validated = false; + frappe.msgprint("Invalid file type") + } + if (r.message[1] == 2) { + frappe.validated = false; + frappe.msgprint("Invalid file size") + } + } + else{ + frappe.call({ + method: "smart_service.phase_2.doctype.feature_finder.feature_finder.insert_image_data", + args: { + doc_name: frm.doc.name, + values: values, + tab_ref: frm.doc.tab_ref + }, + callback: function (r) { + if (r.message.status == "success") { + cur_frm.reload_doc() + cur_frm.refresh() + } + } + }) + } } - } - }) + }) + } + } spec_dia.hide(); } diff --git a/smart_service/phase_2/doctype/feature_finder/feature_finder.py b/smart_service/phase_2/doctype/feature_finder/feature_finder.py index 10b201c..db85913 100644 --- a/smart_service/phase_2/doctype/feature_finder/feature_finder.py +++ b/smart_service/phase_2/doctype/feature_finder/feature_finder.py @@ -290,3 +290,36 @@ def insert_tab_ref(docname, tab_ref): frappe.db.commit() except Exception as e: frappe.log_error("insert_tab", frappe.get_traceback()) + + + +@frappe.whitelist() +def file_validation(image): + from smart_service.apis.utils import check_png_ext, check_img_ext,details_of_image + if image: + res = check_img_ext(image) + res1 = check_png_ext(image) + if res == True: + (width, height, size) = details_of_image(image) + + if width > 1920 or height > 1080 and image: + val = delete_feature_image(image) + if val == True: + return (False, 2) + else: + return True + + else: + val = delete_feature_image(image) + if res == False: + ret = res + else: + ret = res1 + return ret, 1 + + +def delete_feature_image(file_url): + image_name = frappe.db.sql(f"""select name from `tabFile` where file_url='{file_url}'""",as_dict=1) + if len(image_name) > 0: + frappe.delete_doc('File', image_name[0]['name']) + return True \ No newline at end of file diff --git a/smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.js b/smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.js index 553f763..8a9da83 100644 --- a/smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.js +++ b/smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.js @@ -10,5 +10,26 @@ frappe.ui.form.on('Feature Finder Master', { } }; }); + }, + validate:function(frm){ + frappe.call({ + method: "smart_service.phase_2.doctype.feature_finder_master.feature_finder_master.file_validation", + args: { + image: frm.doc.feature_pdf, + name:frm.doc.name + }, + callback: function (r) { + console.log(r.message, "r.message") + if (r.message && r.message[0] == false) { + if (r.message[1] == 1) { + frappe.validated = false; + frappe.msgprint("Invalid file type") + } + + } + + } + }) } }); + diff --git a/smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.py b/smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.py index 4a09561..7191570 100644 --- a/smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.py +++ b/smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.py @@ -1,8 +1,42 @@ # Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors # For license information, please see license.txt -# import frappe +import frappe from frappe.model.document import Document class FeatureFinderMaster(Document): pass + + +@frappe.whitelist() +def file_validation(image, name, value=None): + from smart_service.apis.utils import check_png_ext, check_img_ext,check_pdf_ext,details_of_image + if image: + res = check_pdf_ext(image) + if res == True: + pass + # (width, height, size) = details_of_image(image) + + # if width > 640 or height > 360 and image: + # val = delete_feature_image(image) + # if val == True: + # return (False, 2) + # else: + # return True + + else: + val = delete_file(image, 'Feature Finder Master', + "feature_pdf", name) + if res == False: + ret = res + return ret, 1 + + +def delete_file(file_url, attached_to_doctype, attached_to_field, docname, is_child=None): + image_name = frappe.db.get_list("File", fields={"name"}, filters={"file_url": file_url, + "attached_to_doctype": attached_to_doctype, + "attached_to_field": attached_to_field, + "attached_to_name": docname}) + if len(image_name) > 0: + frappe.delete_doc('File', image_name[0]['name']) + return True diff --git a/smart_service/phase_2/doctype/qwik_service/qwik_service.js b/smart_service/phase_2/doctype/qwik_service/qwik_service.js index 6168478..b796ebf 100644 --- a/smart_service/phase_2/doctype/qwik_service/qwik_service.js +++ b/smart_service/phase_2/doctype/qwik_service/qwik_service.js @@ -26,7 +26,52 @@ frappe.ui.form.on('Qwik Service', { variant(frm) }, validate:function(frm){ + // file validation start + if (frm.doc.pdf){ + frappe.call({ + method: "smart_service.phase_2.doctype.qwik_service.qwik_service.file_validation", + args: { + image: frm.doc.pdf, + name:frm.doc.name + }, + callback: function (r) { + console.log(r.message, "r.message") + if (r.message && r.message[0] == false) { + if (r.message[1] == 1) { + frappe.validated = false; + frappe.msgprint("Invalid file type") + } + + } + + } + }) + } + // file validation end + cur_frm.refresh_fields("display_order") + // check_field_character(frm.doc.service_time) + if (frm.doc.service_time) { + var alphanum = /[@#$^\\[\]{}`\\|\?]/; + if (frm.doc.service_time.length > 1) { + if (frm.doc.service_time.length > 3) { + frappe.throw("Service Time: Only 3 characters are allowed") + frappe.validated = false; + } else { + if (alphanum.test(frm.doc.service_time) === true) { + } else if (frm.doc.service_time) { + frappe.throw(__("Service Time: Enter letter or alpha numeric characters only.")); + frappe.validated = false; + } + } + } else if(frm.doc.service_time.length == 1) { + frappe.throw("Service Time: Single character not allowed") + frappe.validated = false; + } + else{ + // pass + } + } if (frm.doc.display_order && frm.doc.name && !frm.is_new()) { //***check if there is same display_order frappe.db.get_list('Qwik Service', { @@ -58,7 +103,6 @@ frappe.ui.form.on('Qwik Service', { } }); } - check_field_character(frm.doc.service_time) }, after_save: function (frm) { cur_frm.refresh_fields("display_order") @@ -422,16 +466,26 @@ frappe.ui.form.on('Qwik Service Content',{ } }) -function check_field_character(field_name) { - if (field_name) { - if (field_name.length > 1) { - if (field_name.length > 3) { - frappe.throw("Service Time: Only 3 characters are allowed") - frappe.validated = false; - } - } - } -} +// function check_field_character(field_name) { +// if (field_name) { +// var alphanum = /[@#$^\\[\]{}`\\|\?]/; +// if (field_name.length > 1) { +// if (field_name.length > 3) { +// frappe.throw("Service Time: Only 3 characters are allowed") +// frappe.validated = false; +// } else { +// if (alphanum.test(field_name) === true) { +// } else if (field_name) { +// frappe.throw(__("Service Time: Enter letter or alpha numeric characters only.")); +// frappe.validated = false; +// } +// } +// } else { +// frappe.throw("Service Time: Single character not allowed") +// frappe.validated = false; +// } +// } +// } function variant(frm){ frappe.call({ diff --git a/smart_service/phase_2/doctype/qwik_service/qwik_service.py b/smart_service/phase_2/doctype/qwik_service/qwik_service.py index cfb9db6..a6ff1d3 100644 --- a/smart_service/phase_2/doctype/qwik_service/qwik_service.py +++ b/smart_service/phase_2/doctype/qwik_service/qwik_service.py @@ -102,3 +102,27 @@ def delete_qwik_data(values): def get_kilometer(vehicle=None): kilometer_list = frappe.db.sql("""select service_kilometers from `tabVehicle_SK` where parent='%s'; """%(vehicle),as_list=1) return kilometer_list + + +@frappe.whitelist() +def file_validation(image, name, value=None): + from smart_service.apis.utils import check_png_ext, check_img_ext,check_pdf_ext,details_of_image + if image: + res = check_pdf_ext(image) + if res == True: + pass + else: + val = delete_file(image, 'Qwik Service', + "pdf", name) + if res == False: + ret = res + return ret, 1 + +def delete_file(file_url, attached_to_doctype, attached_to_field, docname, is_child=None): + image_name = frappe.db.get_list("File", fields={"name"}, filters={"file_url": file_url, + "attached_to_doctype": attached_to_doctype, + "attached_to_field": attached_to_field, + "attached_to_name": docname}) + if len(image_name) > 0: + frappe.delete_doc('File', image_name[0]['name']) + return True \ No newline at end of file diff --git a/smart_service/phase_2/doctype/special_tool_information/special_tool_information.py b/smart_service/phase_2/doctype/special_tool_information/special_tool_information.py index 3c2c8b8..6787872 100644 --- a/smart_service/phase_2/doctype/special_tool_information/special_tool_information.py +++ b/smart_service/phase_2/doctype/special_tool_information/special_tool_information.py @@ -21,3 +21,5 @@ class SpecialToolInformation(Document): if not self.is_new() and self.published == 1: self.published = 0 + + diff --git a/smart_service/phase_2/doctype/training_information/training_information.js b/smart_service/phase_2/doctype/training_information/training_information.js index 28153dc..cd1f977 100644 --- a/smart_service/phase_2/doctype/training_information/training_information.js +++ b/smart_service/phase_2/doctype/training_information/training_information.js @@ -20,6 +20,27 @@ frappe.ui.form.on('Training Information', { validate:function(frm){ cur_frm.refresh_fields("display_order") }, + after_save: function (frm) { + if (frm.doc.content) { + frappe.call({ + method: "smart_service.phase_2.doctype.training_information.training_information.file_validation_child", + args: { + name: frm.doc.name, + value:"content" + }, + callback: function (r) { + console.log(r.message, "----file validation size-------") + if (r.message && r.message[0] == false) { + if (r.message[1]) { + frappe.validated = false; + frm.reload_doc() + frappe.throw("In training information content " + r.message[1] + " row was invalid file type") + } + } + } + }) + } + } }); function set_display_order(frm){ if (frm.is_new()) { diff --git a/smart_service/phase_2/doctype/training_information/training_information.py b/smart_service/phase_2/doctype/training_information/training_information.py index 8842404..e5be4b8 100644 --- a/smart_service/phase_2/doctype/training_information/training_information.py +++ b/smart_service/phase_2/doctype/training_information/training_information.py @@ -18,3 +18,48 @@ class TrainingInformation(Document): if not self.is_new() and self.published == 1: self.published = 0 + + +@frappe.whitelist() +def file_validation_child(name, value=None): + from smart_service.apis.utils import check_png_ext, check_img_ext, check_zip_ext, check_pdf_ext, details_of_image, checking_image, check_mp4_ext, get_file_size + if name: + child_data = frappe.db.sql( + """select * from `tabTraining Information Content Reference` where parent='%s'"""%(name), as_dict=1) + for d in child_data: + if d['image_video']: + res = False + res1 = False + res2= False + if d['content_type'] == "Image": + res = check_img_ext(d['image_video']) + res1 = check_png_ext(d['image_video']) + else: + res2 = check_mp4_ext(d['image_video']) + + if res == True or res1 == True: + width, height, size = details_of_image( + d['image_video']) + if width > 1280 or height > 720 or size > 1*1024 and d['image_video']: + val = checking_image( + d['image_video'], "Training Information", value, name, 1) + frappe.delete_doc("Training Information Content Reference", d['name']) + if val == True: + return False, d['idx'] + else: + return True + elif res2 == True: + video_size_mb = get_file_size(d['image_video']) + if video_size_mb > 10: + frappe.delete_doc('Training Information Content Reference', d['name']) + return (False, d['idx']) + else: + if res == False and res1==False: + ret = res + else: + ret = res2 + + val = checking_image( + d['image_video'], 'Training Information', value, name, 1) + frappe.delete_doc('Training Information Content Reference', d['name']) + return (ret, d['idx']) diff --git a/smart_service/transactions/doctype/procedure/procedure.js b/smart_service/transactions/doctype/procedure/procedure.js index 1f368af..009c7cd 100644 --- a/smart_service/transactions/doctype/procedure/procedure.js +++ b/smart_service/transactions/doctype/procedure/procedure.js @@ -49,7 +49,7 @@ frappe.ui.form.on('Procedure', { } } - frm.doc.procedure_filter = "All"; + frm.doc.procedure_filter = "All"; if (frm.doc.procedure_filter == "All") { frm.get_field('procedure_details').grid.static_rows = false; frm.fields_dict.procedure_details.grid.grid_rows.forEach((row) => {