Browse Source

Phase Release1

version2
venkataakhil 1 year ago
parent
commit
357c900d64
  1. 113
      smart_service/apis/master_api.py
  2. 164
      smart_service/apis/v2/master.py
  3. 0
      smart_service/masters/doctype/module_master/__init__.py
  4. 55
      smart_service/masters/doctype/module_master/module_master.js
  5. 74
      smart_service/masters/doctype/module_master/module_master.json
  6. 21
      smart_service/masters/doctype/module_master/module_master.py
  7. 8
      smart_service/masters/doctype/module_master/test_module_master.py
  8. 0
      smart_service/masters/doctype/role_master/__init__.py
  9. 96
      smart_service/masters/doctype/role_master/role_master.js
  10. 96
      smart_service/masters/doctype/role_master/role_master.json
  11. 25
      smart_service/masters/doctype/role_master/role_master.py
  12. 8
      smart_service/masters/doctype/role_master/test_role_master.py
  13. 3
      smart_service/modules.txt
  14. 0
      smart_service/phase_2/__init__.py
  15. 0
      smart_service/phase_2/doctype/__init__.py
  16. 0
      smart_service/phase_2/doctype/feature_finder/__init__.py
  17. 527
      smart_service/phase_2/doctype/feature_finder/feature_finder.js
  18. 171
      smart_service/phase_2/doctype/feature_finder/feature_finder.json
  19. 131
      smart_service/phase_2/doctype/feature_finder/feature_finder.py
  20. 8
      smart_service/phase_2/doctype/feature_finder/test_feature_finder.py
  21. 0
      smart_service/phase_2/doctype/feature_finder_category_master/__init__.py
  22. 8
      smart_service/phase_2/doctype/feature_finder_category_master/feature_finder_category_master.js
  23. 59
      smart_service/phase_2/doctype/feature_finder_category_master/feature_finder_category_master.json
  24. 8
      smart_service/phase_2/doctype/feature_finder_category_master/feature_finder_category_master.py
  25. 8
      smart_service/phase_2/doctype/feature_finder_category_master/test_feature_finder_category_master.py
  26. 0
      smart_service/phase_2/doctype/feature_finder_content/__init__.py
  27. 51
      smart_service/phase_2/doctype/feature_finder_content/feature_finder_content.json
  28. 8
      smart_service/phase_2/doctype/feature_finder_content/feature_finder_content.py
  29. 0
      smart_service/phase_2/doctype/feature_finder_disclaimer/__init__.py
  30. 38
      smart_service/phase_2/doctype/feature_finder_disclaimer/feature_finder_disclaimer.json
  31. 8
      smart_service/phase_2/doctype/feature_finder_disclaimer/feature_finder_disclaimer.py
  32. 0
      smart_service/phase_2/doctype/feature_finder_images/__init__.py
  33. 51
      smart_service/phase_2/doctype/feature_finder_images/feature_finder_images.json
  34. 8
      smart_service/phase_2/doctype/feature_finder_images/feature_finder_images.py
  35. 0
      smart_service/phase_2/doctype/feature_finder_master/__init__.py
  36. 8
      smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.js
  37. 95
      smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.json
  38. 8
      smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.py
  39. 8
      smart_service/phase_2/doctype/feature_finder_master/test_feature_finder_master.py
  40. 0
      smart_service/phase_2/doctype/feature_finder_specification/__init__.py
  41. 58
      smart_service/phase_2/doctype/feature_finder_specification/feature_finder_specification.json
  42. 8
      smart_service/phase_2/doctype/feature_finder_specification/feature_finder_specification.py
  43. 0
      smart_service/phase_2/doctype/feature_finder_specification_master/__init__.py
  44. 8
      smart_service/phase_2/doctype/feature_finder_specification_master/feature_finder_specification_master.js
  45. 59
      smart_service/phase_2/doctype/feature_finder_specification_master/feature_finder_specification_master.json
  46. 15
      smart_service/phase_2/doctype/feature_finder_specification_master/feature_finder_specification_master.py
  47. 8
      smart_service/phase_2/doctype/feature_finder_specification_master/test_feature_finder_specification_master.py
  48. 0
      smart_service/phase_2/doctype/module_publish_mapping/__init__.py
  49. 8
      smart_service/phase_2/doctype/module_publish_mapping/module_publish_mapping.js
  50. 131
      smart_service/phase_2/doctype/module_publish_mapping/module_publish_mapping.json
  51. 8
      smart_service/phase_2/doctype/module_publish_mapping/module_publish_mapping.py
  52. 8
      smart_service/phase_2/doctype/module_publish_mapping/test_module_publish_mapping.py
  53. 0
      smart_service/phase_2/doctype/mst_information_assets/__init__.py
  54. 56
      smart_service/phase_2/doctype/mst_information_assets/mst_information_assets.json
  55. 8
      smart_service/phase_2/doctype/mst_information_assets/mst_information_assets.py
  56. 0
      smart_service/phase_2/doctype/post_vin_cutoff_id/__init__.py
  57. 37
      smart_service/phase_2/doctype/post_vin_cutoff_id/post_vin_cutoff_id.json
  58. 8
      smart_service/phase_2/doctype/post_vin_cutoff_id/post_vin_cutoff_id.py
  59. 0
      smart_service/phase_2/doctype/repair_service_child/__init__.py
  60. 8
      smart_service/phase_2/doctype/repair_service_child/repair_service_child.js
  61. 52
      smart_service/phase_2/doctype/repair_service_child/repair_service_child.json
  62. 14
      smart_service/phase_2/doctype/repair_service_child/repair_service_child.py
  63. 8
      smart_service/phase_2/doctype/repair_service_child/test_repair_service_child.py
  64. 0
      smart_service/phase_2/doctype/repair_service_mapping/__init__.py
  65. 103
      smart_service/phase_2/doctype/repair_service_mapping/repair_service_mapping.js
  66. 140
      smart_service/phase_2/doctype/repair_service_mapping/repair_service_mapping.json
  67. 67
      smart_service/phase_2/doctype/repair_service_mapping/repair_service_mapping.py
  68. 8
      smart_service/phase_2/doctype/repair_service_mapping/test_repair_service_mapping.py
  69. 0
      smart_service/phase_2/doctype/repair_service_master/__init__.py
  70. 57
      smart_service/phase_2/doctype/repair_service_master/repair_service_master.js
  71. 77
      smart_service/phase_2/doctype/repair_service_master/repair_service_master.json
  72. 19
      smart_service/phase_2/doctype/repair_service_master/repair_service_master.py
  73. 8
      smart_service/phase_2/doctype/repair_service_master/test_repair_service_master.py
  74. 0
      smart_service/phase_2/doctype/repair_service_master_mapping/__init__.py
  75. 76
      smart_service/phase_2/doctype/repair_service_master_mapping/repair_service_master_mapping.js
  76. 126
      smart_service/phase_2/doctype/repair_service_master_mapping/repair_service_master_mapping.json
  77. 22
      smart_service/phase_2/doctype/repair_service_master_mapping/repair_service_master_mapping.py
  78. 8
      smart_service/phase_2/doctype/repair_service_master_mapping/test_repair_service_master_mapping.py
  79. 0
      smart_service/phase_2/doctype/special_tool_information/__init__.py
  80. 91
      smart_service/phase_2/doctype/special_tool_information/special_tool_information.js
  81. 88
      smart_service/phase_2/doctype/special_tool_information/special_tool_information.json
  82. 14
      smart_service/phase_2/doctype/special_tool_information/special_tool_information.py
  83. 8
      smart_service/phase_2/doctype/special_tool_information/test_special_tool_information.py
  84. 0
      smart_service/phase_2/doctype/training_information/__init__.py
  85. 8
      smart_service/phase_2/doctype/training_information/test_training_information.py
  86. 30
      smart_service/phase_2/doctype/training_information/training_information.js
  87. 107
      smart_service/phase_2/doctype/training_information/training_information.json
  88. 14
      smart_service/phase_2/doctype/training_information/training_information.py
  89. 0
      smart_service/phase_2/doctype/training_information_content_reference/__init__.py
  90. 50
      smart_service/phase_2/doctype/training_information_content_reference/training_information_content_reference.json
  91. 8
      smart_service/phase_2/doctype/training_information_content_reference/training_information_content_reference.py
  92. 0
      smart_service/phase_2/doctype/training_information_master/__init__.py
  93. 8
      smart_service/phase_2/doctype/training_information_master/test_training_information_master.py
  94. 36
      smart_service/phase_2/doctype/training_information_master/training_information_master.js
  95. 74
      smart_service/phase_2/doctype/training_information_master/training_information_master.json
  96. 21
      smart_service/phase_2/doctype/training_information_master/training_information_master.py
  97. 90
      smart_service/public/js/utils.js
  98. 48
      smart_service/transactions/doctype/procedure/procedure.js
  99. 7
      smart_service/transactions/doctype/publish/publish.json
  100. 0
      smart_service/transactions/doctype/publish_test/__init__.py

113
smart_service/apis/master_api.py

@ -37,17 +37,19 @@ def custom_rate_limit(limit, seconds):
@frappe.whitelist()
def masters(args=None, LSD=None,iid=None):
def masters(args=None, LSD=None, iid=None):
# Rate limit - Step 1
rate = custom_rate_limit(limit=20, seconds=5)
if rate != 1:
return rate
# Input Validation
val = input_validation(args=args)
if val != '':
return {"status": 0, "error": "Parameter's missing:"+val}
# Time validation
date_format = "%Y-%m-%d %H:%M:%S.%f"
if LSD != "":
try:
datetime.datetime.strptime(LSD, date_format)
@ -66,13 +68,13 @@ def masters(args=None, LSD=None,iid=None):
select name as vehicle,vehicle_segment,vehicle_segment_id,image,active_status,display_order,
myid as vechile_id,display_order,modified from tabVehicle
where modified > '{LSD}' and global_publish = 1;
''',as_dict=1)
''', as_dict=1)
else:
api = frappe.db.sql(f'''
select name as vehicle,vehicle_segment,vehicle_segment_id,image,active_status,display_order,
myid as vechile_id,display_order,modified from tabVehicle
where modified > '{LSD}' and internal_publish = 1;
''',as_dict=1)
''', as_dict=1)
for i in api:
if i["active_status"] == "Active":
i["active_status"] = True
@ -80,6 +82,10 @@ def masters(args=None, LSD=None,iid=None):
i["active_status"] = False
elif args == "variant":
api = frappe.db.sql('''
select v.myid as variant_id,vm.name,vm.vehicle,vm.variant,vm.fuel,vm.transmission,vm.drive,vm.active_status
FROM `tabVariant Mapping` vm left join tabVariant v on v.name = vm.variant where vm.modified >='';''', as_dict=1)
api = frappe.db.get_list(
"Variant",
fields=[
@ -223,14 +229,14 @@ def masters(args=None, LSD=None,iid=None):
api = frappe.db.sql('''
SELECT lang_name,lang_code,active_status,display_order,myid as lang_id,modified FROM `tabCustom Languages`
where modified> 'LSD' and global_publish = 1;
''',as_dict=1)
''', as_dict=1)
else:
api = frappe.db.sql('''
SELECT lang_name,lang_code,active_status,display_order,myid as lang_id,modified FROM `tabCustom Languages`
where modified> 'LSD' and internal_publish = 1;
''',as_dict=1)
''', as_dict=1)
for i in api:
if i["active_status"] == "Active":
i["active_status"] = True
@ -296,3 +302,94 @@ def check_pub_type(iid):
if not device_pub_type:
return False
return device_pub_type[0][0]
@frappe.whitelist(methods=['POST'])
def variant(LSD, language):
date_format = "%Y-%m-%d %H:%M:%S.%f"
if LSD != "":
try:
datetime.datetime.strptime(LSD, date_format)
except:
return {"status": 0, "error": " 'LSD' format error"}
try:
data = frappe.db.sql('''
select name,vehicle,vehicle_id,variant_name,variant,variant_id,fuel,fuel_id,transmission,transmission_id,drive,drive_id,family_code,
case when active_status= 'Active' Then true else false end as active_status
FROM `tabVariant Mapping` where modified >='';''', as_dict=1)
for d in data:
d['modules'] = {
"Automotive System": 1,
"TSB": 1,
"FSA": 1,
"TEKalert": 1,
"Feature Finder": 1,
"Repair/Service Check Sheet": 1,
"Mahindra Special Tool Information": 0,
"Training Information": 0,
"QWIK Service": 0,
"PDI Inspection": 0,
"Torque Information NM": 0
}
return {"status": 1, "error": None, 'data': data}
except Exception as e:
frappe.local.response['http_status_code'] = 400
return {"status": 0, "error": e, 'data': None}
@frappe.whitelist(methods=['POST'])
def variant1(LSD, language):
date_format = "%Y-%m-%d %H:%M:%S.%f"
if LSD != "":
try:
datetime.datetime.strptime(LSD, date_format)
except:
return {"status": 0, "error": " 'LSD' format error"}
try:
data = frappe.db.sql('''
select name,vehicle,vehicle_id,variant_name,variant,variant_id,fuel,fuel_id,transmission,transmission_id,drive,drive_id,family_code,
case when active_status= 'Active' Then true else false end as active_status
FROM `tabVariant Mapping` where modified >='';''', as_dict=1)
for d in data:
d['modules'] = frappe.db.sql(''' select 'automotive_system' as 'Automotive System', automotive_system as 'Active Status','tsb' as 'TSB',tsb as
'Active Status','fsa' as 'FSA', fsa as 'Active Status','tekalert' as 'TEKalert',tekalert as 'Active Status',
'feature_finder' as 'Feature Finder',feature_finder as 'Active Status','repairservice_check_sheet' as 'Repair/Service Check Sheet',
repairservice_check_sheet as 'Active Status','mahindra_special_tool_information' as 'Mahindra Special Tool Information',
mahindra_special_tool_information as 'Active Status','training_information' as 'Training Information',training_information as
'Active Status','qwik_service' as 'QWIK Service',qwik_service as 'Active Status','pdi_inspection' as 'PDI Inspection',
pdi_inspection as 'Active Status','torque_information_nm' as 'Torque Information NM',torque_information_nm as
'Active Status' FROM grmtest.`tabModule Publish Mapping`;''')
module_list = []
for k, v in d.items():
module_list.append([{'title': k}, {'active_status': v}])
return {"status":1,"error":None,'data':module_list}
# return {"status": 1, "error": None, 'data': data}
except Exception as e:
frappe.local.response['http_status_code'] = 400
return {"status": 0, "error": e, 'data': None}
@frappe.whitelist(methods=['POST'])
def app_modules(LSD):
date_format = "%Y-%m-%d %H:%M:%S.%f"
if LSD != "":
try:
datetime.datetime.strptime(LSD, date_format)
except:
return {"status": 0, "error": " 'LSD' format error"}
try:
data = frappe.db.sql('''
select module_name as title, app_menu_id,display_order,
case when active_status = 'Active' Then true else false end as active_status
FROM `tabModule Master` where modified >='';''', as_dict=1)
return {"status": 1, "error": None, 'data': data}
except Exception as e:
frappe.local.response['http_status_code'] = 400
return {"status": 0, "error": e, 'data': None}

164
smart_service/apis/v2/master.py

@ -0,0 +1,164 @@
import frappe
from urllib import request
import datetime
from frappe import utils
import json
from smart_service.apis.app_user_login import input_validation
date_format = "%Y-%m-%d %H:%M:%S.%f"
current_db_name = frappe.conf.get("db_name")
@frappe.whitelist(methods=["POST"], allow_guest=1)
def get_role_mapping():
req = json.loads(frappe.request.data)
try:
lsdt = req['lsdt']
if lsdt != '':
try:
datetime.datetime.strptime(lsdt, date_format)
except:
frappe.local.response['http_status_code'] = 400
return {"status": 0, "error": "Invalid date format", 'data': None}
except Exception as e:
frappe.local.response['http_status_code'] = 403
return {"status": 0, "error": e}
data = {}
try:
module_details = frappe.db.sql(f"""select module_name,active_status,my_id,display_order,modified from `tabModule Master`
where modified >= '{lsdt}' order by display_order;""", as_dict=1)
data['module'] = module_details
if lsdt:
role_maping_details = frappe.db.sql(f"""SELECT role,my_id,display_order,modules,active_status,modified from `tabRole Master` where modified>='{lsdt}'
order by display_order;""", as_dict=1)
else:
role_maping_details = frappe.db.sql(f"""SELECT role,my_id,display_order,modules,active_status,modified from `tabRole Master`
order by display_order;""", as_dict=1)
data['role_mapping'] = role_maping_details
return {"status": 1, "error": None, 'lsdt': utils.now(), "data": data}
except Exception as e:
return {"status": 0, "error": e, 'lsdt': utils.now(), "data": None}
@frappe.whitelist(methods=["POST"], allow_guest=1)
def get_repair_service_mapping(vehicle, language):
try:
repair_service_details = frappe.db.sql(f""" select vehicle,name,language,check_list_name,active_status,display_order,my_id from
`tabRepair Service Mapping` where vehicle = '{vehicle}' and language = '{language}'; """, as_dict=1)
for d in repair_service_details:
d['complaint'] = frappe.db.sql(f""" select complaint,remedial_action_ok,remedial_action_not_ok,idx as display_order,active_status from `tabRepair Service Child`
where parent = '{d['name']}' order by display_order ;""", as_dict=1)
return True, repair_service_details
except Exception as e:
return False, e
@frappe.whitelist(methods=["POST"], allow_guest=1)
def get_feature_finder(vehicle, variant, language):
try:
feature_finder_details = frappe.db.sql(f"""select ff.name,ff.vehicle,ff.variant,ff.language,ff.feature_name,ff.translated_feature_name,
ff.feature_category,ff.feature_type,ff.display_order,ff.active_status,ffm.feature_pdf from `tabFeature Finder` ff
left join grmtest.`tabFeature Finder Master` ffm on ff.vehicle = ffm.vehicle
where ff.vehicle = "{vehicle}" and ff.variant = "{variant}"
and ff.language = "{language}"; """, as_dict=1)
for d in feature_finder_details:
d['disclaimer'] = frappe.db.sql(f'''
SELECT name,content,active_status,idx as display_order FROM grmtest.`tabFeature Finder Disclaimer`
where parent = '{d['feature_name']}';
''', as_dict=1)
d['images'] = frappe.db.sql(f""" select image,idx as display_order,active_status from `tabFeature Finder Images` where
parent = '{d['name']}';""", as_dict=1)
d['content'] = frappe.db.sql(f"""select content,idx as display_order, active_status from `tabFeature Finder Content`
where parent = '{d['name']}';""", as_dict=1)
d['specification'] = frappe.db.sql(f"""select specification,value,idx as display_order,active_status from `tabFeature Finder Specification`
where parent = '{d['name']}';""", as_dict=1)
return True, feature_finder_details
except Exception as e:
return False, e
@frappe.whitelist(methods=["POST"], allow_guest=1)
def get_feature_finder1(vehicle, variant, language):
try:
feature_finder_details = frappe.db.sql(f"""select ff.name,ff.vehicle,ff.variant,ff.language,ff.features_names as feature_name,
ff.feature_category,ff.display_order,ff.active_status,ffm.feature_pdf as pdf from `tabFeature Finder` ff
left join grmtest.`tabFeature Finder Master` ffm on ff.features_names = ffm.feature_name
where ff.vehicle = "{vehicle}" and ffm.vehicle = "{vehicle}" and ff.variant = "{variant}"
and ff.language = "{language}"; """, as_dict=1)
for f in feature_finder_details:
f['disclaimer'] = frappe.db.sql(f'''
SELECT name,content,active_status,idx as display_order FROM `tabFeature Finder Disclaimer`
where parent = '{str(f['vehicle'])+ str('-')+ str(f['feature_name']) +str('-')+str(f['language'])}';
''', as_dict=1)
sop_images = frappe.db.sql(f""" select image,idx as display_order,active_status from `tabFeature Finder Images` where
parent = '{f['name']}' and feature_type ='sop';""", as_dict=1)
sop_content = frappe.db.sql(f"""select content,idx as display_order, active_status from `tabFeature Finder Content`
where parent = '{f['name']}' and feature_type ='SOP';""", as_dict=1)
sop_specification = frappe.db.sql(f"""select specification,value,idx as display_order,active_status from `tabFeature Finder Specification`
where parent = '{f['name']}' and post_vin_cutoff_name ='SOP';""", as_dict=1)
f['sop'] = {'content': sop_content, 'images': sop_images,
'specificaton': sop_specification}
post_vin_data = frappe.db.sql(f'''
select name,idx as display_order,post_vin_cutoff_name,post_vin_cutoff_id
from `tabPost Vin Cutoff ID` where parent = '{f['name']}';''', as_dict=1)
for p in post_vin_data:
vin_content = frappe.db.sql(f"""select content,idx as display_order, active_status from `tabFeature Finder Content`
where parent = '{f['name']}' and post_vin_cutoff_name ='{p['post_vin_cutoff_name']}';""", as_dict=1)
vin_images = frappe.db.sql(f""" select image,idx as display_order,active_status from `tabFeature Finder Images` where
parent = '{f['name']}' and post_vin_cutoff_name ='{p['post_vin_cutoff_name']}';""", as_dict=1)
vin_specification = frappe.db.sql(f"""select specification,value,idx as display_order,active_status from `tabFeature Finder Specification`
where parent = '{f['name']}' and post_vin_cutoff_name ='{p['post_vin_cutoff_name']}';""", as_dict=1)
p['content'] = vin_content
p['images'] = vin_images
p['specificaton'] = vin_specification
f['post_vin'] = post_vin_data
return True, feature_finder_details
except Exception as e:
return False, e
@frappe.whitelist(methods=['POST'])
def new_publish():
req = json.loads(frappe.request.data)
try:
module = req['module']
iid = req['iid']
vehicle = req['vehicle']
variant = req['variant']
language = req['language']
data = []
if module == 'Feature Finder':
flag, data = get_feature_finder1(vehicle, variant, language)
elif module == 'Repair/Service Check Sheet':
flag, data = get_repair_service_mapping(vehicle, language)
if flag:
return {'status': 1, 'error': None, 'data': data}
else:
return {'status': 0, 'error': data, 'data': None}
except Exception as e:
frappe.local.response['http_status_code'] = 400
return {'status': 0, 'error': "Parameter's missing: " + str(e), 'data': None}

0
smart_service/masters/doctype/module_master/__init__.py

55
smart_service/masters/doctype/module_master/module_master.js

@ -0,0 +1,55 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
var original_display_order = 0;
var module_name_count=0;
frappe.require('assets/smart_service/js/utils.js', () => {})
frappe.ui.form.on('Module Master', {
onload: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Module Master')
.then(count => {
module_name_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", module_name_count);
} else {
original_display_order = frm.doc.display_order;
}
});
},
refresh: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Module Master')
.then(count => {
module_name_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", module_name_count);
} else {
original_display_order = frm.doc.display_order;
}
});
},
after_save:function(frm){
cur_frm.refresh_fields("display_order")
},
validate: function (frm) {
//For Display Order
cur_frm.refresh_fields("display_order")
// console.log(module_name_count,"----",original_display_order)
display_order_validation(frm, module_name_count, original_display_order,frm.doc.module_name)
}
});

74
smart_service/masters/doctype/module_master/module_master.json

@ -0,0 +1,74 @@
{
"_liked_by": "[\"Administrator\"]",
"actions": [],
"allow_rename": 1,
"autoname": "format:{module_name}",
"creation": "2023-07-19 13:36:02.668693",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"module_name",
"active_status",
"display_order",
"app_menu_id"
],
"fields": [
{
"fieldname": "module_name",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Module Name",
"reqd": 1,
"set_only_once": 1
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Active Status",
"options": "Active\nInactive",
"reqd": 1
},
{
"fieldname": "display_order",
"fieldtype": "Int",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Display Order",
"reqd": 1
},
{
"fieldname": "app_menu_id",
"fieldtype": "Int",
"label": "App Menu Id",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-07 11:29:32.921688",
"modified_by": "Administrator",
"module": "Masters",
"name": "Module Master",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "module_name"
}

21
smart_service/masters/doctype/module_master/module_master.py

@ -0,0 +1,21 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class ModuleMaster(Document):
def validate(self):
if self.module_name:
self.module_name = self.module_name.strip()
# def autoname(self):
# if self.is_new():
# count = frappe.db.sql(
# '''select max(my_id) as max_count from `tabModule Master`;''')
# if count[0][0] is not None:
# self.my_id = count[0][0] + 1
# else:
# self.my_id = 1

8
smart_service/masters/doctype/module_master/test_module_master.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestModuleMaster(unittest.TestCase):
pass

0
smart_service/masters/doctype/role_master/__init__.py

96
smart_service/masters/doctype/role_master/role_master.js

@ -0,0 +1,96 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
var original_display_order = 0;
var role_name_count=0;
frappe.require('assets/smart_service/js/utils.js', () => {})
frappe.ui.form.on('Role Master', {
onload: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Role Master')
.then(count => {
role_name_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", role_name_count);
} else {
original_display_order = frm.doc.display_order;
}
});
},
refresh: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Role Master')
.then(count => {
role_name_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", role_name_count);
} else {
original_display_order = frm.doc.display_order;
}
});
//for Module Master
// frappe.db.get_list('Module Master', {
// fields: ['module_name', 'name'],
// filters: {
// }
// }).then(records => {
frappe.call({
method: "smart_service.masters.doctype.role_master.role_master.get_module_names",
args: { vehicle: frm.doc.vehicle, language_label: frm.doc.language_label, publish_type: frm.doc.publish_type },
callback: function (r) {
if (r.message) {
let res = cur_frm.fields_dict.module_master_html.$wrapper.empty()
let module_html = "<div class='module-container' style='float:left;display:flex'>"
module_html ="<div class='row' style='margin-left:5px !important;'>"
r.message.map(val => {
if (!frm.is_new() &&frm.doc.modules &&frm.doc.modules.includes(val.module_name) ) {
module_html += "<div class='col-2' style='padding-left:0px !important;padding-right:0px !important'>"
module_html += "<input type='checkbox' id=" +"'"+ val.name +"'"+ " name='vehicle1' value=" +"'"+ val.module_name +"'"+ " checked>"
module_html += "<label for=" + val.name + " style='padding-right:20px'>" + val.module_name + "</label></div>"
} else {
module_html += "<div class='col-2' style='padding-left:0px !important;padding-right:0px !important'>"
module_html += "<input type='checkbox' id=" +"'"+ val.name +"'"+ " name='vehicle1' value=" +"'"+ val.module_name +"'"+ " >"
module_html += "<label for=" + val.name + " style='padding-right:20px'>" + val.module_name + "</label></div>"
}
})
res.append(module_html)
}
}
})
},
after_save:function(frm){
cur_frm.refresh_fields("display_order")
},
validate: function (frm) {
//check html if has Module name value
var val = ""
$(':checkbox:checked').each(function (i) {
let value = $(this).val();
val += $(this).val() + ","
});
val = val.substring(0, val.length - 1);
frm.set_value('modules', val);
cur_frm.refresh_fields();
//For Display Order
cur_frm.refresh_fields("display_order")
// console.log(module_name_count,"----",original_display_order)
display_order_validation(frm, role_name_count, original_display_order,frm.doc.role)
}
});

96
smart_service/masters/doctype/role_master/role_master.json

@ -0,0 +1,96 @@
{
"_liked_by": "[\"Administrator\"]",
"actions": [],
"allow_rename": 1,
"autoname": "format:{role}",
"creation": "2023-07-19 13:42:52.880565",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"role",
"module_name_configuration",
"module_master_html",
"column_break_ffrrr",
"active_status",
"display_order",
"my_id",
"modules"
],
"fields": [
{
"fieldname": "role",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Role",
"reqd": 1
},
{
"fieldname": "column_break_ffrrr",
"fieldtype": "Column Break"
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "display_order",
"fieldtype": "Int",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Display Order"
},
{
"fieldname": "my_id",
"fieldtype": "Int",
"hidden": 1,
"in_list_view": 1,
"label": "My ID"
},
{
"fieldname": "module_master_html",
"fieldtype": "HTML",
"label": "Module Master"
},
{
"fieldname": "module_name_configuration",
"fieldtype": "Heading",
"label": "Module Name Configuration"
},
{
"fieldname": "modules",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Modules"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-07-21 15:15:43.988229",
"modified_by": "Administrator",
"module": "Masters",
"name": "Role Master",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "role"
}

25
smart_service/masters/doctype/role_master/role_master.py

@ -0,0 +1,25 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class RoleMaster(Document):
def validate(self):
if self.role:
self.role = self.role.strip()
def autoname(self):
if self.is_new():
count = frappe.db.sql(
'''select max(my_id) as max_count from `tabRole Master`;''')
if count[0][0] is not None:
self.my_id = count[0][0] + 1
else:
self.my_id = 1
@ frappe.whitelist()
def get_module_names():
data = frappe.db.sql(f'''
select name,module_name from `tabModule Master`''', as_dict=1)
return data

8
smart_service/masters/doctype/role_master/test_role_master.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestRoleMaster(unittest.TestCase):
pass

3
smart_service/modules.txt

@ -1,4 +1,5 @@
Add Ons
Masters
Reports
Transactions
Transactions
Phase-2

0
smart_service/phase_2/__init__.py

0
smart_service/phase_2/doctype/__init__.py

0
smart_service/phase_2/doctype/feature_finder/__init__.py

527
smart_service/phase_2/doctype/feature_finder/feature_finder.js

@ -0,0 +1,527 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
var click_count = 0;
var original_display_order = 0;
var vehicle_count = 0;
var filter_value = 0
frappe.ui.form.on('Feature Finder', {
refresh: function (frm) {
// filter_value = "SOP"
// set_default_tab(frm,filter_value)
custom_tab_html(frm)
set_display_order(frm)
show_images(frm)
},
onload: function (frm) {
// filter_value = "SOP"
// set_default_tab(frm,filter_value)
custom_tab_html(frm)
set_display_order(frm)
show_images(frm)
},
variant: function (frm) {
set_display_order(frm)
},
features_names:function(frm){
if(frm.doc.features_names){
frappe.db.get_list('Feature Finder Master', {
fields: ['name'],
filters: {
feature_name: frm.doc.feature_name,
vehicle:frm.doc.vehicle
}
}).then(records => {
frm.doc.feature_name = records[0].name
cur_frm.refresh_fields("feature_name")
})
}
},
create_feature_finder_images: function (frm) {
if (click_count == 0) {
frm.toggle_display('feature_finder_images', true)
click_count = 1
} else {
frm.toggle_display('feature_finder_images', false)
click_count = 0
}
},
language: function (frm) {
if (frm.doc.language == "en") {
frm.toggle_display('translated_feature_name', false)
frm.doc.translated_feature_name = ""
cur_frm.refresh_fields("translated_feature_name")
} else {
frm.toggle_display('translated_feature_name', true)
}
},
// feature_type: function (frm) {
// if (frm.doc.feature_type == "Post VIN Cutoff") {
// frm.toggle_display('post_vin_cutoff_id', true)
// }
// else {
// frm.toggle_display('post_vin_cutoff_id', false)
// }
// },
validate: function (frm) {
if (frm.doc.language == "en") {
frm.doc.translated_feature_name = ""
cur_frm.refresh_fields("translated_feature_name")
}
if (frm.doc.display_order && frm.doc.name && !frm.is_new()) {
//***check if there is same display_order
frappe.db.get_list('Feature Finder', {
fields: ['display_order', 'name'],
filters: {
display_order: frm.doc.display_order,
name: ["!=", frm.doc.name],
variant: frm.doc.variant,
language: frm.doc.language,
}
}).then(records => {
if (records.length) {
frappe.db.set_value('Feature Finder', records[0].name, {
display_order: original_display_order
}).then(r => {
let doc = r.message;
frappe.show_alert({
message: __('Swapped display order with: ' + records[0].name),
indicator: 'green'
}, 5);
});
} else {
// if (frm.doc.display_order >= vehicle_count) {
// let display_vehicle_count = vehicle_count - 1;
// msgprint('There are only ' + display_vehicle_count + " " + frm.doc.doctype);
// frappe.validated = false;
// }
}
});
}
},
after_save: function (frm) {
cur_frm.refresh_fields("display_order")
frm.reload_doc()
}
});
function show_images(frm) {
var res = $(cur_frm.fields_dict.image_html.wrapper).empty();
if (cur_frm.doc.feature_finder_images && cur_frm.doc.feature_finder_images.length > 0) {
var img_html = ""
img_html += "<div style='height: 300px;overflow-y: auto;overflow-x: hidden;border:1px solid var(--table-border-color);margin: 5px 0px 10px 0px;'><div style='padding: 5px;' class='row'>"
cur_frm.doc.feature_finder_images.forEach((val) =>
img_html += "<div class='col-3' style='padding-top:13px;'><img src=" + "'" + val.image + "'" + "></div>"
);
img_html += "</div></div>"
$(res).append(img_html)
}
}
function custom_tab_html(frm){
// $('[data-fieldname="specification"]').show()
// $('[data-fieldname="feature_finder_images"]').show()
// $('[data-fieldname="feature_finder_content"]').show()
// $('[data-fieldname="specification"]').css('margin-bottom','unset')
// $('[data-fieldname="specification"]').css('border-right','1px solid var(--table-border-color)')
// $('[data-fieldname="specification"]').css('border-left','1px solid var(--table-border-color)')
// $('[data-fieldname="specification"]').css('padding-right','20px')
// $('[data-fieldname="specification"]').css('padding-left','20px')
// $('[data-fieldname="feature_finder_images"]').css('margin-bottom','unset')
// $('[data-fieldname="feature_finder_images"]').css('border-right','1px solid var(--table-border-color)')
// $('[data-fieldname="feature_finder_images"]').css('border-left','1px solid var(--table-border-color)')
// $('[data-fieldname="feature_finder_images"]').css('padding-right','20px')
// $('[data-fieldname="feature_finder_images"]').css('padding-left','20px')
// $('[data-fieldname="feature_finder_content"]').css('border-right','1px solid var(--table-border-color)')
// $('[data-fieldname="feature_finder_content"]').css('border-left','1px solid var(--table-border-color)')
// $('[data-fieldname="feature_finder_content"]').css('border-bottom','1px solid var(--table-border-color)')
// $('[data-fieldname="feature_finder_content"]').css('padding-right','20px')
// $('[data-fieldname="feature_finder_content"]').css('padding-left','20px')
var res = $(cur_frm.fields_dict.test_html.wrapper).empty();
var ret = '<div class="main"><div class="custom_tab style="border:1px solid var(--table-border-color);"><ul class="nav nav-tabs" role="tablist">'
if(frm.doc.post_vin_cutoff_id_tab.length>0){
ret += '<li class="nav-item">'
ret += '<a class="nav-link active" id="SOP" data-toggle="tab" role="tab" value="SOP">SOP</a>'
ret += '</li>'
frm.doc.post_vin_cutoff_id_tab.map(val => {
ret += '<li class="nav-item">'
ret += '<a class="nav-link" id="'+ val.post_vin_cutoff_name+'" value='+val.post_vin_cutoff_name+' data-toggle="tab" role="tab">PV-'+val.post_vin_cutoff_name+'</a>'
ret += '</li>'
})
//table html
}
ret += '</div>'
res.append(ret)
res.append(`<style>.custom_tab{border:1px solid var(--table-border-color);}.nav-tabs .nav-item.show .nav-link, .nav-tabs .nav-link.active {background-color:lavender !important;}.nav-tabs {
border-bottom:none !important;}.specification_bl{margin:10px;}.main{border: 1px solid var(--table-border-color);margin:15px 0px 15px 0px}.spec_custom_add{margin:10px 0px 0px 0px}</style>`)
$(res).find('.main').append(`<div class="specification_bl"></div>`)
var specification =""
specification = frm.doc.specification.filter(o => o.feature_type == "SOP")
var spec_dialog_value = ""
var nav_spec = {}
nav_spec.feature_type = "SOP"
all_tabs()
$('.main').find('.nav-link').click(function(event){
console.log($(this)[0].id)
if($(this)[0].id=="SOP"){
nav_spec.feature_type= "SOP"
nav_spec.post_vin_cutoff_name = ""
specification = frm.doc.specification.filter(o => o.feature_type == $(this)[0].id)
}
else{
nav_spec.feature_type= "Post Vin CutOff"
nav_spec.post_vin_cutoff_name = $(this)[0].id
specification = frm.doc.specification.filter(o => o.post_vin_cutoff_name == $(this)[0].id)
}
all_tabs()
})
function all_tabs(){
var spec_custom_dt = ""
spec_custom_dt += `<label class="control-label">Specification</label><table class="table table-bordered table-editable" style='margin:0px !important'>
<thead>
<tr>
<th style="width: 7%;" class="specifiction"><input type="checkbox" id="checkAll"' class="grid-row-check pull-left"><span class='spec_check'>No</span></th>
<th>Specification</th>
<th>Value</th>
<th>Active Status</th>
<th>Feature Type</th>
<th>Post Vin CutOff Name</th>
<th><a><svg class="icon icon-sm" style="filter: opacity(0.5)">
<use class="" href="#icon-setting-gear"></use>
</svg></a></th>
</tr>
</thead>`
spec_custom_dt += "<tbody>"
var specification_count = 0
specification.map(val => {
specification_count += 1
spec_custom_dt += '<tr>'
spec_custom_dt += '<td style="width: 7%;"><input id='+val.name+' type="checkbox" class="check grid-row-check pull-left"><span class="spec_check">'+specification_count+'</span></td>'
spec_custom_dt += '<td>'+val.specification+'</td>'
spec_custom_dt += '<td>'+val.value+'</td>'
spec_custom_dt += '<td>'+val.active_status+'</td>'
spec_custom_dt += '<td>'+val.feature_type+'</td>'
if(val.post_vin_cutoff_name){
spec_custom_dt += '<td>'+val.post_vin_cutoff_name+'</td>'
}
else{
spec_custom_dt += '<td> </td>'
}
spec_custom_dt += '<td id='+ val.name+' class="spec_edit_row"><a><svg class="icon icon-xs" style=""><use class="" href="#icon-edit"></use></svg>Edit</a></td>'
spec_custom_dt += '</tr>'
})
spec_custom_dt += '</tbody>'
spec_custom_dt += '</table>'
spec_custom_dt += '<button class="btn btn-xs btn-secondary grid-add-row spec_custom_delete">Delete</button>'
spec_custom_dt += '<button class="btn btn-xs btn-secondary grid-add-row spec_custom_add">Add Row</button>'
spec_custom_dt += '</div>'
$(res).find('.specification_bl').empty()
$(res).find('.specification_bl').append(spec_custom_dt)
$(res).append(`<style>.spec_check{padding:0px 5px 0px 5px !important}.spec_custom_delete{margin:10px 10px 0px 0px;background-color:red !important;color:#fff !important;display:none}</style>`)
// $(res).append(spec_custom_dt)
$(res).find('.specification_bl').find('.spec_custom_add').click(function(event){
spec_dialog_value = ""
spec_dialog_value = nav_spec
spec_dialog_view()
})
$(res).find('.specification_bl').find('.spec_edit_row').click(function(event){
spec_dialog_value = frm.doc.specification.filter(o => o.name == $(this)[0].id)[0]
spec_dialog_view()
})
$(res).find('.specification_bl').find('.specifiction').find('input[type=checkbox]').change(function() {
$(".check").prop('checked', $(this).prop('checked'));
$(res).find('.specification_bl').find('.spec_custom_delete').css("display","inline-block")
})
$(res).find('.specification_bl').find('.spec_custom_delete').click(function(event){
var arr = []
$(res).find('.specification_bl').find("input[type=checkbox]").each(function () {
var self = $(this);
if (self.is(':checked')) {
console.log(self.attr("id"),"sdcdcd")
arr.push(self.attr("id"));
}
});
arr = arr.slice(1)
console.log(arr,"-------------------")
frappe.call({
method: "smart_service.phase_2.doctype.feature_finder.feature_finder.delete_spec_data",
args: {
values:arr
},
callback:function(r){
console.log(r.message.status,'-rmessage')
if(r.message.status=="success"){
cur_frm.reload_doc()
}
}
})
})
}
function spec_dialog_view(){
let spec_dia = new frappe.ui.Dialog({
title: 'Enter details',
fields: [
{
label: 'Name',
fieldname: 'name',
fieldtype: 'Data',
default:spec_dialog_value.name,
hidden:1
},
{
label: 'Specification',
fieldname: 'specification',
fieldtype: 'Link',
options:"Feature Finder Specification Master",
default:spec_dialog_value.specification
},
{
label: 'Valuee',
fieldname: 'value',
fieldtype: 'Data',
default:spec_dialog_value.value
},
{
label: 'Active Status',
fieldname: 'active_status',
fieldtype: 'Select',
options:"Active\nInactive",
default:spec_dialog_value.active_status
},
{
label: 'Feature Type',
fieldname: 'feature_type',
fieldtype: 'Data',
default:spec_dialog_value.feature_type,
read_only:1
},
{
label: 'Post Vin Cutoff Name',
fieldname: 'post_vin_cutoff_name',
fieldtype: 'Data',
default:spec_dialog_value.post_vin_cutoff_name,
depends_on:"eval:doc.feature_type=='Post Vin CutOff'",
},
],
// size: 'small', // small, large, extra-large
primary_action_label: 'Submit',
primary_action(values) {
console.log(values,"values");
if (values){
frappe.call({
method: "smart_service.phase_2.doctype.feature_finder.feature_finder.insert_spec_data",
args: {
doc_name:frm.doc.name,
values:values
},
callback:function(r){
console.log(r.message.status,'-rmessage')
if(r.message.status=="success"){
cur_frm.reload_doc()
}
}
})
}
spec_dia.hide();
}
});
console.log(spec_dia,"spec_dia")
spec_dia.show();
}
// $("#specification").click(function(){
// $('[data-fieldname="specification"]').show()
// $('[data-fieldname="feature_finder_images"]').hide()
// $('[data-fieldname="feature_finder_content"]').hide()
// });
// $("#images").click(function(){
// $('[data-fieldname="specification"]').hide()
// $('[data-fieldname="feature_finder_images"]').show()
// $('[data-fieldname="feature_finder_content"]').hide()
// });
// $("#content").click(function(){
// $('[data-fieldname="specification"]').hide()
// $('[data-fieldname="feature_finder_images"]').hide()
// $('[data-fieldname="feature_finder_content"]').show()
// });
$('.nav-link').click(function(event){
// console.log($(this)[0].id)
// filter_value = $(this)[0].id
// frappe.call({
// method: "smart_service.phase_2.doctype.feature_finder.feature_finder.get_list_data",
// args: {
// name:frm.doc.name,
// val:filter_value
// },
// callback: function (r) {
// console.log(r.message)
// frm.doc.specification = []
// frm.doc.feature_finder_images = []
// frm.doc.feature_finder_content = []
// cur_frm.refresh_fields("specification")
// cur_frm.refresh_fields("feature_finder_images")
// cur_frm.refresh_fields("feature_finder_content")
// frm.doc.specification= r.message[0]
// frm.doc.feature_finder_images = r.message[1]
// frm.doc.feature_finder_content = r.message[2]
// cur_frm.refresh_fields("specification")
// }
// })
})
}
// function set_default_tab(frm,filter_value){
// frappe.call({
// method: "smart_service.phase_2.doctype.feature_finder.feature_finder.get_list_data",
// args: {
// name:frm.doc.name,
// val:filter_value
// },
// callback: function (r) {
// console.log(r.message)
// frm.doc.specification = []
// cur_frm.refresh_fields("specification")
// frm.doc.specification= r.message[0]
// cur_frm.refresh_fields("specification")
// }
// })
// }
function set_display_order(frm) {
if(frm.doc.variant){
frm.toggle_display('feature_name', true)
frm.toggle_display('features_names', true)
}else{
frm.toggle_display('feature_name', false)
frm.toggle_display('features_names', false)
}
// if (frm.doc.feature_type == "Post VIN Cutoff") {
// frm.toggle_display('post_vin_cutoff_id', true)
// }
// else {
// frm.toggle_display('post_vin_cutoff_id', false)
// }
if(frm.doc.variant && frm.doc.vehicle){
frappe.call({
method: "smart_service.phase_2.doctype.feature_finder.feature_finder.get_feature_list",
args: {
vehicle:frm.doc.vehicle
},
callback: function (r) {
frm.set_df_property('features_names', 'options', r.message);
frm.refresh_field('features_names')
}
})
}
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Feature Finder', {
filters: {
"variant": cur_frm.doc.variant,
"language": frm.doc.language,
"feature_name": frm.doc.feature_name,
// "feature_type":frm.doc.feature_type
}
}).then(count => {
vehicle_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", vehicle_count);
} else {
original_display_order = frm.doc.display_order;
}
});
}
frappe.ui.form.on('Feature Finder Specification', {
// post_vin_cutoff_name: function(frm){
// frm.fields_dict.specification.grid.grid_rows.forEach((row) => {
// if (row.doc.post_vin_cutoff_name == filter_value) {
// $("div[data-fieldname=specification]").find('div.grid-row[data-idx="' + row.doc.idx + '"]').hide();
// } else {
// $("div[data-fieldname=specification]").find('div.grid-row[data-idx="' + row.doc.idx + '"]').show();
// }
// });
// refresh_field("specification");
// },
specification_add: function(frm,cdt,cdn){
console.log(locals[cdt][cdn],"locals[cdt][cdn]")
var child2 = locals[cdt][cdn];
child2.post_vin_cutoff_name = filter_value
refresh_field("specification");
}
})
frappe.ui.form.on('Feature Finder Content', {
feature_finder_content_add: function(frm,cdt,cdn){
var child = locals[cdt][cdn];
child.post_vin_cutoff_name = filter_value
refresh_field("feature_finder_content");
},
})
frappe.ui.form.on('Feature Finder Images', {
feature_finder_images_add: function(frm,cdt,cdn){
var child = locals[cdt][cdn];
child.post_vin_cutoff_name = filter_value
refresh_field("feature_finder_images");
},
})

171
smart_service/phase_2/doctype/feature_finder/feature_finder.json

@ -0,0 +1,171 @@
{
"_comments": "[]",
"_liked_by": "[]",
"actions": [],
"allow_rename": 1,
"autoname": "format:{variant}-{features_names}-{language}",
"creation": "2023-07-21 13:31:57.705945",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"variant",
"language",
"display_order",
"active_status",
"column_break_mmuuc",
"vehicle",
"feature_name",
"features_names",
"feature_category",
"section_break_u9bx1",
"image_html",
"create_feature_finder_images",
"post_vin_cutoff_id_tab",
"test_html",
"specification",
"feature_finder_images",
"feature_finder_content"
],
"fields": [
{
"fetch_from": "variant.vehicle",
"fieldname": "vehicle",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Vehicle",
"read_only": 1,
"reqd": 1
},
{
"fieldname": "language",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Language",
"options": "Custom Languages",
"reqd": 1,
"set_only_once": 1
},
{
"fieldname": "column_break_mmuuc",
"fieldtype": "Column Break"
},
{
"fieldname": "variant",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Variant",
"options": "Variant Mapping",
"reqd": 1
},
{
"depends_on": "eval:doc.variant!=\"\"",
"fieldname": "feature_name",
"fieldtype": "Link",
"hidden": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Feature Name",
"options": "Feature Finder Master",
"set_only_once": 1
},
{
"fieldname": "feature_finder_images",
"fieldtype": "Table",
"hidden": 1,
"label": "Feature Finder Images",
"options": "Feature Finder Images"
},
{
"fieldname": "feature_finder_content",
"fieldtype": "Table",
"hidden": 1,
"label": "Feature Finder Content",
"options": "Feature Finder Content"
},
{
"fieldname": "section_break_u9bx1",
"fieldtype": "Section Break"
},
{
"fieldname": "image_html",
"fieldtype": "HTML",
"label": "Image HTML"
},
{
"fieldname": "create_feature_finder_images",
"fieldtype": "Button",
"label": "Add Feature Finder Images"
},
{
"fieldname": "display_order",
"fieldtype": "Int",
"in_list_view": 1,
"label": "Display Order",
"read_only_depends_on": "eval:doc.language!=\"en\""
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"label": "Active Status",
"options": "Active\nIn Active"
},
{
"fieldname": "specification",
"fieldtype": "Table",
"hidden": 1,
"label": "Specification",
"options": "Feature Finder Specification"
},
{
"fetch_from": "feature_name.feature_category",
"fieldname": "feature_category",
"fieldtype": "Data",
"label": "Feature Category"
},
{
"depends_on": "eval:doc.variant!=\"\"",
"fieldname": "features_names",
"fieldtype": "Select",
"label": "Feature Name",
"reqd": 1
},
{
"fieldname": "test_html",
"fieldtype": "HTML",
"label": "Test Html"
},
{
"fieldname": "post_vin_cutoff_id_tab",
"fieldtype": "Table",
"label": "Post Vin Cutoff ID",
"options": "Post Vin Cutoff ID"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-07 13:10:48.720447",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Feature Finder",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC"
}

131
smart_service/phase_2/doctype/feature_finder/feature_finder.py

@ -0,0 +1,131 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
import json
class FeatureFinder(Document):
# def validate(self):
# if self.feature_name and self.feature_type=="SOP":
# check_existing = frappe.db.sql(f"""select name from `tabFeature Finder` where feature_name='{self.feature_name}' and feature_type='SOP'
# and name!='{self.name}'""",as_dict=1)
# if len(check_existing)>0:
# frappe.throw("This Feature Name and Feature Type already exists")
# def autoname(self):
# if self.feature_type == "SOP":
# self.name = self.variant+"-"+self.features_names + \
# "-"+self.language+"-"+self.feature_type
# else:
# self.name = self.variant+"-"+self.features_names+"-" + \
# self.language+"-"+self.feature_type+"-"+self.post_vin_cutoff_id
def validate(self):
try:
if self.is_new():
if self.variant and self.language and self.feature_name:
check_exe = frappe.db.get_list("Feature Finder",
filters={"variant": self.variant, "language": "en",
"feature_name": self.feature_name,
"name": ["!=", self.name]},
fields={"name", "language", "display_order", "active_status"})
if check_exe:
if self.language != "en":
for d in check_exe:
self.display_order = d['display_order']
self.active_status = d['active_status']
if not check_exe:
if self.language != "en":
frappe.throw("First language will be english only")
# if len(self.specification)>0:
# specification = frappe.db.sql(f"""select * from `tabFeature Finder Specification` where parent = '{self.name}'""",as_dict=1)
# for d in self.specification:
# specification.append(d)
# set_idx = 0
# for k in specification:
# set_idx +=1
# k['']
except Exception as e:
raise e
def on_update(self):
if self.language == "en":
try:
check_exe = frappe.db.get_list("Feature Finder",
filters={"variant": self.variant, "language": ["!=", "en"],
"feature_name": self.feature_name,
"name": ["!=", self.name]},
fields={"name", "language", "display_order", "active_status"})
if check_exe:
for i in check_exe:
res = frappe.get_doc(
"Feature Finder", i['name'])
res.display_order = self.display_order
res.active_status = self.active_status
res.save()
except Exception as e:
raise e
@frappe.whitelist()
def get_feature_list(vehicle):
features_list = frappe.db.sql(f"""select feature_name from `tabFeature Finder Master` where vehicle='{vehicle}'""",as_list=1)
return features_list
@frappe.whitelist()
def get_list_data(name,val):
specification = frappe.db.sql(f"""select *,'Feature Finder Specification' as doctype from `tabFeature Finder Specification` where parent = '{name}' and post_vin_cutoff_name='{val}'""",as_dict=1)
feature_finder_images = frappe.db.sql(f"""select * from `tabFeature Finder Images` where parent = '{name}' and post_vin_cutoff_name='{val}'""",as_dict=1)
feature_finder_content = frappe.db.sql(f"""select * from `tabFeature Finder Content` where parent = '{name}' and post_vin_cutoff_name='{val}'""",as_dict=1)
return specification,feature_finder_images,feature_finder_content
@frappe.whitelist()
def insert_spec_data(doc_name,values):
try:
val = json.loads(values)
if val.get('name')!=None:
doc = frappe.get_doc("Feature Finder Specification",val['name'])
doc.specification = val.get('specification')
doc.value = val.get('value')
doc.active_status = val.get('active_status')
doc.feature_type = val.get('feature_type')
doc.save()
frappe.db.commit()
else:
res = frappe.get_doc("Feature Finder",doc_name)
res.append("specification",val)
res.save()
return {"status":"success"}
except Exception as e:
frappe.log_error("insert_spec_data",str(e))
return {"status":"failure"}
@frappe.whitelist()
def delete_spec_data(values):
try:
val = json.loads(values)
if len(val)>0:
for d in val:
frappe.delete_doc("Feature Finder Specification",d)
frappe.db.commit()
return {"status":"success"}
except Exception as e:
frappe.log_error("delete_spec_data",str(e))
# res.append("specification",{
# "specification":val.get('specification'),
# "value":val.get('value'),
# "active_status":val.get('active_status'),
# "feature_type":val.get('feature_type')
# })

8
smart_service/phase_2/doctype/feature_finder/test_feature_finder.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestFeatureFinder(unittest.TestCase):
pass

0
smart_service/phase_2/doctype/feature_finder_category_master/__init__.py

8
smart_service/phase_2/doctype/feature_finder_category_master/feature_finder_category_master.js

@ -0,0 +1,8 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
frappe.ui.form.on('Feature Finder Category Master', {
// refresh: function(frm) {
// }
});

59
smart_service/phase_2/doctype/feature_finder_category_master/feature_finder_category_master.json

@ -0,0 +1,59 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{feature_name}",
"creation": "2023-08-04 11:36:36.503213",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"feature_category",
"feature_name"
],
"fields": [
{
"fieldname": "feature_category",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Feature Category",
"reqd": 1,
"set_only_once": 1
},
{
"fieldname": "feature_name",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Feature Name",
"reqd": 1,
"set_only_once": 1,
"unique": 1
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-04 15:35:06.625979",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Feature Finder Category Master",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"search_fields": "feature_name",
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "feature_name"
}

8
smart_service/phase_2/doctype/feature_finder_category_master/feature_finder_category_master.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class FeatureFinderCategoryMaster(Document):
pass

8
smart_service/phase_2/doctype/feature_finder_category_master/test_feature_finder_category_master.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestFeatureFinderCategoryMaster(unittest.TestCase):
pass

0
smart_service/phase_2/doctype/feature_finder_content/__init__.py

51
smart_service/phase_2/doctype/feature_finder_content/feature_finder_content.json

@ -0,0 +1,51 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-07-21 13:55:18.779535",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"content",
"active_status",
"feature_type",
"post_vin_cutoff_name"
],
"fields": [
{
"fieldname": "content",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Content"
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "feature_type",
"fieldtype": "Data",
"label": "Feature Type"
},
{
"fieldname": "post_vin_cutoff_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Post Vin Cutoff Name"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-08-04 17:42:23.562696",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Feature Finder Content",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

8
smart_service/phase_2/doctype/feature_finder_content/feature_finder_content.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class FeatureFinderContent(Document):
pass

0
smart_service/phase_2/doctype/feature_finder_disclaimer/__init__.py

38
smart_service/phase_2/doctype/feature_finder_disclaimer/feature_finder_disclaimer.json

@ -0,0 +1,38 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-07-21 14:37:31.662625",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"content",
"active_status"
],
"fields": [
{
"fieldname": "content",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Content"
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Active Status",
"options": "Active\nInactive"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-07-21 15:51:05.822149",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Feature Finder Disclaimer",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

8
smart_service/phase_2/doctype/feature_finder_disclaimer/feature_finder_disclaimer.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class FeatureFinderDisclaimer(Document):
pass

0
smart_service/phase_2/doctype/feature_finder_images/__init__.py

51
smart_service/phase_2/doctype/feature_finder_images/feature_finder_images.json

@ -0,0 +1,51 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-07-21 13:53:04.565458",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"image",
"active_status",
"feature_type",
"post_vin_cutoff_name"
],
"fields": [
{
"fieldname": "image",
"fieldtype": "Attach",
"in_list_view": 1,
"label": "Image"
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "feature_type",
"fieldtype": "Data",
"label": "Feature Type"
},
{
"fieldname": "post_vin_cutoff_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Post Vin Cutoff Name"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-08-04 17:42:08.111627",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Feature Finder Images",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

8
smart_service/phase_2/doctype/feature_finder_images/feature_finder_images.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class FeatureFinderImages(Document):
pass

0
smart_service/phase_2/doctype/feature_finder_master/__init__.py

8
smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.js

@ -0,0 +1,8 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
frappe.ui.form.on('Feature Finder Master', {
// refresh: function(frm) {
// }
});

95
smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.json

@ -0,0 +1,95 @@
{
"_comments": "[]",
"_liked_by": "[]",
"actions": [],
"allow_rename": 1,
"autoname": "format:{vehicle}-{feature_name}-{language}",
"creation": "2023-07-21 14:37:42.551453",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"feature_name",
"feature_category",
"column_break_5ksna",
"feature_pdf",
"section_break_lyzco",
"feature_finder_disclaimer",
"vehicle",
"language"
],
"fields": [
{
"fieldname": "feature_name",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Feature Name",
"options": "Feature Finder Category Master",
"reqd": 1,
"set_only_once": 1
},
{
"fieldname": "feature_pdf",
"fieldtype": "Attach",
"label": "PDF"
},
{
"fieldname": "feature_finder_disclaimer",
"fieldtype": "Table",
"label": "Feature Finder Disclaimer",
"options": "Feature Finder Disclaimer"
},
{
"fieldname": "column_break_5ksna",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_lyzco",
"fieldtype": "Section Break"
},
{
"fieldname": "vehicle",
"fieldtype": "Link",
"label": "Vehicle",
"options": "Vehicle"
},
{
"fieldname": "language",
"fieldtype": "Link",
"label": "Language",
"options": "Custom Languages"
},
{
"fetch_from": "feature_name.feature_category",
"fieldname": "feature_category",
"fieldtype": "Data",
"label": "Feature Category"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-04 17:45:51.699581",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Feature Finder Master",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"search_fields": "feature_name",
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "feature_name"
}

8
smart_service/phase_2/doctype/feature_finder_master/feature_finder_master.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class FeatureFinderMaster(Document):
pass

8
smart_service/phase_2/doctype/feature_finder_master/test_feature_finder_master.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestFeatureFinderMaster(unittest.TestCase):
pass

0
smart_service/phase_2/doctype/feature_finder_specification/__init__.py

58
smart_service/phase_2/doctype/feature_finder_specification/feature_finder_specification.json

@ -0,0 +1,58 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-08-03 12:55:07.973284",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"specification",
"value",
"active_status",
"feature_type",
"post_vin_cutoff_name"
],
"fields": [
{
"fieldname": "specification",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Specification",
"options": "Feature Finder Specification Master"
},
{
"fieldname": "value",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Value"
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "feature_type",
"fieldtype": "Data",
"label": "Feature Type"
},
{
"fieldname": "post_vin_cutoff_name",
"fieldtype": "Data",
"label": "Post Vin Cutoff Name"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-08-04 13:05:42.300134",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Feature Finder Specification",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

8
smart_service/phase_2/doctype/feature_finder_specification/feature_finder_specification.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class FeatureFinderSpecification(Document):
pass

0
smart_service/phase_2/doctype/feature_finder_specification_master/__init__.py

8
smart_service/phase_2/doctype/feature_finder_specification_master/feature_finder_specification_master.js

@ -0,0 +1,8 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
frappe.ui.form.on('Feature Finder Specification Master', {
// refresh: function(frm) {
// }
});

59
smart_service/phase_2/doctype/feature_finder_specification_master/feature_finder_specification_master.json

@ -0,0 +1,59 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{specification}",
"creation": "2023-08-03 11:06:15.559188",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"specification",
"active_status",
"my_id"
],
"fields": [
{
"fieldname": "specification",
"fieldtype": "Data",
"label": "Specification",
"reqd": 1,
"set_only_once": 1
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "my_id",
"fieldtype": "Int",
"hidden": 1,
"in_list_view": 1,
"label": "My Id"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-03 16:03:25.491315",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Feature Finder Specification Master",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC"
}

15
smart_service/phase_2/doctype/feature_finder_specification_master/feature_finder_specification_master.py

@ -0,0 +1,15 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class FeatureFinderSpecificationMaster(Document):
def autoname(self):
if self.is_new():
count = frappe.db.sql(
'''select max(my_id) as max_count from `tabFeature Finder Specification Master`;''')
if count[0][0] is not None:
self.my_id = count[0][0] + 1
else:
self.my_id = 1

8
smart_service/phase_2/doctype/feature_finder_specification_master/test_feature_finder_specification_master.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestFeatureFinderSpecificationMaster(unittest.TestCase):
pass

0
smart_service/phase_2/doctype/module_publish_mapping/__init__.py

8
smart_service/phase_2/doctype/module_publish_mapping/module_publish_mapping.js

@ -0,0 +1,8 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
frappe.ui.form.on('Module Publish Mapping', {
// refresh: function(frm) {
// }
});

131
smart_service/phase_2/doctype/module_publish_mapping/module_publish_mapping.json

@ -0,0 +1,131 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{vehicle}-{variant}-{language}",
"creation": "2023-08-07 12:44:24.978007",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"vehicle",
"variant",
"language",
"automotive_system",
"tsb",
"fsa",
"tekalert",
"feature_finder",
"repairservice_check_sheet",
"mahindra_special_tool_information",
"training_information",
"qwik_service",
"pdi_inspection",
"torque_information_nm"
],
"fields": [
{
"fieldname": "vehicle",
"fieldtype": "Data",
"label": "Vehicle"
},
{
"fieldname": "variant",
"fieldtype": "Data",
"label": "Variant"
},
{
"fieldname": "language",
"fieldtype": "Data",
"label": "Language"
},
{
"default": "0",
"fieldname": "automotive_system",
"fieldtype": "Check",
"label": "Automotive System"
},
{
"default": "0",
"fieldname": "tsb",
"fieldtype": "Check",
"label": "TSB"
},
{
"default": "0",
"fieldname": "fsa",
"fieldtype": "Check",
"label": "FSA"
},
{
"default": "0",
"fieldname": "tekalert",
"fieldtype": "Check",
"label": "TEKalert"
},
{
"default": "0",
"fieldname": "feature_finder",
"fieldtype": "Check",
"label": "Feature Finder"
},
{
"default": "0",
"fieldname": "repairservice_check_sheet",
"fieldtype": "Check",
"label": "Repair/Service Check Sheet"
},
{
"default": "0",
"fieldname": "mahindra_special_tool_information",
"fieldtype": "Check",
"label": "Mahindra Special Tool Information"
},
{
"default": "0",
"fieldname": "training_information",
"fieldtype": "Check",
"label": "Training Information"
},
{
"default": "0",
"fieldname": "qwik_service",
"fieldtype": "Check",
"label": "QWIK Service"
},
{
"default": "0",
"fieldname": "pdi_inspection",
"fieldtype": "Check",
"label": "PDI Inspection"
},
{
"default": "0",
"fieldname": "torque_information_nm",
"fieldtype": "Check",
"label": "Torque Information NM"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-07 12:52:27.310290",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Module Publish Mapping",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC"
}

8
smart_service/phase_2/doctype/module_publish_mapping/module_publish_mapping.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ModulePublishMapping(Document):
pass

8
smart_service/phase_2/doctype/module_publish_mapping/test_module_publish_mapping.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestModulePublishMapping(unittest.TestCase):
pass

0
smart_service/phase_2/doctype/mst_information_assets/__init__.py

56
smart_service/phase_2/doctype/mst_information_assets/mst_information_assets.json

@ -0,0 +1,56 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-08-04 12:57:30.766141",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"image",
"content",
"asset_type",
"active_status"
],
"fields": [
{
"depends_on": "eval:doc.asset_type==\"Image\"\n",
"fieldname": "image",
"fieldtype": "Attach",
"in_list_view": 1,
"label": "Image/Video",
"read_only_depends_on": "eval:doc.asset_type==\"\""
},
{
"fieldname": "content",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Content",
"read_only_depends_on": "eval:doc.asset_type==\"Image\"\n"
},
{
"fieldname": "asset_type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Asset Type",
"options": "\nImage\nVideo"
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Active Status",
"options": "Active\nInactive"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-08-04 16:19:50.891867",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "MST Information Assets",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

8
smart_service/phase_2/doctype/mst_information_assets/mst_information_assets.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class MSTInformationAssets(Document):
pass

0
smart_service/phase_2/doctype/post_vin_cutoff_id/__init__.py

37
smart_service/phase_2/doctype/post_vin_cutoff_id/post_vin_cutoff_id.json

@ -0,0 +1,37 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-08-04 13:43:23.238711",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"post_vin_cutoff_name",
"post_vin_cutoff_id"
],
"fields": [
{
"fieldname": "post_vin_cutoff_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Post Vin Cutoff Name"
},
{
"fieldname": "post_vin_cutoff_id",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Post Vin Cutoff ID"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-08-04 15:07:04.378340",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Post Vin Cutoff ID",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

8
smart_service/phase_2/doctype/post_vin_cutoff_id/post_vin_cutoff_id.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class PostVinCutoffID(Document):
pass

0
smart_service/phase_2/doctype/repair_service_child/__init__.py

8
smart_service/phase_2/doctype/repair_service_child/repair_service_child.js

@ -0,0 +1,8 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
frappe.ui.form.on('Repair Service Child', {
// refresh: function(frm) {
// }
});

52
smart_service/phase_2/doctype/repair_service_child/repair_service_child.json

@ -0,0 +1,52 @@
{
"_liked_by": "[\"Administrator\"]",
"actions": [],
"allow_rename": 1,
"creation": "2023-07-20 18:02:39.917427",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"complaint",
"active_status",
"remedial_action_ok",
"remedial_action_not_ok"
],
"fields": [
{
"fieldname": "active_status",
"fieldtype": "Select",
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "complaint",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Complaint"
},
{
"fieldname": "remedial_action_ok",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Remedial Action OK"
},
{
"fieldname": "remedial_action_not_ok",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Remedial Action Not OK"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-08-04 09:54:39.573005",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Repair Service Child",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

14
smart_service/phase_2/doctype/repair_service_child/repair_service_child.py

@ -0,0 +1,14 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class RepairServiceChild(Document):
def validate(self):
if self.complaint:
self.complaint = self.complaint.strip()
if self.remedial_action_ok:
self.remedial_action_ok = self.remedial_action_ok.strip()
if self.remedial_action_not_ok:
self.remedial_action_not_ok=self.remedial_action_not_ok.strip()

8
smart_service/phase_2/doctype/repair_service_child/test_repair_service_child.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestRepairServiceChild(unittest.TestCase):
pass

0
smart_service/phase_2/doctype/repair_service_mapping/__init__.py

103
smart_service/phase_2/doctype/repair_service_mapping/repair_service_mapping.js

@ -0,0 +1,103 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
var original_display_order = 0;
var vehicle_count = 0;
frappe.require('assets/smart_service/js/utils.js', () => { })
frappe.ui.form.on('Repair Service Mapping', {
onload: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Repair Service Mapping', {
filters: {
"vehicle": cur_frm.doc.vehicle,
"language": frm.doc.language
}
}).then(count => {
vehicle_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", vehicle_count);
} else {
original_display_order = frm.doc.display_order;
}
});
},
refresh: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Repair Service Mapping', {
filters: {
"vehicle": cur_frm.doc.vehicle,
"language": frm.doc.language
}
}).then(count => {
vehicle_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", vehicle_count);
} else {
original_display_order = frm.doc.display_order;
}
});
},
validate: function (frm) {
//For Display Order
cur_frm.refresh_fields("display_order")
// console.log(module_name_count,"----",original_display_order)
// if (frm.doc.display_order && frm.doc.name && !frm.is_new()) {
// //***check if there is same display_order
// frappe.db.get_list('Repair Service Mapping', {
// fields: ['display_order', 'name'],
// filters: {
// display_order: frm.doc.display_order,
// name: ["!=", frm.doc.name],
// vehicle: frm.doc.vehicle,
// language:frm.doc.language
// }
// }).then(records => {
// if (records.length) {
// frappe.db.set_value('Repair Service Mapping', records[0].name,{
// display_order: original_display_order
// }).then(r => {
// // console.log(records)
// let doc = r.message;
// frappe.show_alert({
// message: __('Swapped display order with: ' + records[0].name),
// indicator: 'green'
// }, 5);
// });
// } else {
// if (frm.doc.display_order >= vehicle_count) {
// let display_name_count = vehicle_count - 1;
// msgprint('There are only ' + display_name_count +" "+frm.doc.doctype);
// frappe.validated = false;
// }
// }
// });
// }
display_order_validation(frm, vehicle_count, original_display_order, frm.doc.vehicle)
},
after_save: function (frm) {
cur_frm.refresh_fields("display_order")
},
});

140
smart_service/phase_2/doctype/repair_service_mapping/repair_service_mapping.json

@ -0,0 +1,140 @@
{
"_comments": "[]",
"_liked_by": "[\"Administrator\"]",
"actions": [],
"allow_rename": 1,
"autoname": "format:{vehicle}-{check_list_name}-{language}",
"creation": "2023-07-21 16:05:07.941117",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"published",
"section_break_ci53z",
"vehicle",
"language",
"column_break_sjvew",
"check_list_name",
"translated_check_list_name",
"column_break_azh0p",
"active_status",
"display_order",
"section_break_ecyyc",
"description",
"my_id"
],
"fields": [
{
"default": "0",
"fieldname": "published",
"fieldtype": "Check",
"label": "Published"
},
{
"fieldname": "section_break_ci53z",
"fieldtype": "Section Break"
},
{
"fieldname": "vehicle",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Vehicle",
"options": "Vehicle",
"reqd": 1,
"set_only_once": 1
},
{
"fieldname": "language",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Language",
"options": "Custom Languages"
},
{
"fieldname": "column_break_sjvew",
"fieldtype": "Column Break"
},
{
"fieldname": "check_list_name",
"fieldtype": "Link",
"in_global_search": 1,
"in_standard_filter": 1,
"label": "Check List Name",
"options": "Repair Service Master",
"set_only_once": 1
},
{
"fieldname": "translated_check_list_name",
"fieldtype": "Data",
"in_global_search": 1,
"in_standard_filter": 1,
"label": "Translated Check List Name",
"mandatory_depends_on": "eval:doc.language!=\"en\"",
"read_only_depends_on": "eval:doc.language==\"en\""
},
{
"fieldname": "column_break_azh0p",
"fieldtype": "Column Break"
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"in_global_search": 1,
"in_standard_filter": 1,
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "display_order",
"fieldtype": "Int",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Display Order",
"read_only_depends_on": "eval: doc.language != 'en'"
},
{
"fieldname": "section_break_ecyyc",
"fieldtype": "Section Break"
},
{
"fieldname": "description",
"fieldtype": "Table",
"label": "Description",
"options": "Repair Service Child"
},
{
"fieldname": "my_id",
"fieldtype": "Int",
"hidden": 1,
"in_list_view": 1,
"label": "My Id",
"set_only_once": 1
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-04 09:54:00.221736",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Repair Service Mapping",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "check_list_name"
}

67
smart_service/phase_2/doctype/repair_service_mapping/repair_service_mapping.py

@ -0,0 +1,67 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class RepairServiceMapping(Document):
def validate(self):
if self.is_new():
count = frappe.db.sql(
'''select max(my_id) as max_count from `tabRepair Service Mapping`;''')
if count[0][0] is not None:
self.my_id = count[0][0] + 1
else:
self.my_id = 1
if self.vehicle:
self.vehicle = self.vehicle.strip()
try:
if self.is_new():
if self.vehicle and self.language and self.check_list_name:
check_exe = frappe.db.get_list("Repair Service Mapping",
filters={"vehicle": self.vehicle, "language": "en",
"check_list_name": self.check_list_name,
"name": ["!=", self.name]},
fields={"name", "language", "display_order", "active_status"})
if check_exe:
if self.language != "en":
for d in check_exe:
self.display_order = d['display_order']
self.active_status = d['active_status']
if not check_exe:
if self.language != "en":
frappe.throw("First language will be english only")
except Exception as e:
raise e
# def autoname(self):
# if self.is_new():
# count = frappe.db.sql('''select max(my_id) as max_count from `tabRepair Service Mapping`;''')
# if count[0][0] is not None:
# self.my_id = count[0][0] + 1
# else:
# self.my_id = 1
def on_update(self):
if self.language == "en":
try:
check_exe = frappe.db.get_list("Repair Service Mapping",
filters={"vehicle": self.vehicle, "language": ["!=", "en"],
"check_list_name": self.check_list_name,
"name": ["!=", self.name]},
fields={"name", "language", "display_order", "active_status"})
if check_exe:
for i in check_exe:
res = frappe.get_doc(
"Repair Service Mapping", i['name'])
res.display_order = self.display_order
res.active_status = self.active_status
res.save()
except Exception as e:
raise e

8
smart_service/phase_2/doctype/repair_service_mapping/test_repair_service_mapping.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestRepairServiceMapping(unittest.TestCase):
pass

0
smart_service/phase_2/doctype/repair_service_master/__init__.py

57
smart_service/phase_2/doctype/repair_service_master/repair_service_master.js

@ -0,0 +1,57 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
var original_display_order = 0;
var vehicle_count=0;
// frappe.require('assets/smart_service/js/utils.js', () => {})
frappe.ui.form.on('Repair Service Master', {
onload: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Repair Service Master')
.then(count => {
vehicle_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", vehicle_count);
} else {
original_display_order = frm.doc.display_order;
}
});
},
refresh: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Repair Service Master')
.then(count => {
vehicle_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", vehicle_count);
} else {
original_display_order = frm.doc.display_order;
}
});
},
after_save:function(frm){
cur_frm.refresh_fields("display_order")
},
validate: function (frm){
//For Display Order
cur_frm.refresh_fields("display_order")
// console.log(module_name_count,"----",original_display_order)
// display_order_validation(frm, repair_service_count, original_display_order,frm.doc.vehicle)
}
});

77
smart_service/phase_2/doctype/repair_service_master/repair_service_master.json

@ -0,0 +1,77 @@
{
"_liked_by": "[\"Administrator\"]",
"actions": [],
"allow_rename": 1,
"autoname": "format:{repairservicename}",
"creation": "2023-07-20 17:52:46.159091",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"repairservicename",
"column_break_jsfhv",
"active_status",
"display_order",
"my_id"
],
"fields": [
{
"fieldname": "repairservicename",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Repair/ServiceName",
"set_only_once": 1
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "my_id",
"fieldtype": "Int",
"hidden": 1,
"in_list_view": 1,
"label": "My Id",
"set_only_once": 1
},
{
"fieldname": "column_break_jsfhv",
"fieldtype": "Column Break"
},
{
"fieldname": "display_order",
"fieldtype": "Int",
"label": "Display Order"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-04 16:23:33.967758",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Repair Service Master",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"search_fields": "repairservicename",
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "repairservicename"
}

19
smart_service/phase_2/doctype/repair_service_master/repair_service_master.py

@ -0,0 +1,19 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class RepairServiceMaster(Document):
def validate(self):
if self.repairservicename:
self.repairservicename = self.repairservicename.strip()
def autoname(self):
if self.is_new():
count = frappe.db.sql(
'''select max(my_id) as max_count from `tabRepair Service Master`;''')
if count[0][0] is not None:
self.my_id = count[0][0] + 1
else:
self.my_id = 1

8
smart_service/phase_2/doctype/repair_service_master/test_repair_service_master.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestRepairServiceMaster(unittest.TestCase):
pass

0
smart_service/phase_2/doctype/repair_service_master_mapping/__init__.py

76
smart_service/phase_2/doctype/repair_service_master_mapping/repair_service_master_mapping.js

@ -0,0 +1,76 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
var original_display_order = 0;
var vehicle_count=0;
frappe.require('assets/smart_service/js/utils.js', () => {})
frappe.ui.form.on('Repair Service Master Mapping', {
onload: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Repair Service Master Mapping')
.then(count => {
vehicle_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", vehicle_count);
} else {
original_display_order = frm.doc.display_order;
}
});
frm.set_query("check_list_name", function() {
return{
"filters": {
"language": ["in", [frm.doc.language]],
}
}
});
},
refresh: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Repair Service Master Mapping')
.then(count => {
vehicle_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", vehicle_count);
} else {
original_display_order = frm.doc.display_order;
}
});
frm.set_query("check_list_name", function() {
return{
"filters": {
"language": ["in", [frm.doc.language]],
}
}
});
},
after_save:function(frm){
cur_frm.refresh_fields("display_order")
},
validate: function (frm){
//For Display Order
cur_frm.refresh_fields("display_order")
// console.log(module_name_count,"----",original_display_order)
display_order_validation(frm, vehicle_count, original_display_order,frm.doc.vehicle)
},
});

126
smart_service/phase_2/doctype/repair_service_master_mapping/repair_service_master_mapping.json

@ -0,0 +1,126 @@
{
"_comments": "[]",
"_liked_by": "[]",
"actions": [],
"allow_rename": 1,
"autoname": "format:{vehicle}-{check_list_name}-{language}",
"creation": "2023-07-20 17:51:20.201193",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"published",
"section_break_ci53z",
"vehicle",
"language",
"column_break_sjvew",
"check_list_name",
"column_break_azh0p",
"active_status",
"display_order",
"section_break_ecyyc",
"description",
"my_id"
],
"fields": [
{
"fieldname": "vehicle",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Vehicle",
"options": "Vehicle"
},
{
"fieldname": "language",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Language",
"options": "Custom Languages"
},
{
"fieldname": "check_list_name",
"fieldtype": "Link",
"in_global_search": 1,
"in_standard_filter": 1,
"label": "Check List Name",
"options": "Repair Service Master"
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"in_global_search": 1,
"in_standard_filter": 1,
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "display_order",
"fieldtype": "Int",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Display Order"
},
{
"fieldname": "description",
"fieldtype": "Table",
"label": "Description",
"options": "Repair Service Child"
},
{
"default": "0",
"fieldname": "published",
"fieldtype": "Check",
"label": "Published"
},
{
"fieldname": "section_break_ci53z",
"fieldtype": "Section Break"
},
{
"fieldname": "section_break_ecyyc",
"fieldtype": "Section Break"
},
{
"fieldname": "my_id",
"fieldtype": "Int",
"hidden": 1,
"in_list_view": 1,
"label": "My Id",
"set_only_once": 1
},
{
"fieldname": "column_break_sjvew",
"fieldtype": "Column Break"
},
{
"fieldname": "column_break_azh0p",
"fieldtype": "Column Break"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-04 10:54:59.348477",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Repair Service Master Mapping",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "check_list_name"
}

22
smart_service/phase_2/doctype/repair_service_master_mapping/repair_service_master_mapping.py

@ -0,0 +1,22 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class RepairServiceMasterMapping(Document):
def validate(self):
if self.vehicle:
self.vehicle = self.vehicle.strip()
def autoname(self):
if self.is_new():
count = frappe.db.sql('''select max(my_id) as max_count from `tabRepair Service Master Mapping`;''')
if count[0][0] is not None:
self.my_id = count[0][0] + 1
else:
self.my_id = 1

8
smart_service/phase_2/doctype/repair_service_master_mapping/test_repair_service_master_mapping.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestRepairServiceMasterMapping(unittest.TestCase):
pass

0
smart_service/phase_2/doctype/special_tool_information/__init__.py

91
smart_service/phase_2/doctype/special_tool_information/special_tool_information.js

@ -0,0 +1,91 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
var original_display_order = 0;
var vehicle_count=0;
// var counter = 0;
// frappe.require('assets/smart_service/js/utils.js', () => {})
frappe.ui.form.on('Special Tool Information', {
onload: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else{
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Special Tool Information')
.then(count => {
vehicle_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", vehicle_count);
} else {
original_display_order = frm.doc.display_order;
}
});
},
refresh: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Special Tool Information')
.then(count => {
vehicle_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", vehicle_count);
} else {
original_display_order = frm.doc.display_order;
}
});
},
// after_save:function(frm){
// cur_frm.refresh_fields("display_order")
// },
validate:function(frm){
//For Display Order
cur_frm.refresh_fields("display_order")
// console.log(module_name_count,"----",original_display_order)
if (frm.doc.display_order && frm.doc.name && !frm.is_new()) {
//***check if there is same display_order
frappe.db.get_list('Special Tool Information', {
fields: ['display_order', 'name'],
filters: {
display_order: frm.doc.display_order,
name: ["!=", frm.doc.name],
}
}).then(records => {
if (records.length) {
frappe.db.set_value('Special Tool Information', records[0].name, {
display_order: original_display_order
}).then(r => {
let doc = r.message;
frappe.show_alert({
message: __('Swapped display order with: ' + records[0].name),
indicator: 'green'
}, 5);
});
} else {
// if (frm.doc.display_order >= vehicle_count) {
// let display_vehicle_count = vehicle_count - 1;
// msgprint('There are only ' + display_vehicle_count + " " + frm.doc.doctype);
// frappe.validated = false;
// }
}
});
}
},
after_save: function (frm) {
cur_frm.refresh_fields("display_order")
frm.reload_doc()
}
});

88
smart_service/phase_2/doctype/special_tool_information/special_tool_information.json

@ -0,0 +1,88 @@
{
"_comments": "[]",
"_liked_by": "[]",
"actions": [],
"allow_rename": 1,
"autoname": "format:{vehicle}-{category}-",
"creation": "2023-08-04 13:09:53.363093",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"vehicle",
"category",
"sub_category",
"display_order",
"my_id",
"tool_usage_content"
],
"fields": [
{
"fieldname": "vehicle",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Vehicle",
"options": "Vehicle",
"reqd": 1,
"set_only_once": 1
},
{
"fieldname": "category",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Category",
"options": "New Tool\nCarry Over",
"set_only_once": 1
},
{
"fieldname": "sub_category",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Sub Category",
"options": "Maintenance Tool\nRepair Tool\nOverhauling Tool",
"set_only_once": 1
},
{
"fieldname": "display_order",
"fieldtype": "Int",
"in_list_view": 1,
"label": "Display Order"
},
{
"fieldname": "my_id",
"fieldtype": "Int",
"hidden": 1,
"in_list_view": 1,
"label": "My id"
},
{
"fieldname": "tool_usage_content",
"fieldtype": "Table",
"label": "Tool Usage Content",
"options": "MST Information Assets"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-07 10:38:16.791578",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Special Tool Information",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC"
}

14
smart_service/phase_2/doctype/special_tool_information/special_tool_information.py

@ -0,0 +1,14 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class SpecialToolInformation(Document):
def autoname(self):
if self.is_new():
count = frappe.db.sql('''select max(my_id) as max_count from `tabSpecial Tool Information`;''')
if count[0][0] is not None:
self.my_id = count[0][0] + 1
else:
self.my_id = 1

8
smart_service/phase_2/doctype/special_tool_information/test_special_tool_information.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestSpecialToolInformation(unittest.TestCase):
pass

0
smart_service/phase_2/doctype/training_information/__init__.py

8
smart_service/phase_2/doctype/training_information/test_training_information.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestTrainingInformation(unittest.TestCase):
pass

30
smart_service/phase_2/doctype/training_information/training_information.js

@ -0,0 +1,30 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
frappe.ui.form.on('Training Information', {
onload: function (frm) {
// Set Display Order
if (frm.is_new()) {
frm.set_df_property('display_order', 'read_only', 1);
} else {
frm.set_df_property('display_order', 'read_only', 0);
}
frappe.db.count('Repair Service Master Mapping',{
filters: {
"variant": cur_frm.doc.variant,
"language": frm.doc.language,
"feature_name": frm.doc.feature_name,
}
})
.then(count => {
vehicle_count = count + 1;
if (frm.is_new()) {
frm.set_value("display_order", vehicle_count);
} else {
original_display_order = frm.doc.display_order;
}
});
},
});

107
smart_service/phase_2/doctype/training_information/training_information.json

@ -0,0 +1,107 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{vehicle}-{category}-{topic}-{language}",
"creation": "2023-08-04 13:35:17.855020",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"vehicle",
"category",
"topic",
"language",
"column_break_tweld",
"active_status",
"display_order",
"section_break_6ucxv",
"content",
"section_break_6kjyf",
"my_id"
],
"fields": [
{
"fieldname": "vehicle",
"fieldtype": "Link",
"label": "Vehicle",
"options": "Vehicle"
},
{
"fieldname": "category",
"fieldtype": "Link",
"label": "Category",
"options": "Training Information Master"
},
{
"fieldname": "topic",
"fieldtype": "Data",
"label": "Topic"
},
{
"fieldname": "language",
"fieldtype": "Link",
"label": "Language",
"options": "Custom Languages"
},
{
"fieldname": "column_break_tweld",
"fieldtype": "Column Break"
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "section_break_6ucxv",
"fieldtype": "Section Break"
},
{
"fieldname": "content",
"fieldtype": "Table",
"label": "Content",
"options": "Training Information Content Reference"
},
{
"fieldname": "section_break_6kjyf",
"fieldtype": "Section Break"
},
{
"fieldname": "my_id",
"fieldtype": "Int",
"hidden": 1,
"in_list_view": 1,
"label": "My ID",
"set_only_once": 1
},
{
"fieldname": "display_order",
"fieldtype": "Int",
"label": "Display Order"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-07 10:25:28.869989",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Training Information",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC"
}

14
smart_service/phase_2/doctype/training_information/training_information.py

@ -0,0 +1,14 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class TrainingInformation(Document):
def autoname(self):
if self.is_new():
count = frappe.db.sql('''select max(my_id) as max_count from `tabTraining Information`;''')
if count[0][0] is not None:
self.my_id = count[0][0] + 1
else:
self.my_id = 1

0
smart_service/phase_2/doctype/training_information_content_reference/__init__.py

50
smart_service/phase_2/doctype/training_information_content_reference/training_information_content_reference.json

@ -0,0 +1,50 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-08-04 13:14:47.966141",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"content_type",
"image_video",
"active_status",
"content"
],
"fields": [
{
"fieldname": "content_type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Content Type",
"options": "Heading\nContent\nImage\nVideo"
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "content",
"fieldtype": "Data",
"label": "Content"
},
{
"fieldname": "image_video",
"fieldtype": "Attach",
"label": "Image/Video"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-08-04 14:47:37.837618",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Training Information Content Reference",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

8
smart_service/phase_2/doctype/training_information_content_reference/training_information_content_reference.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class TrainingInformationContentReference(Document):
pass

0
smart_service/phase_2/doctype/training_information_master/__init__.py

8
smart_service/phase_2/doctype/training_information_master/test_training_information_master.py

@ -0,0 +1,8 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and Contributors
# See license.txt
# import frappe
import unittest
class TestTrainingInformationMaster(unittest.TestCase):
pass

36
smart_service/phase_2/doctype/training_information_master/training_information_master.js

@ -0,0 +1,36 @@
// Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
// For license information, please see license.txt
frappe.ui.form.on('Training Information Master', {
// refresh: function(frm) {
// }
validate: function (frm) {
check_field_character(frm.doc.category)
check_field_character(frm.doc.topic)
}
});
function check_field_character(field_name) {
if (field_name) {
var alphanum = /^[a-zA-Z]+/;
if (field_name.length > 1) {
if (field_name.length > 50) {
frappe.msgprint("<b>Training Information Master:</b> Only <b> 50 </b> characters are allowed")
frappe.validated = false;
} else {
if (alphanum.test(field_name) === true) {
frappe.validated = true;
} else if (field_name) {
frappe.msgprint(__("<b>Training Information Master:</b> Enter letter or alpha numeric characters only."));
frappe.validated = false;
}
}
} else {
frappe.msgprint("<b>Training Information Master:</b> Single character not allowed")
frappe.validated = false;
}
}
}

74
smart_service/phase_2/doctype/training_information_master/training_information_master.json

@ -0,0 +1,74 @@
{
"_comments": "[]",
"_liked_by": "[]",
"actions": [],
"allow_rename": 1,
"autoname": "format:{category}-{topic}",
"creation": "2023-08-04 13:06:01.847663",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"category",
"topic",
"column_break_75wva",
"active_status",
"my_id"
],
"fields": [
{
"fieldname": "category",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Category",
"reqd": 1
},
{
"fieldname": "topic",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Topic",
"reqd": 1
},
{
"fieldname": "active_status",
"fieldtype": "Select",
"label": "Active Status",
"options": "Active\nInactive"
},
{
"fieldname": "column_break_75wva",
"fieldtype": "Column Break"
},
{
"fieldname": "my_id",
"fieldtype": "Int",
"hidden": 1,
"in_list_view": 1,
"label": "My Id"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-07 10:45:52.226211",
"modified_by": "Administrator",
"module": "Phase-2",
"name": "Training Information Master",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC"
}

21
smart_service/phase_2/doctype/training_information_master/training_information_master.py

@ -0,0 +1,21 @@
# Copyright (c) 2023, Hard n Soft Technologies Pvt Ltd and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class TrainingInformationMaster(Document):
def autoname(self):
if self.is_new():
count = frappe.db.sql('''select max(my_id) as max_count from `tabTraining Informations`;''')
if count[0][0] is not None:
self.my_id = count[0][0] + 1
else:
self.my_id = 1
def validate(self):
if self.category:
self.category = self.category.strip()
if self.topic:
self.topic = self.topic.strip()

90
smart_service/public/js/utils.js

@ -0,0 +1,90 @@
function display_order_validation(frm, field_count, original_display_order,field_name) {
debugger
if (frm.doc.display_order == null || typeof (frm.doc.display_order) == String) {
frappe.validated = false;
frm.doc.display_order = original_display_order
cur_frm.refresh_fields("display_order")
frappe.throw(__("<b>Display Order:</b> Invalid Characters not permitted."));
}
// Check negative display order
if (frm.doc.display_order <= 0 && frm.doc.display_order != null && typeof (frm.doc.display_order) != String) {
frappe.validated = false;
frm.doc.display_order = original_display_order
cur_frm.refresh_fields("display_order")
frappe.throw(__("<b>Display Order:</b> Zero or Negative values not allowed."));
}
// let regex = /[!@#$%^&*()_+\-=\[\]{};'`~:"\\|,.<>\/?]+/;
// if (field_name) {
// if (regex.test(field_name) === true) {
// frappe.msgprint(__("<b>"+frm.doc.doctype+":</b> There can only be letters and numerals."));
// frappe.validated = false;
// } else if (field_name) {
// if (field_name.includes("'")) {
// frappe.msgprint(__("<b>"+frm.doc.doctype+":</b> There can only be letters and numerals."));
// frappe.validated = false;
// }
// }
// }
var alphanum = /^[a-zA-Z]+/;
if (field_name) {
if (field_name.length > 1) {
if (field_name.length > 50) {
frappe.msgprint(__("<b>"+frm.doc.doctype+":</b> Only <b> 50 </b> characters are allowed."))
frappe.validated = false;
} else {
if (alphanum.test(field_name) === true) {
frappe.validated = true;
} else if (field_name) {
frappe.msgprint(__("<b>"+frm.doc.doctype+":</b> There can only be letters and alpha numerals."));
frappe.validated = false;
}
}
} else {
frappe.msgprint(__("<b>"+frm.doc.doctype+":</b> Single character is not allowed."))
frappe.validated = false;
}
}
if (frm.doc.display_order && frm.doc.name && !frm.is_new()) {
//***check if there is same display_order
frappe.db.get_list(frm.doc.doctype, {
fields: ['display_order', 'name'],
filters: {
display_order: frm.doc.display_order,
name: ["!=", frm.doc.name]
}
}).then(records => {
debugger
if (records.length) {
frappe.db.set_value(frm.doc.doctype, records[0].name, {
display_order: original_display_order
}).then(r => {
let doc = r.message;
frappe.show_alert({
message: __('Swapped display order with: ' + records[0].name),
indicator: 'green'
}, 5);
});
} else {
console.log(field_count,"---field_count")
if (frm.doc.display_order >= field_count) {
frappe.validated = false;
let display_field_count = field_count - 1;
frm.doc.display_order = original_display_order
cur_frm.refresh_fields("display_order")
msgprint('There are only ' + display_field_count + ' '+frm.doc.doctype+'(s)');
frappe.validated = false;
}
}
});
}
// }
// catch (e) {
// return e
// }
}

48
smart_service/transactions/doctype/procedure/procedure.js

@ -57,7 +57,7 @@ frappe.ui.form.on('Procedure', {
});
}
// frm.refresh();
// frm.refresh();
},
refresh: function (frm) {
if (frm.doc.procedure_details) {
@ -69,28 +69,28 @@ frappe.ui.form.on('Procedure', {
callback: function (r) {
}
})
if(frm.doc.procedure_details){
frappe.call({
"method": "smart_service.transactions.doctype.procedure.procedure.get_path",
"args": {
"name": frm.doc.name,
},
callback: function (r) {
var url = window.location.host;
var regex = /[://]+/;
// frappe.db.get_value('Fish', { name: "Fish" }, 'path', (r) => {
if (frm.doc.procedure_details) {
frappe.call({
"method": "smart_service.transactions.doctype.procedure.procedure.get_path",
"args": {
"name": frm.doc.name,
},
callback: function (r) {
var url = window.location.host;
var regex = /[://]+/;
// frappe.db.get_value('Fish', { name: "Fish" }, 'path', (r) => {
for (var i = 0; i < frm.doc.procedure_details.length; i++) {
if (frm.doc.procedure_details[i].content && r.message && frm.doc.procedure_details[i].content_type == "Link"){// && !(frm.doc.procedure_details[i].content).includes('</a>')){
var x = "<a href=" + '"' + r.message + "://" + url + "/app/procedure/" + frm.doc.procedure_details[i].temp_cnt+ '"' + 'target="_blank"' + ' role="link"' +' onclick="window.open('+r.message + "://" + url + "/app/procedure/" + frm.doc.procedure_details[i].temp_cnt+')"'+'>' + frm.doc.procedure_details[i].temp_cnt + '</a>';
frm.doc.procedure_details[i].content = x
if (frm.doc.procedure_details[i].content && r.message && frm.doc.procedure_details[i].content_type == "Link") {// && !(frm.doc.procedure_details[i].content).includes('</a>')){
var x = "<a href=" + '"' + r.message + "://" + url + "/app/procedure/" + frm.doc.procedure_details[i].temp_cnt + '"' + 'target="_blank"' + ' role="link"' + ' onclick="window.open(' + r.message + "://" + url + "/app/procedure/" + frm.doc.procedure_details[i].temp_cnt + ')"' + '>' + frm.doc.procedure_details[i].temp_cnt + '</a>';
frm.doc.procedure_details[i].content = x
}
}
cur_frm.refresh_fields('procedure_details');
// })
}
// })
}
})
}
}
}
select_row(frm);
if (frm.doc.procedure_filter == "All") {
@ -454,19 +454,19 @@ frappe.ui.form.on('Procedure_Details', {
var url = window.location.host;
var content = values.procedure;
row.doc.system_id = values.variant_mapping + ',' + values.system_id + ',' + values.subsystem_id;
// row.doc.content = '<a href="http://' + url + "/app/procedure/" + content + '"' + 'target="_blank"' + '>' + content + '</a>';
if(values.procedure){
// row.doc.content = '<a href="http://' + url + "/app/procedure/" + content + '"' + 'target="_blank"' + '>' + content + '</a>';
if (values.procedure) {
row.doc.content = values.procedure + ''
row.doc.temp_cnt = values.procedure + ''
}
row.doc.temp_cnt = values.procedure + ''
}
d.hide();
// frm.refresh();
// frm.refresh();
cur_frm.refresh_fields('procedure_details');
}
});
d.show();
} else {
// d.content = d.temp_cnt;
// d.content = d.temp_cnt;
}
},

7
smart_service/transactions/doctype/publish/publish.json

@ -228,7 +228,7 @@
"fieldname": "version",
"fieldtype": "Float",
"in_standard_filter": 1,
"label": "Version",
"label": "Others",
"read_only": 1
},
{
@ -305,14 +305,13 @@
"allow_on_submit": 1,
"fieldname": "file_path",
"fieldtype": "Data",
"label": "File Path",
"read_only": 1
"label": "File Path"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2023-06-15 11:30:29.844592",
"modified": "2023-08-07 12:34:32.740534",
"modified_by": "Administrator",
"module": "Transactions",
"name": "Publish",

0
smart_service/transactions/doctype/publish_test/__init__.py

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save