Merge develop into sla_fix
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index 1d75bb5..0923a5b 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -4,6 +4,7 @@
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
+ "engine": "InnoDB",
"field_order": [
"item_code",
"col_break1",
@@ -15,6 +16,10 @@
"image_section",
"image",
"image_view",
+ "manufacture_details",
+ "manufacturer",
+ "column_break_13",
+ "manufacturer_part_no",
"quantity_and_rate",
"received_qty",
"qty",
@@ -728,11 +733,32 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "manufacture_details",
+ "fieldtype": "Section Break",
+ "label": "Manufacture"
+ },
+ {
+ "fieldname": "manufacturer",
+ "fieldtype": "Link",
+ "label": "Manufacturer",
+ "options": "Manufacturer"
+ },
+ {
+ "fieldname": "column_break_13",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "manufacturer_part_no",
+ "fieldtype": "Data",
+ "label": "Manufacturer Part Number",
+ "read_only": 1
}
],
"idx": 1,
"istable": 1,
- "modified": "2019-05-25 22:04:48.435730",
+ "modified": "2019-06-02 06:36:17.078419",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
index e8b19b4..5d3253a 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
@@ -102,7 +102,9 @@
("customer", " and `tabSales Invoice`.customer = %(customer)s"),
("item_code", " and `tabSales Invoice Item`.item_code = %(item_code)s"),
("from_date", " and `tabSales Invoice`.posting_date>=%(from_date)s"),
- ("to_date", " and `tabSales Invoice`.posting_date<=%(to_date)s")):
+ ("to_date", " and `tabSales Invoice`.posting_date<=%(to_date)s"),
+ ("company_gstin", " and `tabSales Invoice`.company_gstin = %(company_gstin)s"),
+ ("invoice_type", " and `tabSales Invoice`.invoice_type = %(invoice_type)s")):
if filters.get(opts[0]):
conditions += opts[1]
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index c0338fd..1b63f8f 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -17,6 +17,10 @@
"col_break1",
"image",
"image_view",
+ "manufacture_details",
+ "manufacturer",
+ "column_break_14",
+ "manufacturer_part_no",
"quantity_and_rate",
"qty",
"stock_uom",
@@ -672,11 +676,32 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "manufacture_details",
+ "fieldtype": "Section Break",
+ "label": "Manufacture"
+ },
+ {
+ "fieldname": "manufacturer",
+ "fieldtype": "Link",
+ "label": "Manufacturer",
+ "options": "Manufacturer"
+ },
+ {
+ "fieldname": "column_break_14",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "manufacturer_part_no",
+ "fieldtype": "Data",
+ "label": "Manufacturer Part Number",
+ "read_only": 1
}
],
"idx": 1,
"istable": 1,
- "modified": "2019-05-25 22:10:32.518941",
+ "modified": "2019-06-02 06:34:47.495730",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",
diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
index b37e0ba..7d7d6f4 100644
--- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
+++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
@@ -18,6 +18,10 @@
"col_break1",
"image",
"image_view",
+ "manufacture_details",
+ "manufacturer",
+ "column_break_15",
+ "manufacturer_part_no",
"quantity_and_rate",
"qty",
"stock_uom",
@@ -285,6 +289,7 @@
"read_only": 1
},
{
+ "default": "0",
"fieldname": "is_free_item",
"fieldtype": "Check",
"label": "Is Free Item",
@@ -493,6 +498,7 @@
},
{
"allow_on_submit": 1,
+ "default": "0",
"fieldname": "page_break",
"fieldtype": "Check",
"label": "Page Break",
@@ -500,11 +506,33 @@
"oldfieldname": "page_break",
"oldfieldtype": "Check",
"print_hide": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "manufacture_details",
+ "fieldtype": "Section Break",
+ "label": "Manufacture"
+ },
+ {
+ "fieldname": "manufacturer",
+ "fieldtype": "Link",
+ "label": "Manufacturer",
+ "options": "Manufacturer"
+ },
+ {
+ "fieldname": "manufacturer_part_no",
+ "fieldtype": "Data",
+ "label": "Manufacturer Part Number",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_15",
+ "fieldtype": "Column Break"
}
],
"idx": 1,
"istable": 1,
- "modified": "2019-05-01 17:35:05.078030",
+ "modified": "2019-06-02 05:32:46.019237",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",
diff --git a/erpnext/config/quality_management.py b/erpnext/config/quality_management.py
index 1256b2d..35acdfa 100644
--- a/erpnext/config/quality_management.py
+++ b/erpnext/config/quality_management.py
@@ -59,14 +59,14 @@
"items": [
{
"type": "doctype",
- "name": "Customer Feedback",
- "description":_("Customer Feedback"),
+ "name": "Quality Feedback",
+ "description":_("Quality Feedback"),
"onboard": 1,
},
{
"type": "doctype",
- "name": "Customer Feedback Template",
- "description":_("Customer Feedback Template"),
+ "name": "Quality Feedback Template",
+ "description":_("Quality Feedback Template"),
}
]
},
diff --git a/erpnext/config/stock.py b/erpnext/config/stock.py
index 4fc824f..84aa847 100644
--- a/erpnext/config/stock.py
+++ b/erpnext/config/stock.py
@@ -163,6 +163,10 @@
},
{
"type": "doctype",
+ "name": "Item Manufacturer",
+ },
+ {
+ "type": "doctype",
"name": "Item Variant Settings",
},
]
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 2284669..ccd334f 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -437,3 +437,20 @@
query += " and item = {item}".format(item = frappe.db.escape(filters.get('item')))
return frappe.db.sql(query, filters)
+
+@frappe.whitelist()
+def item_manufacturer_query(doctype, txt, searchfield, start, page_len, filters):
+ search_txt = "{0}%".format(txt)
+
+ item_filters = {
+ 'manufacturer': ('like', search_txt),
+ 'item_code': filters.get("item_code")
+ }
+
+ return frappe.get_all("Item Manufacturer",
+ fields = "manufacturer",
+ filters = item_filters,
+ limit_start=start,
+ limit_page_length=page_len,
+ as_list=1
+ )
diff --git a/erpnext/demo/data/drug_list.json b/erpnext/demo/data/drug_list.json
index 9b101cb..e91c30d 100644
--- a/erpnext/demo/data/drug_list.json
+++ b/erpnext/demo/data/drug_list.json
@@ -39,8 +39,8 @@
"item_name": "Atocopherol",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
+
+
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:16.577151",
@@ -123,8 +123,8 @@
"item_name": "Abacavir",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
+
+
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:16.678257",
@@ -207,8 +207,6 @@
"item_name": "Abciximab",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:16.695413",
@@ -291,8 +289,6 @@
"item_name": "Acacia",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:16.797774",
@@ -375,8 +371,6 @@
"item_name": "Acamprosate",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:16.826952",
@@ -459,8 +453,6 @@
"item_name": "Acarbose",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:16.843890",
@@ -543,8 +535,6 @@
"item_name": "Acebrofylline",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:16.969984",
@@ -627,8 +617,6 @@
"item_name": "Acebrofylline (SR)",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:16.987354",
@@ -711,8 +699,6 @@
"item_name": "Aceclofenac",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.004369",
@@ -795,8 +781,6 @@
"item_name": "Ash",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.021192",
@@ -879,8 +863,6 @@
"item_name": "Asparaginase",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.038058",
@@ -963,8 +945,6 @@
"item_name": "Aspartame",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.054463",
@@ -1047,8 +1027,6 @@
"item_name": "Aspartic Acid",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.071001",
@@ -1131,8 +1109,6 @@
"item_name": "Bleomycin",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.087170",
@@ -1215,8 +1191,6 @@
"item_name": "Bleomycin Sulphate",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.103691",
@@ -1299,8 +1273,6 @@
"item_name": "Blue cap contains",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.120040",
@@ -1383,8 +1355,6 @@
"item_name": "Boran",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.135964",
@@ -1467,8 +1437,6 @@
"item_name": "Borax",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.152575",
@@ -1551,8 +1519,6 @@
"item_name": "Chlorbutanol",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.168998",
@@ -1635,8 +1601,6 @@
"item_name": "Chlorbutol",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.185316",
@@ -1719,8 +1683,6 @@
"item_name": "Chlordiazepoxide",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.208361",
@@ -1803,8 +1765,6 @@
"item_name": "Chlordiazepoxide and Clidinium Bromide",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.224341",
@@ -1887,8 +1847,6 @@
"item_name": "Chlorhexidine",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.240634",
@@ -1971,8 +1929,6 @@
"item_name": "Chlorhexidine 40%",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.256922",
@@ -2055,8 +2011,6 @@
"item_name": "Chlorhexidine Acetate",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.274789",
@@ -2139,8 +2093,6 @@
"item_name": "Chlorhexidine Gluconate",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.295371",
@@ -2223,8 +2175,6 @@
"item_name": "Chlorhexidine HCL",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.312916",
@@ -2307,8 +2257,6 @@
"item_name": "Chlorhexidine Hydrochloride",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.329570",
@@ -2391,8 +2339,6 @@
"item_name": "Chloride",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.346088",
@@ -2475,8 +2421,6 @@
"item_name": "Fosfomycin Tromethamine",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.362777",
@@ -2559,8 +2503,6 @@
"item_name": "Fosinopril",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.379465",
@@ -2643,8 +2585,6 @@
"item_name": "Iodochlorhydroxyquinoline",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.396068",
@@ -2727,8 +2667,6 @@
"item_name": "Iodochlorohydroxyquinoline",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.412734",
@@ -2811,8 +2749,6 @@
"item_name": "Ipratropium",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.429333",
@@ -2895,8 +2831,6 @@
"item_name": "Mebeverine hydrochloride",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.445814",
@@ -2979,8 +2913,6 @@
"item_name": "Mecetronium ethylsulphate",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.461696",
@@ -3063,8 +2995,6 @@
"item_name": "Meclizine",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.478020",
@@ -3147,8 +3077,8 @@
"item_name": "Oxaprozin",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
+
+
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.496221",
@@ -3231,8 +3161,6 @@
"item_name": "Oxazepam",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.511933",
@@ -3315,8 +3243,6 @@
"item_name": "Oxcarbazepine",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.528472",
@@ -3399,8 +3325,6 @@
"item_name": "Oxetacaine",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.544177",
@@ -3483,8 +3407,6 @@
"item_name": "Oxethazaine",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.560193",
@@ -3567,8 +3489,6 @@
"item_name": "Suxamethonium Chloride",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.576447",
@@ -3651,8 +3571,6 @@
"item_name": "Tacrolimus",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.593481",
@@ -3735,8 +3653,6 @@
"item_name": "Ubiquinol",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.609930",
@@ -3819,8 +3735,6 @@
"item_name": "Vitamin B12",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.626225",
@@ -3903,8 +3817,6 @@
"item_name": "Vitamin B1Hydrochloride",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.642423",
@@ -3987,8 +3899,6 @@
"item_name": "Vitamin B1Monohydrate",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.658946",
@@ -4071,8 +3981,6 @@
"item_name": "Vitamin B2",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.675234",
@@ -4155,8 +4063,6 @@
"item_name": "Vitamin B3",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.691598",
@@ -4239,8 +4145,6 @@
"item_name": "Vitamin D4",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.707840",
@@ -4323,8 +4227,6 @@
"item_name": "Vitamin E",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.723859",
@@ -4407,8 +4309,6 @@
"item_name": "Wheat Germ Oil",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.739829",
@@ -4491,8 +4391,6 @@
"item_name": "Wheatgrass extr",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.757695",
@@ -4575,8 +4473,6 @@
"item_name": "Whey Protein",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.774098",
@@ -4659,8 +4555,6 @@
"item_name": "Xylometazoline",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.790224",
@@ -4743,8 +4637,6 @@
"item_name": "Xylometazoline Hydrochloride",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.806359",
@@ -4827,8 +4719,6 @@
"item_name": "Yeast",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.823305",
@@ -4911,8 +4801,6 @@
"item_name": "Yellow Fever Vaccine",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.840250",
@@ -4995,8 +4883,6 @@
"item_name": "Zafirlukast",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.856856",
@@ -5079,8 +4965,6 @@
"item_name": "Zaleplon",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.873287",
@@ -5163,8 +5047,6 @@
"item_name": "Zaltoprofen",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.889263",
@@ -5247,8 +5129,6 @@
"item_name": "Zanamivir",
"last_purchase_rate": 0.0,
"lead_time_days": 0,
- "manufacturer": null,
- "manufacturer_part_no": null,
"max_discount": 0.0,
"min_order_qty": 0.0,
"modified": "2017-07-06 12:53:17.905022",
diff --git a/erpnext/domains/education.py b/erpnext/domains/education.py
index 55e4eed..bbaa6e5 100644
--- a/erpnext/domains/education.py
+++ b/erpnext/domains/education.py
@@ -14,7 +14,7 @@
'Student Attendance Tool',
'Student Applicant'
],
- 'default_portal_role': 'LMS User',
+ 'default_portal_role': 'Student',
'restricted_roles': [
'Student',
'Instructor',
diff --git a/erpnext/education/doctype/course/course.json b/erpnext/education/doctype/course/course.json
index 072e8b4..7d8b073 100644
--- a/erpnext/education/doctype/course/course.json
+++ b/erpnext/education/doctype/course/course.json
@@ -1,514 +1,135 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:course_code",
- "beta": 0,
- "creation": "2015-09-07 12:39:55.181893",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 0,
- "engine": "InnoDB",
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:course_code",
+ "creation": "2015-09-07 12:39:55.181893",
+ "doctype": "DocType",
+ "engine": "InnoDB",
+ "field_order": [
+ "course_name",
+ "department",
+ "parent_course",
+ "column_break_3",
+ "course_code",
+ "course_abbreviation",
+ "section_break_6",
+ "topics",
+ "description",
+ "hero_image",
+ "assessment",
+ "default_grading_scale",
+ "assessment_criteria"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "course_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Course Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "course_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Course Name",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "department",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Department",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Department",
+ "options": "Department"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "parent_course",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Parent Course (Leave blank, if this isn't part of Parent Course)",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "parent_course",
+ "fieldtype": "Data",
+ "label": "Parent Course (Leave blank, if this isn't part of Parent Course)"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "column_break_3",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "course_code",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Course Code",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "fieldname": "course_code",
+ "fieldtype": "Data",
+ "label": "Course Code",
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "course_abbreviation",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Course Abbreviation",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "course_abbreviation",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Course Abbreviation"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_6",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "section_break_6",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "topics",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Topics",
- "length": 0,
- "no_copy": 0,
- "options": "Course Topic",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "topics",
+ "fieldtype": "Table",
+ "label": "Topics",
+ "options": "Course Topic"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "course_intro",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Course Intro",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "hero_image",
+ "fieldtype": "Attach Image",
+ "label": "Hero Image"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "hero_image",
- "fieldtype": "Attach Image",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Hero Image",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "assessment",
+ "fieldtype": "Section Break",
+ "label": "Assessment"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "assessment",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Assessment",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "default_grading_scale",
+ "fieldtype": "Link",
+ "label": "Default Grading Scale",
+ "options": "Grading Scale"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "default_grading_scale",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Default Grading Scale",
- "length": 0,
- "no_copy": 0,
- "options": "Grading Scale",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "assessment_criteria",
+ "fieldtype": "Table",
+ "label": "Assessment Criteria",
+ "options": "Course Assessment Criteria"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "assessment_criteria",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Assessment Criteria",
- "length": 0,
- "no_copy": 0,
- "options": "Course Assessment Criteria",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description"
}
- ],
- "has_web_view": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "menu_index": 0,
- "modified": "2019-04-09 11:35:27.354877",
- "modified_by": "Administrator",
- "module": "Education",
- "name": "Course",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2019-06-05 18:39:11.870605",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Course",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Academics User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Academics User",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Instructor",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Instructor",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "restrict_to_domain": "Education",
- "search_fields": "course_name",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "restrict_to_domain": "Education",
+ "search_fields": "course_name",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_enrollment/course_enrollment.py b/erpnext/education/doctype/course_enrollment/course_enrollment.py
index 6f2bb0d..b082be2 100644
--- a/erpnext/education/doctype/course_enrollment/course_enrollment.py
+++ b/erpnext/education/doctype/course_enrollment/course_enrollment.py
@@ -35,7 +35,7 @@
if enrollment:
frappe.throw(_("Student is already enrolled."))
- def add_quiz_activity(self, quiz_name, quiz_response,answers, score, status):
+ def add_quiz_activity(self, quiz_name, quiz_response, answers, score, status):
result = {k: ('Correct' if v else 'Wrong') for k,v in answers.items()}
result_data = []
for key in answers:
@@ -43,7 +43,9 @@
item['question'] = key
item['quiz_result'] = result[key]
try:
- if isinstance(quiz_response[key], list):
+ if not quiz_response[key]:
+ item['selected_option'] = "Unattempted"
+ elif isinstance(quiz_response[key], list):
item['selected_option'] = ', '.join(frappe.get_value('Options', res, 'option') for res in quiz_response[key])
else:
item['selected_option'] = frappe.get_value('Options', quiz_response[key], 'option')
@@ -59,11 +61,12 @@
"result": result_data,
"score": score,
"status": status
- }).insert()
+ }).insert(ignore_permissions = True)
def add_activity(self, content_type, content):
- if check_activity_exists(self.name, content_type, content):
- pass
+ activity = check_activity_exists(self.name, content_type, content)
+ if activity:
+ return activity
else:
activity = frappe.get_doc({
"doctype": "Course Activity",
@@ -71,9 +74,14 @@
"content_type": content_type,
"content": content,
"activity_date": frappe.utils.datetime.datetime.now()
- })
- activity.insert()
+ })
+
+ activity.insert(ignore_permissions=True)
+ return activity.name
def check_activity_exists(enrollment, content_type, content):
activity = frappe.get_all("Course Activity", filters={'enrollment': enrollment, 'content_type': content_type, 'content': content})
- return bool(activity)
\ No newline at end of file
+ if activity:
+ return activity[0].name
+ else:
+ return None
\ No newline at end of file
diff --git a/erpnext/education/doctype/program/program.json b/erpnext/education/doctype/program/program.json
index cb8d778..a0a2aa2 100644
--- a/erpnext/education/doctype/program/program.json
+++ b/erpnext/education/doctype/program/program.json
@@ -1,627 +1,181 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:program_code",
- "beta": 0,
"creation": "2015-09-07 12:54:03.609282",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
- "document_type": "",
- "editable_grid": 0,
"engine": "InnoDB",
+ "field_order": [
+ "program_name",
+ "department",
+ "column_break_3",
+ "program_code",
+ "program_abbreviation",
+ "section_break_5",
+ "courses",
+ "section_break_9",
+ "description",
+ "intro_video",
+ "hero_image",
+ "column_break_11",
+ "is_published",
+ "is_featured",
+ "allow_self_enroll"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "program_name",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Program Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "department",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Department",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Department"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "column_break_3",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "program_code",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Program Code",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
"unique": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "program_abbreviation",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Program Abbreviation",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Program Abbreviation"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fetch_if_empty": 0,
"fieldname": "section_break_5",
"fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Portal Settings",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Portal Settings"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "courses",
"fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Courses",
- "length": 0,
- "no_copy": 0,
- "options": "Program Course",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Program Course"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "section_break_9",
"fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "LMS Settings"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "description",
"fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Description",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Description"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "intro_video",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Intro Video",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Intro Video"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "hero_image",
"fieldtype": "Attach Image",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Hero Image",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Hero Image"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "column_break_11",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "0",
- "fetch_if_empty": 0,
"fieldname": "is_published",
"fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Is Published",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Is Published"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "0",
- "fetch_if_empty": 0,
+ "depends_on": "eval: doc.is_published == 1",
"fieldname": "is_featured",
"fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Is Featured",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Is Featured"
+ },
+ {
+ "default": "0",
+ "depends_on": "eval: doc.is_published == 1",
+ "description": "Allow students to enroll themselves from the portal",
+ "fieldname": "allow_self_enroll",
+ "fieldtype": "Check",
+ "label": "Allow Self Enroll"
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "menu_index": 0,
- "modified": "2019-03-18 15:26:56.737903",
+ "modified": "2019-06-05 17:47:26.877296",
"modified_by": "Administrator",
"module": "Education",
"name": "Program",
- "name_case": "",
"owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Academics User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Instructor",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Guest",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "LMS User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Student",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Academics User",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Instructor",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Guest",
+ "share": 1
+ },
+ {
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Student",
+ "share": 1
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
"restrict_to_domain": "Education",
- "route": "",
"search_fields": "program_name",
"show_name_in_global_search": 1,
"sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment.py b/erpnext/education/doctype/program_enrollment/program_enrollment.py
index 22cca86..d232e47 100644
--- a/erpnext/education/doctype/program_enrollment/program_enrollment.py
+++ b/erpnext/education/doctype/program_enrollment/program_enrollment.py
@@ -96,29 +96,6 @@
quiz_progress.program = self.program
return quiz_progress
- def get_program_progress(self):
- import math
- program = frappe.get_doc("Program", self.program)
- program_progress = {}
- progress = []
- for course in program.get_all_children():
- course_progress = lms.get_student_course_details(course.course, self.program)
- is_complete = False
- if course_progress['flag'] == "Completed":
- is_complete = True
- progress.append({'course_name': course.course_name, 'name': course.course, 'is_complete': is_complete})
-
- program_progress['progress'] = progress
- program_progress['name'] = self.program
- program_progress['program'] = frappe.get_value("Program", self.program, 'program_name')
-
- try:
- program_progress['percentage'] = math.ceil((sum([item['is_complete'] for item in progress] * 100)/len(progress)))
- except ZeroDivisionError:
- program_progress['percentage'] = 0
-
- return program_progress
-
@frappe.whitelist()
def get_program_courses(doctype, txt, searchfield, start, page_len, filters):
if filters.get('program'):
diff --git a/erpnext/education/doctype/question/question.json b/erpnext/education/doctype/question/question.json
index 14a9f3c..b3a161d 100644
--- a/erpnext/education/doctype/question/question.json
+++ b/erpnext/education/doctype/question/question.json
@@ -1,167 +1,80 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "format:QUESTION-{#####}",
- "beta": 0,
- "creation": "2018-10-01 15:58:00.696815",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "allow_import": 1,
+ "autoname": "format:QUESTION-{#####}",
+ "creation": "2018-10-01 15:58:00.696815",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "question",
+ "options",
+ "question_type"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "question",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Question",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "question",
+ "fieldtype": "Small Text",
+ "in_list_view": 1,
+ "label": "Question",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "options",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Options",
- "length": 0,
- "no_copy": 0,
- "options": "Options",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "options",
+ "fieldtype": "Table",
+ "label": "Options",
+ "options": "Options",
+ "reqd": 1
+ },
+ {
+ "fieldname": "question_type",
+ "fieldtype": "Select",
+ "in_standard_filter": 1,
+ "label": "Type",
+ "options": "\nSingle Correct Answer\nMultiple Correct Answer",
+ "read_only": 1
}
- ],
- "has_web_view": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-04-22 14:02:08.140652",
- "modified_by": "Administrator",
- "module": "Education",
- "name": "Question",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2019-05-30 18:39:21.880974",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Question",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Academics User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Academics User",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Instructor",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Instructor",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "LMS User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "LMS User",
+ "share": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/question/question.py b/erpnext/education/doctype/question/question.py
index 8cd2398..b822108 100644
--- a/erpnext/education/doctype/question/question.py
+++ b/erpnext/education/doctype/question/question.py
@@ -12,6 +12,7 @@
def validate(self):
self.check_at_least_one_option()
self.check_minimum_one_correct_answer()
+ self.set_question_type()
def check_at_least_one_option(self):
if len(self.options) <= 1:
@@ -26,6 +27,13 @@
else:
frappe.throw(_("A qustion must have at least one correct options"))
+ def set_question_type(self):
+ correct_options = [option for option in self.options if option.is_correct]
+ if len(correct_options) > 1:
+ self.question_type = "Multiple Correct Answer"
+ else:
+ self.question_type = "Single Correct Answer"
+
def get_answer(self):
options = self.options
answers = [item.name for item in options if item.is_correct == True]
diff --git a/erpnext/education/doctype/quiz/quiz.json b/erpnext/education/doctype/quiz/quiz.json
index f91bc0f..b4903fc 100644
--- a/erpnext/education/doctype/quiz/quiz.json
+++ b/erpnext/education/doctype/quiz/quiz.json
@@ -1,299 +1,105 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
"autoname": "field:title",
- "beta": 0,
"creation": "2018-10-17 05:52:50.149904",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
- "document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
+ "field_order": [
+ "title",
+ "question",
+ "quiz_configuration_section",
+ "passing_score",
+ "max_attempts",
+ "grading_basis"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "title",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Title",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
"unique": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "question",
"fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Question",
- "length": 0,
- "no_copy": 0,
"options": "Quiz Question",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "quiz_configuration_section",
"fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Quiz Configuration",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Quiz Configuration"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "default": "75",
+ "description": "Score out of 100",
"fieldname": "passing_score",
"fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Passing Score",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "1",
"description": "Enter 0 to waive limit",
"fieldname": "max_attempts",
"fieldtype": "Int",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Max Attempts",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Last Highest Score",
+ "default": "Latest Highest Score",
"fieldname": "grading_basis",
"fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Grading Basis",
- "length": 0,
- "no_copy": 0,
- "options": "\nLast Attempt\nLast Highest Score",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Latest Highest Score\nLatest Attempt"
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-25 19:07:36.190116",
+ "modified": "2019-05-30 18:50:54.218571",
"modified_by": "Administrator",
"module": "Education",
"name": "Quiz",
- "name_case": "",
"owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Academics User",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "LMS User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
+ "share": 1
},
{
- "amend": 0,
- "cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Instructor",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
}
],
"quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/quiz/quiz.py b/erpnext/education/doctype/quiz/quiz.py
index 6da50a6..8e54745 100644
--- a/erpnext/education/doctype/quiz/quiz.py
+++ b/erpnext/education/doctype/quiz/quiz.py
@@ -7,51 +7,47 @@
from frappe.model.document import Document
class Quiz(Document):
+ def validate(self):
+ if self.passing_score > 100:
+ frappe.throw("Passing Score value should be between 0 and 100")
- def validate_quiz_attempts(self, enrollment, quiz_name):
- if self.max_attempts > 0:
- try:
- if len(frappe.get_all("Quiz Activity", {'enrollment': enrollment.name, 'quiz': quiz_name})) >= self.max_attempts:
- frappe.throw('Maximum attempts reached!')
- except Exception as e:
- pass
+ def allowed_attempt(self, enrollment, quiz_name):
+ if self.max_attempts == 0:
+ return True
+
+ try:
+ if len(frappe.get_all("Quiz Activity", {'enrollment': enrollment.name, 'quiz': quiz_name})) >= self.max_attempts:
+ frappe.msgprint("Maximum attempts for this quiz reached!")
+ return False
+ else:
+ return True
+ except Exception as e:
+ return False
def evaluate(self, response_dict, quiz_name):
- # self.validate_quiz_attempts(enrollment, quiz_name)
questions = [frappe.get_doc('Question', question.question_link) for question in self.question]
answers = {q.name:q.get_answer() for q in questions}
- correct_answers = {}
+ result = {}
for key in answers:
try:
if isinstance(response_dict[key], list):
- result = compare_list_elementwise(response_dict[key], answers[key])
+ is_correct = compare_list_elementwise(response_dict[key], answers[key])
else:
- result = (response_dict[key] == answers[key])
- except:
- result = False
- correct_answers[key] = result
- score = (sum(correct_answers.values()) * 100 ) / len(answers)
+ is_correct = (response_dict[key] == answers[key])
+ except Exception as e:
+ is_correct = False
+ result[key] = is_correct
+ score = (sum(result.values()) * 100 ) / len(answers)
if score >= self.passing_score:
status = "Pass"
else:
status = "Fail"
- return correct_answers, score, status
+ return result, score, status
def get_questions(self):
- quiz_question = self.get_all_children()
- if quiz_question:
- questions = [frappe.get_doc('Question', question.question_link).as_dict() for question in quiz_question]
- for question in questions:
- correct_options = [option.is_correct for option in question.options]
- if sum(correct_options) > 1:
- question['type'] = "MultipleChoice"
- else:
- question['type'] = "SingleChoice"
- return questions
- else:
- return None
+ return [frappe.get_doc('Question', question.question_link) for question in self.question]
def compare_list_elementwise(*args):
try:
diff --git a/erpnext/education/doctype/quiz_result/quiz_result.json b/erpnext/education/doctype/quiz_result/quiz_result.json
index 86505ac..67c7e2d 100644
--- a/erpnext/education/doctype/quiz_result/quiz_result.json
+++ b/erpnext/education/doctype/quiz_result/quiz_result.json
@@ -1,145 +1,52 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-10-15 15:52:25.766374",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "creation": "2018-10-15 15:52:25.766374",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "question",
+ "selected_option",
+ "quiz_result"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "question",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Question",
- "length": 0,
- "no_copy": 0,
- "options": "Question",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "question",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Question",
+ "options": "Question",
+ "read_only": 1,
+ "reqd": 1,
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "selected_option",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Selected Option",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "selected_option",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Selected Option",
+ "read_only": 1,
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "quiz_result",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Result",
- "length": 0,
- "no_copy": 0,
- "options": "\nCorrect\nWrong",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
+ "fieldname": "quiz_result",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Result",
+ "options": "\nCorrect\nWrong",
+ "read_only": 1,
+ "reqd": 1,
+ "set_only_once": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2019-03-27 17:58:54.388848",
- "modified_by": "Administrator",
- "module": "Education",
- "name": "Quiz Result",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "istable": 1,
+ "modified": "2019-06-03 12:52:32.267392",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Quiz Result",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py
index 529f78d..da25880 100644
--- a/erpnext/education/doctype/student/student.py
+++ b/erpnext/education/doctype/student/student.py
@@ -54,7 +54,7 @@
'send_welcome_email': 1,
'user_type': 'Website User'
})
- student_user.add_roles("Student", "LMS User")
+ student_user.add_roles("Student")
student_user.save()
update_password_link = student_user.reset_password()
diff --git a/erpnext/education/doctype/topic/topic.json b/erpnext/education/doctype/topic/topic.json
index f47b10d..6e748fd 100644
--- a/erpnext/education/doctype/topic/topic.json
+++ b/erpnext/education/doctype/topic/topic.json
@@ -1,297 +1,104 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "field:topic_code",
- "beta": 0,
- "creation": "2018-12-12 11:37:39.917760",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "autoname": "field:topic_code",
+ "creation": "2018-12-12 11:37:39.917760",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "topic_name",
+ "column_break_2",
+ "topic_code",
+ "section_break_4",
+ "topic_content",
+ "description",
+ "hero_image"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "topic_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "topic_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Name",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "topic_code",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Code",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "fieldname": "topic_code",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Code",
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_4",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "section_break_4",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "topic_content",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Topic Content",
- "length": 0,
- "no_copy": 0,
- "options": "Topic Content",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "topic_content",
+ "fieldtype": "Table",
+ "label": "Topic Content",
+ "options": "Topic Content"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "hero_image",
- "fieldtype": "Attach Image",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Hero Image",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "hero_image",
+ "fieldtype": "Attach Image",
+ "label": "Hero Image"
+ },
+ {
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description"
}
- ],
- "has_web_view": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "menu_index": 0,
- "modified": "2019-04-09 11:35:34.137040",
- "modified_by": "Administrator",
- "module": "Education",
- "name": "Topic",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2019-06-05 18:38:44.029711",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Topic",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Administrator",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Administrator",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Instructor",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Instructor",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/education/doctype/video/video.json b/erpnext/education/doctype/video/video.json
index cc8f718..3d11bd2 100644
--- a/erpnext/education/doctype/video/video.json
+++ b/erpnext/education/doctype/video/video.json
@@ -1,262 +1,102 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
"allow_import": 1,
- "allow_rename": 0,
"autoname": "field:title",
- "beta": 0,
"creation": "2018-10-17 05:47:13.087395",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
- "document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
+ "field_order": [
+ "title",
+ "description",
+ "duration",
+ "provider",
+ "url",
+ "publish_date"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "title",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
+ "in_list_view": 1,
"label": "Title",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "reqd": 1,
"unique": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "description",
"fieldtype": "Text Editor",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
+ "in_list_view": 1,
"label": "Description",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "duration",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Duration",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Duration"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "url",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
+ "in_list_view": 1,
"label": "URL",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "publish_date",
"fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Publish Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Publish Date"
+ },
+ {
+ "fieldname": "provider",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Provider",
+ "options": "YouTube\nVimeo",
+ "reqd": 1
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-25 19:07:17.134288",
+ "modified": "2019-05-20 15:11:53.075093",
"modified_by": "Administrator",
"module": "Education",
"name": "Video",
- "name_case": "",
"owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Academics User",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Instructor",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
"export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "LMS User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
+ "share": 1
}
],
"quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/education/setup.py b/erpnext/education/setup.py
index ed1d69e..5c40928 100644
--- a/erpnext/education/setup.py
+++ b/erpnext/education/setup.py
@@ -9,7 +9,8 @@
def setup_education():
- if frappe.db.exists('Academic Year', '2015-16'):
+ disable_desk_access_for_student_role()
+ if frappe.db.exists("Academic Year", "2015-16"):
# already setup
return
create_academic_sessions()
@@ -26,3 +27,22 @@
{"doctype": "Academic Term", "academic_year": "2017-18", "term_name": "Semester 2"}
]
insert_record(data)
+
+def disable_desk_access_for_student_role():
+ try:
+ student_role = frappe.get_doc("Role", "Student")
+ except frappe.DoesNotExistError:
+ create_student_role()
+ return
+
+ student_role.desk_access = 0
+ student_role.save()
+
+def create_student_role():
+ student_role = frappe.get_doc({
+ "doctype": "Role",
+ "role_name": "Student",
+ "desk_access": 0,
+ "restrict_to_domain": "Education"
+ })
+ student_role.insert()
diff --git a/erpnext/education/utils.py b/erpnext/education/utils.py
index bf766ad..8cd5bbb 100644
--- a/erpnext/education/utils.py
+++ b/erpnext/education/utils.py
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies and contributors
-# For lice
from __future__ import unicode_literals, division
import frappe
@@ -57,9 +56,10 @@
# LMS Utils
def get_current_student():
- """
- Returns student user name, example EDU-STU-2018-00001 (Based on the naming series).
- Takes email from from frappe.session.user
+ """Returns current student from frappe.session.user
+
+ Returns:
+ object: Student Document
"""
email = frappe.session.user
if email in ('Administrator', 'Guest'):
@@ -70,44 +70,266 @@
except (IndexError, frappe.DoesNotExistError):
return None
-def check_super_access():
+def get_portal_programs():
+ """Returns a list of all program to be displayed on the portal
+ Programs are returned based on the following logic
+ is_published and (student_is_enrolled or student_can_self_enroll)
+
+ Returns:
+ list of dictionary: List of all programs and to be displayed on the portal along with access rights
+ """
+ published_programs = frappe.get_all("Program", filters={"is_published": True})
+ if not published_programs:
+ return None
+
+ program_list = [frappe.get_doc("Program", program) for program in published_programs]
+ portal_programs = [{'program': program, 'has_access': allowed_program_access(program.name)} for program in program_list if allowed_program_access(program.name) or program.allow_self_enroll]
+
+ return portal_programs
+
+def allowed_program_access(program, student=None):
+ """Returns enrollment status for current student
+
+ Args:
+ program (string): Name of the program
+ student (object): instance of Student document
+
+ Returns:
+ bool: Is current user enrolled or not
+ """
+ if has_super_access():
+ return True
+ if not student:
+ student = get_current_student()
+ if student and get_enrollment('program', program, student.name):
+ return True
+ else:
+ return False
+
+def get_enrollment(master, document, student):
+ """Gets enrollment for course or program
+
+ Args:
+ master (string): can either be program or course
+ document (string): program or course name
+ student (string): Student ID
+
+ Returns:
+ string: Enrollment Name if exists else returns empty string
+ """
+ if master == 'program':
+ enrollments = frappe.get_all("Program Enrollment", filters={'student':student, 'program': document, 'docstatus': 1})
+ if master == 'course':
+ enrollments = frappe.get_all("Course Enrollment", filters={'student':student, 'course': document})
+
+ if enrollments:
+ return enrollments[0].name
+ else:
+ return None
+
+@frappe.whitelist()
+def enroll_in_program(program_name, student=None):
+ """Enroll student in program
+
+ Args:
+ program_name (string): Name of the program to be enrolled into
+ student (string, optional): name of student who has to be enrolled, if not
+ provided, a student will be created from the current user
+
+ Returns:
+ string: name of the program enrollment document
+ """
+ if has_super_access():
+ return
+
+ if not student == None:
+ student = frappe.get_doc("Student", student)
+ else:
+ # Check if self enrollment in allowed
+ program = frappe.get_doc('Program', program_name)
+ if not program.allow_self_enroll:
+ return frappe.throw("You are not allowed to enroll for this course")
+
+ student = get_current_student()
+ if not student:
+ student = create_student_from_current_user()
+
+ # Check if student is already enrolled in program
+ enrollment = get_enrollment('program', program_name, student.name)
+ if enrollment:
+ return enrollment
+
+ # Check if self enrollment in allowed
+ program = frappe.get_doc('Program', program_name)
+ if not program.allow_self_enroll:
+ return frappe.throw("You are not allowed to enroll for this course")
+
+ # Enroll in program
+ program_enrollment = student.enroll_in_program(program_name)
+ return program_enrollment.name
+
+def has_super_access():
+ """Check if user has a role that allows full access to LMS
+
+ Returns:
+ bool: true if user has access to all lms content
+ """
current_user = frappe.get_doc('User', frappe.session.user)
roles = set([role.role for role in current_user.roles])
return bool(roles & {'Administrator', 'Instructor', 'Education Manager', 'System Manager', 'Academic User'})
-def get_program_enrollment(program_name):
- """
- Function to get program enrollments for a particular student for a program
- """
+@frappe.whitelist()
+def add_activity(course, content_type, content, program):
+ if has_super_access():
+ return None
+
student = get_current_student()
if not student:
- return None
+ return frappe.throw("Student with email {0} does not exist".format(frappe.session.user), frappe.DoesNotExistError)
+
+ enrollment = get_or_create_course_enrollment(course, program)
+ if content_type == 'Quiz':
+ return
else:
- enrollment = frappe.get_all("Program Enrollment", filters={'student':student.name, 'program': program_name})
- if enrollment:
- return enrollment[0].name
+ return enrollment.add_activity(content_type, content)
+
+@frappe.whitelist()
+def evaluate_quiz(quiz_response, quiz_name, course, program):
+ import json
+
+ student = get_current_student()
+
+ quiz_response = json.loads(quiz_response)
+ quiz = frappe.get_doc("Quiz", quiz_name)
+ result, score, status = quiz.evaluate(quiz_response, quiz_name)
+
+ if has_super_access():
+ return {'result': result, 'score': score, 'status': status}
+
+ if student:
+ enrollment = get_or_create_course_enrollment(course, program)
+ if quiz.allowed_attempt(enrollment, quiz_name):
+ enrollment.add_quiz_activity(quiz_name, quiz_response, result, score, status)
+ return {'result': result, 'score': score, 'status': status}
else:
return None
-def get_program_and_enrollment_status(program_name):
- program = frappe.get_doc('Program', program_name)
- is_enrolled = bool(get_program_enrollment(program_name)) or check_super_access()
- return {'program': program, 'is_enrolled': is_enrolled}
+@frappe.whitelist()
+def get_quiz(quiz_name, course):
+ try:
+ quiz = frappe.get_doc("Quiz", quiz_name)
+ questions = quiz.get_questions()
+ except:
+ frappe.throw("Quiz {0} does not exist".format(quiz_name))
+ return None
-def get_course_enrollment(course_name):
+ questions = [{
+ 'name': question.name,
+ 'question': question.question,
+ 'type': question.question_type,
+ 'options': [{'name': option.name, 'option': option.option}
+ for option in question.options],
+ } for question in questions]
+
+ if has_super_access():
+ return {'questions': questions, 'activity': None}
+
+ student = get_current_student()
+ course_enrollment = get_enrollment("course", course, student.name)
+ status, score, result = check_quiz_completion(quiz, course_enrollment)
+ return {'questions': questions, 'activity': {'is_complete': status, 'score': score, 'result': result}}
+
+def get_topic_progress(topic, course_name, program):
+ """
+ Return the porgress of a course in a program as well as the content to continue from.
+ :param topic_name:
+ :param course_name:
+ """
student = get_current_student()
if not student:
return None
- enrollment_name = frappe.get_all("Course Enrollment", filters={'student': student.name, 'course':course_name})
- try:
- name = enrollment_name[0].name
- enrollment = frappe.get_doc("Course Enrollment", name)
- return enrollment
- except:
+ course_enrollment = get_or_create_course_enrollment(course_name, program)
+ progress = student.get_topic_progress(course_enrollment.name, topic)
+ if not progress:
return None
+ count = sum([activity['is_complete'] for activity in progress])
+ if count == 0:
+ return {'completed': False, 'started': False}
+ elif count == len(progress):
+ return {'completed': True, 'started': True}
+ elif count < len(progress):
+ return {'completed': False, 'started': True}
+
+def get_course_progress(course, program):
+ """
+ Return the porgress of a course in a program as well as the content to continue from.
+ :param topic_name:
+ :param course_name:
+ """
+ course_progress = []
+ for course_topic in course.topics:
+ topic = frappe.get_doc("Topic", course_topic.topic)
+ progress = get_topic_progress(topic, course.name, program)
+ if progress:
+ course_progress.append(progress)
+ if course_progress:
+ number_of_completed_topics = sum([activity['completed'] for activity in course_progress])
+ total_topics = len(course_progress)
+ if total_topics == 1:
+ return course_progress[0]
+ if number_of_completed_topics == 0:
+ return {'completed': False, 'started': False}
+ if number_of_completed_topics == total_topics:
+ return {'completed': True, 'started': True}
+ if number_of_completed_topics < total_topics:
+ return {'completed': False, 'started': True}
+
+ return None
+
+def get_program_progress(program):
+ program_progress = []
+ if not program.courses:
+ return None
+ for program_course in program.courses:
+ course = frappe.get_doc("Course", program_course.course)
+ progress = get_course_progress(course, program.name)
+ if progress:
+ progress['name'] = course.name
+ progress['course'] = course.course_name
+ program_progress.append(progress)
+
+ if program_progress:
+ return program_progress
+
+ return None
+
+def get_program_completion(program):
+ topics = frappe.db.sql("""select `tabCourse Topic`.topic, `tabCourse Topic`.parent
+ from `tabCourse Topic`,
+ `tabProgram Course`
+ where `tabCourse Topic`.parent = `tabProgram Course`.course
+ and `tabProgram Course`.parent = %s""", program.name)
+
+ progress = []
+ for topic in topics:
+ topic_doc = frappe.get_doc('Topic', topic[0])
+ topic_progress = get_topic_progress(topic_doc, topic[1], program.name)
+ if topic_progress:
+ progress.append(topic_progress)
+
+ if progress:
+ number_of_completed_topics = sum([activity['completed'] for activity in progress if activity])
+ total_topics = len(progress)
+ try:
+ return int((float(number_of_completed_topics)/total_topics)*100)
+ except ZeroDivisionError:
+ return 0
+
+ return 0
def create_student_from_current_user():
user = frappe.get_doc("User", frappe.session.user)
+
student = frappe.get_doc({
"doctype": "Student",
"first_name": user.first_name,
@@ -115,12 +337,21 @@
"student_email_id": user.email,
"user": frappe.session.user
})
+
student.save(ignore_permissions=True)
return student
-def enroll_in_course(course_name, program_name):
+def get_or_create_course_enrollment(course, program):
student = get_current_student()
- return student.enroll_in_course(course_name=course_name, program_enrollment=get_program_enrollment(program_name))
+ course_enrollment = get_enrollment("course", course, student.name)
+ if not course_enrollment:
+ program_enrollment = get_enrollment('program', program, student.name)
+ if not program_enrollment:
+ frappe.throw("You are not enrolled in program {0}".format(program))
+ return
+ return student.enroll_in_course(course_name=course, program_enrollment=get_enrollment('program', program, student.name))
+ else:
+ return frappe.get_doc('Course Enrollment', course_enrollment)
def check_content_completion(content_name, content_type, enrollment_name):
activity = frappe.get_all("Course Activity", filters={'enrollment': enrollment_name, 'content_type': content_type, 'content': content_name})
@@ -131,7 +362,7 @@
def check_quiz_completion(quiz, enrollment_name):
attempts = frappe.get_all("Quiz Activity", filters={'enrollment': enrollment_name, 'quiz': quiz.name}, fields=["name", "activity_date", "score", "status"])
- status = False if quiz.max_attempts == 0 else bool(len(attempts) == quiz.max_attempts)
+ status = False if quiz.max_attempts == 0 else bool(len(attempts) >= quiz.max_attempts)
score = None
result = None
if attempts:
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index bdb2080..70ac6fe 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -446,7 +446,7 @@
else:
component_row.additional_amount = amount
- if not overwrite:
+ if not overwrite and component_row.default_amount:
amount += component_row.default_amount
component_row.amount = amount
diff --git a/erpnext/manufacturing/report/bom_items_and_scraps/__init__.py b/erpnext/manufacturing/report/bom_explorer/__init__.py
similarity index 100%
rename from erpnext/manufacturing/report/bom_items_and_scraps/__init__.py
rename to erpnext/manufacturing/report/bom_explorer/__init__.py
diff --git a/erpnext/manufacturing/report/bom_items_and_scraps/bom_items_and_scraps.js b/erpnext/manufacturing/report/bom_explorer/bom_explorer.js
similarity index 83%
rename from erpnext/manufacturing/report/bom_items_and_scraps/bom_items_and_scraps.js
rename to erpnext/manufacturing/report/bom_explorer/bom_explorer.js
index ebff39f..b94d3f3 100644
--- a/erpnext/manufacturing/report/bom_items_and_scraps/bom_items_and_scraps.js
+++ b/erpnext/manufacturing/report/bom_explorer/bom_explorer.js
@@ -2,7 +2,7 @@
// For license information, please see license.txt
/* eslint-disable */
-frappe.query_reports["BOM Items and Scraps"] = {
+frappe.query_reports["BOM Explorer"] = {
"filters": [
{
fieldname: "bom",
diff --git a/erpnext/manufacturing/report/bom_items_and_scraps/bom_items_and_scraps.json b/erpnext/manufacturing/report/bom_explorer/bom_explorer.json
similarity index 71%
rename from erpnext/manufacturing/report/bom_items_and_scraps/bom_items_and_scraps.json
rename to erpnext/manufacturing/report/bom_explorer/bom_explorer.json
index bebe85d..93cba17 100644
--- a/erpnext/manufacturing/report/bom_items_and_scraps/bom_items_and_scraps.json
+++ b/erpnext/manufacturing/report/bom_explorer/bom_explorer.json
@@ -1,20 +1,20 @@
{
"add_total_row": 0,
- "creation": "2019-05-14 12:06:14.998746",
+ "creation": "2019-06-06 15:42:53.021714",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
- "modified": "2019-05-14 12:06:14.998746",
+ "modified": "2019-06-06 15:42:53.021714",
"modified_by": "Administrator",
"module": "Manufacturing",
- "name": "BOM Items and Scraps",
+ "name": "BOM Explorer",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "BOM",
- "report_name": "BOM Items and Scraps ",
+ "report_name": "BOM Explorer",
"report_type": "Script Report",
"roles": [
{
diff --git a/erpnext/manufacturing/report/bom_items_and_scraps/bom_items_and_scraps.py b/erpnext/manufacturing/report/bom_explorer/bom_explorer.py
similarity index 100%
rename from erpnext/manufacturing/report/bom_items_and_scraps/bom_items_and_scraps.py
rename to erpnext/manufacturing/report/bom_explorer/bom_explorer.py
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index b94f0b2..334e2ca 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -604,4 +604,5 @@
erpnext.patches.v11_1.delete_scheduling_tool
erpnext.patches.v12_0.make_custom_fields_for_bank_remittance
execute:frappe.delete_doc_if_exists("Page", "support-analytics")
+erpnext.patches.v12_0.make_item_manufacturer
erpnext.patches.v12_0.set_priority_for_support
diff --git a/erpnext/patches/v12_0/make_item_manufacturer.py b/erpnext/patches/v12_0/make_item_manufacturer.py
new file mode 100644
index 0000000..ebc2832
--- /dev/null
+++ b/erpnext/patches/v12_0/make_item_manufacturer.py
@@ -0,0 +1,27 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ frappe.reload_doc("stock", "doctype", "item_manufacturer")
+
+ item_manufacturer = []
+ for d in frappe.db.sql(""" SELECT name, manufacturer, manufacturer_part_no, creation, owner
+ FROM `tabItem` WHERE manufacturer is not null and manufacturer != ''""", as_dict=1):
+ item_manufacturer.append((
+ frappe.generate_hash("", 10),
+ d.name,
+ d.manufacturer,
+ d.manufacturer_part_no,
+ d.creation,
+ d.owner
+ ))
+
+ if item_manufacturer:
+ frappe.db.sql('''
+ INSERT INTO `tabItem Manufacturer`
+ (`name`, `item_code`, `manufacturer`, `manufacturer_part_no`, `creation`, `owner`)
+ VALUES {}'''.format(', '.join(['%s'] * len(item_manufacturer))), tuple(item_manufacturer)
+ )
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index bb19803..be7189b 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -55,8 +55,5 @@
"stock/dashboard/item_dashboard.html",
"stock/dashboard/item_dashboard_list.html",
"stock/dashboard/item_dashboard.js"
- ],
- "js/lms.min.js": [
- "public/js/education/lms/lms.js"
]
}
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index f2fe3fe..7e61f03 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -14,8 +14,8 @@
this._super();
},
- onload: function() {
- this.setup_queries();
+ onload: function(doc, cdt, cdn) {
+ this.setup_queries(doc, cdt, cdn);
this._super();
this.frm.set_query('shipping_rule', function() {
@@ -50,7 +50,7 @@
/* eslint-enable */
},
- setup_queries: function() {
+ setup_queries: function(doc, cdt, cdn) {
var me = this;
if(this.frm.fields_dict.buying_price_list) {
@@ -90,6 +90,15 @@
}
}
});
+
+
+ this.frm.set_query("manufacturer", "items", function(doc, cdt, cdn) {
+ const row = locals[cdt][cdn];
+ return {
+ query: "erpnext.controllers.queries.item_manufacturer_query",
+ filters:{ 'item_code': row.item_code }
+ }
+ });
},
refresh: function(doc) {
@@ -338,6 +347,25 @@
}
})
}
+ },
+
+ manufacturer: function(doc, cdt, cdn) {
+ const row = locals[cdt][cdn];
+
+ if(row.manufacturer) {
+ frappe.call({
+ method: "erpnext.stock.doctype.item_manufacturer.item_manufacturer.get_item_manufacturer_part_no",
+ args: {
+ 'item_code': row.item_code,
+ 'manufacturer': row.manufacturer
+ },
+ callback: function(r) {
+ if (r.message) {
+ frappe.model.set_value(cdt, cdn, 'manufacturer_part_no', r.message);
+ }
+ }
+ });
+ }
}
});
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 329695e..bbd1f1c 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -460,6 +460,7 @@
weight_per_unit: item.weight_per_unit,
weight_uom: item.weight_uom,
uom : item.uom,
+ manufacturer: item.manufacturer,
stock_uom: item.stock_uom,
pos_profile: me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : '',
cost_center: item.cost_center,
diff --git a/erpnext/public/js/education/lms/call.js b/erpnext/public/js/education/lms/call.js
deleted file mode 100644
index e35acbd..0000000
--- a/erpnext/public/js/education/lms/call.js
+++ /dev/null
@@ -1,15 +0,0 @@
-frappe.ready(() => {
- frappe.provide('lms');
-
- lms.call = (method, args) => {
- const method_path = 'erpnext.www.lms.' + method;
- return new Promise((resolve, reject) => {
- return frappe.call({
- method: method_path,
- args,
- })
- .then(r => resolve(r.message))
- .fail(reject);
- });
- };
-});
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/Article.vue b/erpnext/public/js/education/lms/components/Article.vue
deleted file mode 100644
index eab1424..0000000
--- a/erpnext/public/js/education/lms/components/Article.vue
+++ /dev/null
@@ -1,44 +0,0 @@
-<template>
-<div>
- <ContentTitle :title="contentData.title" :author="contentData.author" :publishDate="contentData.publish_date">
- <slot></slot>
- </ContentTitle>
- <section class="article-content-section">
- <div>
- <div class="content" v-html="contentData.content"></div>
- <div class="text-right">
- </div>
- <div class="mt-3 text-right">
- <a class="text-muted" href="/report"><i class="octicon octicon-issue-opened" title="Report"></i> Report a
- Mistake</a>
- </div>
- </div>
- </section>
-</div>
-</template>
-<script>
-import ContentTitle from './ContentTitle.vue'
-export default {
- props: ['content', 'type'],
- name: 'Article',
- data() {
- return {
- contentData: ''
- }
- },
- mounted() {
- this.getContent().then(data => this.contentData = data);
- },
- methods: {
- getContent() {
- return lms.call('get_content', {
- content_type: this.type,
- content: this.content
- })
- }
- },
- components: {
- ContentTitle
- }
-};
-</script>
diff --git a/erpnext/public/js/education/lms/components/Breadcrumb.vue b/erpnext/public/js/education/lms/components/Breadcrumb.vue
deleted file mode 100644
index 1b617a3..0000000
--- a/erpnext/public/js/education/lms/components/Breadcrumb.vue
+++ /dev/null
@@ -1,56 +0,0 @@
-<template>
- <div>
- <nav aria-label="breadcrumb">
- <ol class="breadcrumb">
- <li v-for="(route, index) in routeData" class="breadcrumb-item active" aria-current="page">
- <router-link v-if="index != routeData.length - 1" :to="route.route">
- {{ route.label }}
- </router-link>
- <span v-else>{{ route.label }}</span>
- </li>
- </ol>
- </nav>
- </div>
-</template>
-<script type="text/javascript">
- export default {
- name: "Breadcrumb",
- data() {
- return {
- routeName: this.$route.name,
- routeParams: this.$route.params,
- routeData: [{
- label: "All Programs",
- route: "/List/Program"
- }]
- }
- },
- mounted() {
- this.buildBreadcrumb()
- },
- methods: {
- buildBreadcrumb() {
- if(this.routeName == 'program') {
- return
- }
- if(this.routeName == 'course') {
- let routeObject = {
- label: this.routeParams.program_name,
- route: `/Program/${this.routeParams.program_name}`
- }
- this.routeData.push(routeObject)
- }
- if(this.routeName == 'content') {
- this.routeData.push({
- label: this.routeParams.program_name,
- route: `/Program/${this.routeParams.program_name}`
- })
- this.routeData.push({
- label: this.routeParams.course_name,
- route: `/Program/${this.routeParams.program_name}/${this.routeParams.course_name}`
- })
- }
- }
- }
- };
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/Button.vue b/erpnext/public/js/education/lms/components/Button.vue
deleted file mode 100644
index 4d8df4b..0000000
--- a/erpnext/public/js/education/lms/components/Button.vue
+++ /dev/null
@@ -1,25 +0,0 @@
-<template>
- <button :class="classList" v-on="$listeners" v-bind="$attrs" @click="goToRoute">
- <slot></slot>
- </button>
-</template>
-<script>
-export default {
- name: 'AButton',
- props: ['type', 'size', 'route'],
- computed: {
- classList() {
- return [
- 'btn',
- 'btn-' + this.type,
- 'btn-' + this.size
- ]
- }
- },
- methods: {
- goToRoute() {
- this.$router.push(this.route);
- }
- }
-}
-</script>
diff --git a/erpnext/public/js/education/lms/components/CardList.vue b/erpnext/public/js/education/lms/components/CardList.vue
deleted file mode 100644
index 10f6af0..0000000
--- a/erpnext/public/js/education/lms/components/CardList.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-<template>
- <div class="featured-products-section py-3">
- <h5 class='featured-heading' v-html="title"></h5>
- <div class="featured-products row">
- <!-- <p class='lead text-center' v-html="description"></p> -->
- <slot name="card-list-slot"></slot>
- </div>
- <div class='mt-4 text-center'>
- <slot name="list-bottom"></slot>
- </div>
- </div>
-</template>
-<script>
-export default {
- props:['title', 'description'],
- name: "CardList",
-};
-</script>
-<style scoped>
-
-.featured-heading {
- text-transform: uppercase;
- letter-spacing: 0.5px;
- font-size: 12px;
- font-weight: 500;
-}
-
-</style>
diff --git a/erpnext/public/js/education/lms/components/ContentNavigation.vue b/erpnext/public/js/education/lms/components/ContentNavigation.vue
deleted file mode 100644
index a07c0f8..0000000
--- a/erpnext/public/js/education/lms/components/ContentNavigation.vue
+++ /dev/null
@@ -1,40 +0,0 @@
-<template>
- <div class="nav-buttons">
- <button class='btn btn-outline-secondary' @click="$router.go(-1)">Back</button>
- <button v-if="nextContent" class='btn btn-primary' @click="goNext()">Next</button>
- <button v-else class='btn btn-primary' @click="finish()">Finish Topic</button>
- </div>
-</template>
-
-<script>
-export default {
- props: ['nextContent', 'nextContentType'],
- name: 'ContentNavigation',
- methods: {
- addActivity() {
- if(this.$route.params.type != "Quiz"){
- console.log("Adding Activity")
- lms.call("add_activity",
- {
- course: this.$route.params.course_name,
- content_type: this.$route.params.type,
- content: this.$route.params.content,
- }
- )
- }
- },
- goNext() {
- this.addActivity()
- this.$router.push({ name: 'content', params: { course: this.$route.params.course_name, type:this.nextContentType, content:this.nextContent }})
- },
- finish() {
- this.addActivity()
- this.$router.push({ name: 'course', params: { program_name: this.$route.params.program_name, course_name: this.$route.params.course_name}})
- lms.trigger('course-completed', course_name);
- }
- }
-};
-</script>
-
-<style lang="css" scoped>
-</style>
diff --git a/erpnext/public/js/education/lms/components/ContentTitle.vue b/erpnext/public/js/education/lms/components/ContentTitle.vue
deleted file mode 100644
index a488ab8..0000000
--- a/erpnext/public/js/education/lms/components/ContentTitle.vue
+++ /dev/null
@@ -1,29 +0,0 @@
-<template>
- <section class='article-top-section video-section-bg'>
- <div>
- <div class="row">
- <div class="col-md-8">
- <h2>{{ title }}</h2>
- <span v-if="typeof author !== 'undefined' || author !== null" class="text-muted">
- <span v-if="publishDate">Published on {{ publishDate }}</span>
- <span v-if="author">— {{ author }}</span>
- </span>
- </div>
- <div class="col-md-4 text-right">
- <slot></slot>
- </div>
- </div>
- <hr>
- </div>
- </section>
-</template>
-
-<script>
-export default {
- props: ['title', 'publishDate', 'author'],
- name: 'ContentTitle',
-};
-</script>
-
-<style lang="css" scoped>
-</style>
diff --git a/erpnext/public/js/education/lms/components/CourseCard.vue b/erpnext/public/js/education/lms/components/CourseCard.vue
deleted file mode 100644
index 48a9f59..0000000
--- a/erpnext/public/js/education/lms/components/CourseCard.vue
+++ /dev/null
@@ -1,87 +0,0 @@
-<template>
- <div class="py-3 col-md-4 col-sm-12">
- <div class="card h-100">
- <div class="card-hero-img" v-if="course.hero_image" v-bind:style="{ 'background-image': 'url(' + image + ')' }"></div>
- <div v-else class="card-image-wrapper">
- <div class="image-body">{{ course.course_name }}</div>
- </div>
- <div class='card-body'>
- <h5 class="card-title">{{ course.course_name }}</h5>
- <span class="course-list text-muted" id="getting-started">
- {{ course.course_intro.substring(0,120) }}
- </span>
- </div>
- <div class='p-3' style="display: flex; justify-content: space-between;">
- <div>
- <span v-if="complete"><i class="mr-2 text-success fa fa-check-circle" aria-hidden="true"></i>Course Complete</span>
- </div>
- <div class='text-right'>
- <a-button
- :type="'primary'"
- size="sm"
- :route="courseRoute"
- >
- {{ buttonName }}
- </a-button>
- </div>
- </div>
- </div>
- </div>
-</template>
-
-<script>
-import AButton from './Button.vue';
-
-export default {
- props: ['course', 'program_name'],
- name: "CourseCard",
- components: {
- AButton
- },
- data() {
- return {
- courseDetails: {},
- }
- },
- mounted() {
- if(lms.store.checkLogin()) this.getCourseDetails().then(data => this.courseDetails = data)
- },
- computed: {
- courseRoute() {
- return `${this.program_name}/${this.course.name}`
- },
- complete() {
- if(lms.store.checkProgramEnrollment(this.program_name)){
- if (this.courseDetails.flag === "Completed" ) {
- return true
- }
- else {
- return false
- }
- }
- else {
- return false
- }
- },
- isLogin() {
- return lms.store.checkLogin()
- },
- buttonName() {
- if(lms.store.checkProgramEnrollment(this.program_name)){
- return "Start Course"
- }
- else {
- return "Explore"
- }
- }
- },
- methods: {
- getCourseDetails() {
- return lms.call('get_student_course_details', {
- course_name: this.course.name,
- program_name: this.program_name
- })
- },
- }
-};
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/Navbar.vue b/erpnext/public/js/education/lms/components/Navbar.vue
deleted file mode 100644
index f3f3ce4..0000000
--- a/erpnext/public/js/education/lms/components/Navbar.vue
+++ /dev/null
@@ -1,85 +0,0 @@
-<template>
-<nav class="navbar navbar-light bg-white navbar-expand-lg sticky-top shadow-sm">
- <div class="container">
- <a class="navbar-brand" href="/lms">
- <span>{{ portal.title }}</span>
- </a>
- <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
- </button>
-
- <div class="collapse navbar-collapse" id="navbarSupportedContent">
- <ul class="navbar-nav mr-auto">
-
- <li class="nav-item">
- <a class="nav-link" href="lms#/List/Program">
- All Programs
- </a>
- </li>
-
- <li class="nav-item">
- <a class="nav-link" href="/lms#/Profile">
- Profile
- </a>
- </li>
- </ul>
- <ul class="navbar-nav ml-auto">
- <!-- post login tools -->
- <li v-if="isLogin" class="nav-item dropdown logged-in" id="website-post-login" data-label="website-post-login">
- <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
- <span class="user-image-wrapper">
- <span class="avatar avatar-small" :title="fullName">
- <span class="avatar-frame" :style="avatarStyle" :title="fullName"></span>
- </span>
- </span>
- <span class="full-name">{{ fullName }}</span>
- <b class="caret"></b>
- </a>
- <ul class="dropdown-menu dropdown-menu-right" role="menu">
- <a class="dropdown-item" href="/me" rel="nofollow"> My Account </a>
- <a class="dropdown-item" href="/?cmd=web_logout" rel="nofollow"> Logout </a>
- </ul>
- </li>
-
- <li v-else class="nav-item">
- <a class="nav-link btn-login-area" href="/login">Login</a>
- </li>
- </ul>
- </div>
- </div>
-</nav>
-</template>
-<script>
-export default {
- name: "Home",
- data() {
- return{
- portal: {},
- avatar: frappe.user_image,
- fullName: frappe.full_name,
- isLogin: frappe.is_user_logged_in()
- }
- },
- mounted() {
- this.getPortalDetails().then(data => this.portal = data);
- },
- methods: {
- getPortalDetails() {
- return lms.call("get_portal_details")
- }
- },
- computed: {
- avatarStyle() {
- return `background-image: url("${this.avatar}")`
- },
- // isLogin() {
- // return frappe.is_user_logged_in()
- // },
- }
-};
-</script>
-<style scoped>
-a {
- text-decoration: none;
-}
-</style>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/ProfileInfo.vue b/erpnext/public/js/education/lms/components/ProfileInfo.vue
deleted file mode 100644
index 5bad713..0000000
--- a/erpnext/public/js/education/lms/components/ProfileInfo.vue
+++ /dev/null
@@ -1,83 +0,0 @@
-<template>
- <div class="py-5">
- <div class="row">
- <div class="col-sm-12">
- <div>
- <h3>{{ fullName }}</h3>
- <ul>
- <li class="row">
- <div class="col-md-3 col-sm-4 pr-0 text-muted">Email:</div>
- <div class="col-md-9 col-sm-8">{{ email }}</div>
- </li>
- <li v-if="joiningDate" class="row">
- <div class="col-md-3 col-sm-4 pr-0 text-muted">Date of Joining:</div>
- <div class="col-md-9 col-sm-8">{{ joiningDate }}</div>
- </li>
- <li class="row">
- <div class="col-md-3 col-sm-4 pr-0 text-muted">Programs Enrolled:</div>
- <div class="col-md-9 col-sm-8">
- <ul v-if="enrolledPrograms">
- <li v-for="program in enrolledPrograms" :key="program">{{ program }}</li>
- </ul>
- <span v-else>None</span>
- </div>
- </li>
- </ul>
- </div>
- <a href="/update-profile" class="edit-button text-muted">Edit Profile</a>
- </div>
- </div>
- <div ></div>
- </div>
-</template>
-<script>
-
-export default {
- props: ['enrolledPrograms'],
- name: "ProfileInfo",
- data() {
- return {
- avatar: frappe.user_image,
- fullName: frappe.full_name,
- abbr: frappe.get_abbr(frappe.get_cookie("full_name")),
- email: frappe.session.user,
- joiningDate: ''
- }
- },
- mounted(){
- this.getJoiningDate().then(data => {
- if(data) {
- this.joiningDate = lms.moment(String(data)).format('D MMMM YYYY')
- }
- })
- },
- computed: {
- avatarStyle() {
- return `background-image: url("${this.avatar}")`
- },
- },
- methods: {
- getJoiningDate() {
- return lms.call("get_joining_date")
- }
- }
-};
-</script>
-<style scoped>
- .edit-button {
- position: absolute;
- top: 0;
- right: 0;
- }
-
- .standard-image {
- font-size: 72px;
- border-radius: 6px;
- }
-
- ul {
- list-style-type: none;
- padding: 0;
- margin: 0
- }
-</style>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/ProgramCard.vue b/erpnext/public/js/education/lms/components/ProgramCard.vue
deleted file mode 100644
index 15a9fcd..0000000
--- a/erpnext/public/js/education/lms/components/ProgramCard.vue
+++ /dev/null
@@ -1,82 +0,0 @@
-<template>
-<div class='py-3 col-md-4 col-sm-12'>
- <div class="card h-100">
- <router-link :to="'/Program/' + program.name">
- <div class="card-hero-img" v-if="program.hero_image" v-bind:style="{ 'background-image': 'url(' + image + ')' }"></div>
- <div v-else class="card-image-wrapper text-center">
- <div class="image-body">{{ program.program_name }}</div>
- </div>
- <div class='card-body'>
- <h5 class='card-title'>{{ program.program_name }}</h5>
- <div class="text-muted">{{ program.description.substring(0,120) }}...</div>
- </div>
- </router-link>
- <div class='text-right p-3'>
- <button v-if="program.intro_video" class='btn btn-light btn-sm' data-toggle="modal" data-target="#videoModal">Watch Intro</button>
- <a-button v-if="enrolled" type="dark" size="sm" :route="programPageRoute">
- {{ buttonName }}
- </a-button>
- <button v-else-if="isLogin" class='btn btn-dark btn-sm' @click="enroll()">{{ enrollButton }}</button>
- <a v-else class='btn btn-secondary btn-sm' href="/login#signup">Sign Up</a>
- </div>
- <VideoModal v-if="program.intro_video" :title="program.program_name" :video="program.intro_video"/>
- </div>
-</div>
-</template>
-<script>
-import AButton from './Button.vue';
-import VideoModal from './VideoModal.vue';
-export default {
- props: ['program', 'enrolled'],
- name: "ProgramCard",
- data() {
- return {
- isLogin: frappe.is_user_logged_in(),
- enrollButton: 'Enroll Now',
- programRoute: { name: 'program', params: { program_name: this.program.name }},
- image: "'" + this.program.hero_image + "'"
- };
- },
- methods: {
- enroll() {
- this.enrollButton = 'Enrolling...'
- lms.call('enroll_in_program', {
- program_name: this.program.name,
- }).then(data => {
- lms.store.updateEnrolledPrograms()
- this.$router.push(this.programRoute)
- })
- }
- },
- computed: {
- buttonName() {
- if(this.enrolled){
- return "Start Program"
- }
- else {
- return "Enroll"
- }
- },
- programPageRoute() {
- return this.programRoute
- },
- isEnrolled() {
- return lms.store.enrolledPrograms.includes(this.program.name)
- }
- },
- components: {
- AButton,
- VideoModal
- }
-};
-</script>
-
-<style lang="css" scoped>
- a {
- text-decoration: none;
- color: black;
- }
- a.btn-secondary {
- color: white !important;
- }
-</style>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/ProgressCard.vue b/erpnext/public/js/education/lms/components/ProgressCard.vue
deleted file mode 100644
index 66b61f6..0000000
--- a/erpnext/public/js/education/lms/components/ProgressCard.vue
+++ /dev/null
@@ -1,89 +0,0 @@
-<template>
- <div class='py-3 col-md-4 col-sm-12'>
- <div class="card h-100">
- <div class='card-body'>
- <router-link :to="'/Program/' + programData.name">
- <h5 class='card-title'>{{ programData.program }}</h5>
- </router-link>
- <span class="course-list text-muted" id="getting-started">
- Courses
- <ul class="mb-0 mt-1 list-unstyled" style="padding-left: 1.5em;">
- <li v-for="item in programData.progress" :key="item.name">
- <span v-if="item.is_complete"><i class="text-success fa fa-check-circle" aria-hidden="true"></i></span>
- <span v-else><i class="text-secondary fa fa-circle-o" aria-hidden="true"></i></span>
- {{ item.course_name }}
- </li>
- </ul>
- </span>
- </div>
- <div class='p-3' style="display: flex; justify-content: space-between;">
- <div></div>
- <div class='text-right'>
- <a-button
- :type="buttonType"
- size="sm btn-block"
- :route="programRoute"
- >
- {{ buttonName }}
- </a-button>
- </div>
- </div>
- </div>
- </div>
-</template>
-<script>
-import AButton from './Button.vue';
-export default {
- props: ['program'],
- name: "ProgressCard",
- data() {
- return {
- programData: {}
- };
- },
- mounted() {
- this.getProgramProgress().then(data => this.programData = data)
- },
- methods: {
- getProgramProgress() {
- return lms.call('get_program_progress', {
- program_name: this.program
- })
- },
- },
- computed: {
- programRoute() {
- return {name: 'program', params: {program_name: this.program}}
- },
- buttonType() {
- if (this.programData.percentage == 100 ){
- return "success"
- }
- else if (this.programData.percentage == "0" ) {
- return "secondary"
- }
- else {
- return "info"
- }
- },
- buttonName() {
- if (this.programData.percentage == 100 ){
- return "Program Complete"
- }
- else {
- return `${this.programData.percentage}% Completed`
- }
- }
- },
- components: {
- AButton
- },
-};
-</script>
-<style scoped>
-
- a {
- text-decoration: none;
- color: black;
- }
-</style>
diff --git a/erpnext/public/js/education/lms/components/Quiz.vue b/erpnext/public/js/education/lms/components/Quiz.vue
deleted file mode 100644
index 0a6199a..0000000
--- a/erpnext/public/js/education/lms/components/Quiz.vue
+++ /dev/null
@@ -1,119 +0,0 @@
-<template>
- <section class="quiz-section">
- <div>
- <div class="row">
- <div class="col-md-8">
- <h2>{{ content }}</h2>
- </div>
- </div>
- <div class="content">
- <hr>
- <div id="quiz" :name="content">
- <div id="quiz-body">
- <component v-for="question in quizData" :key="question.name" v-bind:is="question.type" :question="question" @updateResponse="updateResponse" :isDisabled="isDisabled"></component>
- </div>
- <div class="mt-3">
- <div>
- <div v-if="isDisabled || submitted" id="post-quiz-actions" class="row">
- <div class="col-md-8 text-left">
- <span v-html="message"></span>
- </div>
- <div class="col-md-4 text-right">
- <slot></slot>
- </div>
- </div>
- <div v-else id="quiz-actions" class="text-right">
- <button class='btn btn-outline-secondary' type="reset" :disabled="isDisabled">Reset</button>
- <button class='btn btn-primary' @click="submitQuiz" type="button" :disabled="isDisabled">Submit</button>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="mt-3 text-right">
- <a class="text-muted" href="/report"><i class="octicon octicon-issue-opened" title="Report"></i> Report a
- Mistake</a>
- </div>
- </div>
-</section>
-</template>
-
-<script>
-import QuizSingleChoice from "./Quiz/QuizSingleChoice.vue"
-import QuizMultipleChoice from "./Quiz/QuizMultipleChoice.vue"
-
-export default {
- props: ['content', 'type'],
- name: 'Quiz',
- data() {
- return {
- quizData: '',
- quizResponse: {},
- score: '',
- submitted: false,
- isDisabled: false,
- quizStatus: {},
- }
- },
- mounted() {
- this.getQuizWithoutAnswers().then(data => {
- this.quizData = data.quizData
- this.quizStatus = data.status
- this.isDisabled = data.status.is_complete
- });
- },
- components: {
- 'SingleChoice': QuizSingleChoice,
- 'MultipleChoice': QuizMultipleChoice
- },
- methods: {
- getQuizWithoutAnswers() {
- return lms.call("get_quiz_without_answers",
- {
- quiz_name: this.content,
- course_name: this.$route.params.course_name
- }
- )
- },
- updateResponse(res) {
- this.quizResponse[res.question] = res.option
- },
- submitQuiz() {
- lms.call("evaluate_quiz",
- {
- quiz_response: this.quizResponse,
- quiz_name: this.content,
- course: this.$route.params.course_name
- }
- ).then(data => {
- this.score = data
- this.submitted = true
- this.quizResponse = null
- });
- }
- },
- computed: {
- currentComponent: function() {
- if(this.quizData.type === "MultipleChoice") {
- return 'QuizMultipleChoice'
- }
- else {
- return 'QuizSingleChoice'
- }
- },
- message: function() {
- if(this.submitted) {
- return '<h3>Your Score: <span id="result">'+ this.score +'</span></h3>'
- }
- let message = '<h4>You have exhausted all attempts for this quiz.</h4>'
- if(this.quizStatus.result == 'Pass') {
- message = "<h4>You have successfully completed this quiz.</h4>Score: " + this.quizStatus.score
- }
- return message
- }
- },
-};
-</script>
-
-<style lang="css" scoped>
-</style>
diff --git a/erpnext/public/js/education/lms/components/Quiz/QuizMultipleChoice.vue b/erpnext/public/js/education/lms/components/Quiz/QuizMultipleChoice.vue
deleted file mode 100644
index 338b1ac..0000000
--- a/erpnext/public/js/education/lms/components/Quiz/QuizMultipleChoice.vue
+++ /dev/null
@@ -1,34 +0,0 @@
-<template>
- <div class="question mt-4">
- <h5>{{ question.question }}</h5>
- <div class="options ml-2">
- <div v-for="option in question.options" :key="option.name" class="form-check pb-1">
- <input v-model="checked" class="form-check-input" type="checkbox" :name="question.name" :id="option.name" :value="option.name" @change="emitResponse(question.name, option.name)" :disabled="isDisabled">
- <label class="form-check-label" :for="option.name">
- {{ option.option }}
- </label>
- </div>
- </div>
-</div>
-</template>
-
-<script>
-export default {
- props: ['question', 'isDisabled'],
- name: 'QuizSingleChoice',
- data() {
- return {
- checked: []
- }
- },
- methods: {
- emitResponse(q, o) {
- console.log(this.checked)
- this.$emit('updateResponse', {'question':q , 'option': this.checked, 'type': this.question.type})
- }
- }
-};
-</script>
-
-<style lang="css" scoped>
-</style>
diff --git a/erpnext/public/js/education/lms/components/Quiz/QuizSingleChoice.vue b/erpnext/public/js/education/lms/components/Quiz/QuizSingleChoice.vue
deleted file mode 100644
index 235cbce..0000000
--- a/erpnext/public/js/education/lms/components/Quiz/QuizSingleChoice.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-<template>
- <div class="question mt-4">
- <h5>{{ question.question }}</h5>
- <div class="options ml-2">
- <div v-for="option in question.options" :key="option.name" class="form-check pb-1">
- <input class="form-check-input" type="radio" :name="question.name" :id="option.name" :value="option.name" @change="emitResponse(question.name, option.name)" :disabled="isDisabled">
- <label class="form-check-label" :for="option.name">
- {{ option.option }}
- </label>
- </div>
- </div>
-</div>
-</template>
-
-<script>
-export default {
- props: ['question', 'isDisabled'],
- name: 'QuizSingleChoice',
- methods: {
- emitResponse(q, o) {
- this.$emit('updateResponse', {'question':q , 'option': o, 'type': this.question.type})
- }
- }
-};
-</script>
-
-<style lang="css" scoped>
-</style>
diff --git a/erpnext/public/js/education/lms/components/ScoreCard.vue b/erpnext/public/js/education/lms/components/ScoreCard.vue
deleted file mode 100644
index 80b12cb..0000000
--- a/erpnext/public/js/education/lms/components/ScoreCard.vue
+++ /dev/null
@@ -1,60 +0,0 @@
-<template>
- <div v-if="quizData" class='py-3 col-md-4 col-sm-12'>
- <div class="card h-100">
- <div class='card-body'>
- <h5 class='card-title'>{{ quizData.program }}</h5>
- <div v-for="attempt in quizData.quiz_attempt" :key="attempt.content" class="course-list" id="getting-started">
- <div>
- {{ attempt.content }}
- <ul v-if="attempt.is_complete">
- <li><span class="text-muted">Score: </span>{{ attempt.score }}</li>
- <li><span class="text-muted">Status: </span>{{attempt.result }}</li>
- </ul>
- <span v-else>- Unattempted</span>
- </div>
- </div>
- </div>
- <div class='p-3' style="display: flex; justify-content: space-between;">
- <div></div>
- <div class='text-right'>
- <a-button
- :type="'primary'"
- size="sm btn-block"
- :route="programRoute"
- >
- Go To Program
- </a-button>
- </div>
- </div>
- </div>
- </div>
-</template>
-<script>
-import AButton from './Button.vue';
-export default {
- props: ['program'],
- name: "ScoreCard",
- data() {
- return {
- quizData: {}
- };
- },
- mounted() {
- this.getQuizProgress().then(data => this.quizData = data)
- },
- methods: {
- getQuizProgress() {
- return lms.call('get_quiz_progress_of_program', {
- program_name: this.program
- })
- },
- programRoute() {
- return {name: 'program', params: {program_name: this.program}}
- },
- },
- components: {
- AButton
- },
-};
-</script>
-
diff --git a/erpnext/public/js/education/lms/components/TopSection.vue b/erpnext/public/js/education/lms/components/TopSection.vue
deleted file mode 100644
index c27d003..0000000
--- a/erpnext/public/js/education/lms/components/TopSection.vue
+++ /dev/null
@@ -1,27 +0,0 @@
-<template>
-<div class="hero">
- <h1 class="text-center" v-html="title"></h1>
- <p class='text-center' v-html="description"></p>
- <p class="text-center padding">
- <slot></slot>
- </p>
-</div>
-</template>
-<script>
-
-export default {
- props: ['title', 'description'],
- name: "TopSection",
-};
-</script>
-<style scoped>
- .hero {
- padding-top: 50px;
- padding-bottom: 100px;
- }
-
- .hero h1 {
- font-size: 40px;
- font-weight: 200;
- }
-</style>
diff --git a/erpnext/public/js/education/lms/components/TopSectionButton.vue b/erpnext/public/js/education/lms/components/TopSectionButton.vue
deleted file mode 100644
index 0fa49d4..0000000
--- a/erpnext/public/js/education/lms/components/TopSectionButton.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-<template>
- <button v-if="isLoggedIn" class='btn btn-primary btn-md' @click="primaryAction()">{{ buttonName }}</button>
- <a v-else class='btn btn-primary btn-md' href="/login#signup">{{ buttonName }}</a>
-</template>
-<script>
-export default {
- name: "TopSectionButton",
- data() {
- return {
- buttonName: '',
- isLoggedIn: lms.store.checkLogin(),
- nextContent: '',
- nextContentType: '',
- nextCourse: '',
- link: '',
- }
- },
- mounted() {
- this.computeButtons()
- },
- methods: {
- computeButtons(){
- if(this.isLoggedIn){
- this.buttonName = 'Explore Programs'
- }
- else{
- this.buttonName = 'Sign Up'
- }
- },
- primaryAction() {
- if(this.$route.name == 'home'){
- this.$router.push('List/Program');
- }
- else if(this.$route.name == 'program' && lms.store.enrolledPrograms.includes(this.$route.params.program_name)){
- this.$router.push({ name: 'content', params: { program_name: this.$route.params.program_name, course: this.nextCourse, type: this.nextContentType, content: this.nextContent}})
- }
- else {
- lms.call("enroll_in_program",
- {
- program_name: this.$route.params.program_name,
- student_email_id: frappe.session.user
- }
- )
- lms.store.updateEnrolledPrograms()
- }
- },
- }
-};
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/TopicCard.vue b/erpnext/public/js/education/lms/components/TopicCard.vue
deleted file mode 100644
index 4cb8e85..0000000
--- a/erpnext/public/js/education/lms/components/TopicCard.vue
+++ /dev/null
@@ -1,112 +0,0 @@
-
-<template>
- <div class="py-3 col-md-4 col-sm-12">
- <div class="card h-100">
- <div class="card-hero-img" v-if="topic.hero_image" v-bind:style="{ 'background-image': 'url(' + image + ')' }"></div>
- <div v-else class="card-image-wrapper">
- <div class="image-body">{{ topic.topic_name }}</div>
- </div>
- <div class='card-body'>
- <h5 class="card-title">{{ topic.topic_name }}</h5>
- <span class="course-list text-muted" id="getting-started">
- Content
- <ul class="mb-0 mt-1" style="padding-left: 1.5em;">
- <li v-for="content in topic.topic_content" :key="content.name">
- <router-link v-if="isLogin" tag="a" :class="'text-muted'" :to="{name: 'content', params:{program_name: program_name, topic:topic.name, course_name: course_name, type:content.content_type, content: content.content} }">
- {{ content.content }}
- </router-link>
- <div v-else><span style="padding-right: 0.4em"></span>{{ content.content }}</div>
- </li>
- </ul>
- </span>
- </div>
- <div v-if="isLogin" class='p-3' style="display: flex; justify-content: space-between;">
- <div>
- <span v-if="complete"><i class="mr-2 text-success fa fa-check-circle" aria-hidden="true"></i>Course Complete</span>
- </div>
- <div class='text-right'>
- <a-button
- :type="'primary'"
- size="sm"
- :route="firstContentRoute"
- >
- {{ buttonName }}
- </a-button>
- </div>
- </div>
- </div>
- </div>
-</template>
-
-<script>
-import AButton from './Button.vue';
-
-export default {
- props: ['topic', 'course_name', 'program_name'],
- name: "TopicCard",
- data() {
- return {
- topicDetails: {}
- }
- },
- mounted() {
- if(lms.store.checkLogin()) this.gettopicDetails().then(data => this.topicDetails = data)
- },
- components: {
- AButton
- },
- computed: {
- firstContentRoute() {
- if(lms.store.checkLogin()){
- return `/Program/${this.program_name}/${this.course_name}/${this.topic.name}/${this.topicDetails.content_type}/${this.topicDetails.content}`
- }
- else {
- return {}
- }
- },
- complete() {
- if(lms.store.checkProgramEnrollment(this.program_name)){
- if (this.topicDetails.flag === "Completed" ) {
- return true
- }
- else {
- return false
- }
- }
- else {
- return false
- }
- },
- isLogin() {
- // return lms.store.checkProgramEnrollment(this.program_name)
- return lms.store.checkLogin()
- },
- buttonName() {
- if(lms.store.checkProgramEnrollment(this.program_name)){
- if (this.topicDetails.flag == 'Continue'){
- return 'Continue'
- }
- else {
- return 'Start Topic'
- }
- }
- else {
- return "Explore"
- }
- }
- },
- methods: {
- iconClass(content_type) {
- if(content_type == 'Video') return 'fa fa-play'
- if(content_type == 'Article') return 'fa fa-file-text-o'
- if(content_type == 'Quiz') return 'fa fa-question-circle-o'
- },
- gettopicDetails() {
- return lms.call('get_student_topic_details', {
- topic_name: this.topic.name,
- course_name: this.course_name,
- })
- },
- }
-};
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/Video.vue b/erpnext/public/js/education/lms/components/Video.vue
deleted file mode 100644
index 50b4dd4..0000000
--- a/erpnext/public/js/education/lms/components/Video.vue
+++ /dev/null
@@ -1,63 +0,0 @@
-<template>
-<div>
- <div class='mt-2'>
- <div>
- <div class="mt-3 row">
- <div class="col-md-8">
- <h2>{{ contentData.name }}</h2>
- <span class="text-muted">
- <i class="octicon octicon-clock" title="Duration"></i> <span v-if="contentData.duration"> {{ contentData.duration }} Mins — </span><span v-if="contentData.publish_date"> Published on {{ contentData.publish_date }}. </span>
- </span>
- </div>
- <div class="col-md-4 text-right">
- <slot></slot>
- </div>
- </div>
- <youtube-player :url="contentData.url" class="mt-3"/>
- <hr>
- </div>
-</div>
-<div class="video-description-section">
- <div>
- <div class="content" v-html="contentData.description">
- </div>
- <div class="text-right hidden">
- <a class='btn btn-outline-secondary' href="/classrooms/module">Previous</a>
- <a class='btn btn-primary' href="/classrooms/module">Next</a>
- </div>
- <div class="mt-3 text-right">
- <a class="text-muted" href="/report"><i class="octicon octicon-issue-opened" title="Report"></i> Report a
- Mistake</a>
- </div>
- </div>
-</div>
-</div>
-</template>
-<script>
-import YoutubePlayer from './YoutubePlayer.vue'
-
-export default {
- props: ['content', 'type'],
- name: 'Video',
- data() {
- return {
- contentData: '',
- }
- },
- components: {
- YoutubePlayer
- },
- mounted() {
- this.getContent()
- .then(data => this.contentData = data)
- },
- methods: {
- getContent() {
- return lms.call('get_content', {
- content_type: this.type,
- content: this.content
- })
- }
- }
-};
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/VideoModal.vue b/erpnext/public/js/education/lms/components/VideoModal.vue
deleted file mode 100644
index 71227ad..0000000
--- a/erpnext/public/js/education/lms/components/VideoModal.vue
+++ /dev/null
@@ -1,35 +0,0 @@
-<template>
- <div class="modal" id="videoModal" tabindex="-1" role="dialog">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <h5 class="modal-title">{{ title }}</h5>
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span id="close_modal" aria-hidden="true" @click="stopVideo()">×</span>
- </button>
- </div>
- <div class="modal-body">
- <youtube-player :url="video"/>
- </div>
- </div>
- </div>
- </div>
-</template>
-<script type="text/javascript">
-import YoutubePlayer from './YoutubePlayer.vue'
-
-export default {
- name: 'VideoModal',
- props: ['title', 'video'],
- components: {
- YoutubePlayer
- },
- methods: {
- stopVideo() {
- $('.yvideo').each(function() {
- this.contentWindow.postMessage('{"event":"command","func":"stopVideo","args":""}', '*')
- });
- }
- }
-};
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/YoutubePlayer.vue b/erpnext/public/js/education/lms/components/YoutubePlayer.vue
deleted file mode 100644
index 9377b57..0000000
--- a/erpnext/public/js/education/lms/components/YoutubePlayer.vue
+++ /dev/null
@@ -1,36 +0,0 @@
-<template>
- <div class="embed-responsive embed-responsive-16by9">
- <iframe class="embed-responsive-item yvideo" :src="'https://www.youtube.com/embed/' + videoID + '?version=3&enablejsapi=1'" allowfullscreen></iframe>
- </div>
-</template>
-<script type="text/javascript">
- export default {
- name: 'YoutubePlayer',
- props: ['url'],
- data() {
- return {
- videoID: ''
- }
- },
- watch: {
- url() {
- this.videoID = this.getVideoID(this.url)
- }
- },
- methods: {
- getVideoID(link) {
- if (!Array.prototype.last){
- Array.prototype.last = function(){
- return this[this.length - 1];
- };
- };
- if (link.includes('v=')){
- return link.split('v=')[1].split('&')[0]
- }
- else if (link.includes('youtu.be')) {
- return link.split('/').last().split('?')[0]
- }
- }
- }
- };
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/lms.js b/erpnext/public/js/education/lms/lms.js
deleted file mode 100644
index 4665b14..0000000
--- a/erpnext/public/js/education/lms/lms.js
+++ /dev/null
@@ -1,81 +0,0 @@
-import Vue from 'vue/dist/vue.js';
-import VueRouter from 'vue-router/dist/vue-router.js';
-import moment from 'moment/min/moment.min.js';
-
-import lmsRoot from "./lmsRoot.vue";
-import routes from './routes';
-import './call';
-
-Vue.use(VueRouter);
-
-var store = {
- enrolledPrograms: [],
- enrolledCourses: []
-};
-
-// let profile_page = `<a class="dropdown-item" href="/lms#/Profile" rel="nofollow"> LMS Profile </a>`
-// document.querySelector('#website-post-login > ul').innerHTML += profile_page
-
-frappe.ready(() => {
- frappe.provide('lms');
-
- lms.moment = moment;
-
- lms.store = new Vue({
- data: store,
- methods: {
- updateEnrolledPrograms() {
- if(this.checkLogin()) {
- lms.call("get_program_enrollments").then(data => {
- this.enrolledPrograms = data;
- });
- }
- },
- updateEnrolledCourses() {
- if(this.checkLogin()) {
- lms.call("get_all_course_enrollments").then(data => {
- this.enrolledCourses = data;
- });
- }
- },
- checkLogin() {
- return frappe.is_user_logged_in();
- },
- updateState() {
- this.checkLogin();
- this.updateEnrolledPrograms();
- this.updateEnrolledCourses();
- },
- checkProgramEnrollment(programName) {
- if(this.checkLogin()){
- if(this.enrolledPrograms) {
- if(this.enrolledPrograms.includes(programName)) {
- return true;
- }
- else {
- return false;
- }
- }
- else {
- return false;
- }
- }
- else {
- return false;
- }
- }
- }
- });
- lms.view = new Vue({
- el: "#lms-app",
- router: new VueRouter({ routes }),
- template: "<lms-root/>",
- components: { lmsRoot },
- mounted() {
- lms.store.updateState();
- }
- });
- lms.view.$router.afterEach((to, from) => {
- window.scrollTo(0,0);
- });
-});
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/lmsRoot.vue b/erpnext/public/js/education/lms/lmsRoot.vue
deleted file mode 100644
index d359265..0000000
--- a/erpnext/public/js/education/lms/lmsRoot.vue
+++ /dev/null
@@ -1,45 +0,0 @@
-<template>
- <div id="lms-root">
- <navbar></navbar>
- <main class="container my-5">
- <div class="page_content">
- <router-view :key="$route.fullPath"></router-view>
- </div>
- </main>
- </div>
-</template>
-<script>
-import Navbar from "./components/Navbar.vue"
-export default {
- name: "lmsRoot",
- components: {
- Navbar
- }
-};
-</script>
-<style>
- div.card-hero-img {
- height: 220px;
- background-size: cover;
- background-repeat: no-repeat;
- background-position: center;
- background-color: rgb(250, 251, 252);
- }
-
- .card-image-wrapper {
- display: flex;
- overflow: hidden;
- height: 220px;
- background-color: rgb(250, 251, 252);
- justify-content: center;
- }
-
- .image-body {
- align-self: center;
- color: #d1d8dd;
- font-size: 24px;
- font-weight: 600;
- line-height: 1;
- padding: 20px;
- }
-</style>
diff --git a/erpnext/public/js/education/lms/pages/ContentPage.vue b/erpnext/public/js/education/lms/pages/ContentPage.vue
deleted file mode 100644
index 224ee03..0000000
--- a/erpnext/public/js/education/lms/pages/ContentPage.vue
+++ /dev/null
@@ -1,84 +0,0 @@
-<template>
- <div>
- <component v-bind:is="currentComponent" :content="content" :type="type">
- <ContentNavigation :nextContent="nextContent" :nextContentType="nextContentType"/>
- </component>
- </div>
-</template>
-<script>
-import Article from "../components/Article.vue"
-import Quiz from "../components/Quiz.vue"
-import Video from "../components/Video.vue"
-import ContentNavigation from "../components/ContentNavigation.vue"
-
-export default {
- props:['program_name', 'course_name', 'topic', 'type', 'content'],
- name: "ContentPage",
- data() {
- return{
- nextContent: '',
- nextContentType: '',
- }
- },
- computed: {
- currentComponent: function() {
- if(this.type === "Article") {
- return 'Article'
- }
- else if(this.type === "Quiz") {
- return 'Quiz'
- }
- else if(this.type === "Video") {
- return 'Video'
- }
- },
- },
- mounted() {
- this.getNextContent().then(data => {
- this.nextContent = data.content,
- this.nextContentType = data.content_type
- });
- },
- methods: {
- getNextContent(){
- return lms.call("get_next_content",
- {
- current_content: this.content,
- current_content_type: this.type,
- topic: this.topic,
- }
- );
- }
- },
- components: {
- Article,
- Video,
- Quiz,
- ContentNavigation
- }
-};
-</script>
-
-<style>
-.footer-message {
- display: none;
-}
-
-.video-description-section {
- padding-top: 0em !important;
-}
-
-.article-top-section {
- padding-top: 0.5em !important;
- padding-bottom: 0rem !important;
-}
-
-.article-content-section {
- padding-top: 0em !important;
-}
-
-.quiz-section {
- padding-top: 0.5em !important;
- padding-bottom: 0rem !important;
-}
-</style>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/pages/CoursePage.vue b/erpnext/public/js/education/lms/pages/CoursePage.vue
deleted file mode 100644
index dc3d130..0000000
--- a/erpnext/public/js/education/lms/pages/CoursePage.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-<template>
-<div>
- <breadcrumb></breadcrumb>
- <TopSection v-bind:title="course.course_name" v-bind:description="course.course_intro">
- </TopSection>
- <CardList :title="'Topics'" :description="''">
- <TopicCard slot="card-list-slot" v-for="topic in topicData" :topic="topic" :course_name="course_name" :program_name="program_name" :key="topic.name"/>
- </CardList>
-</div>
-</template>
-<script>
-import TopSection from "../components/TopSection.vue"
-import CardList from "../components/CardList.vue"
-import TopicCard from "../components/TopicCard.vue"
-import Breadcrumb from "../components/Breadcrumb.vue"
-
-export default {
- props: ['program_name','course_name'],
- name: "CoursePage",
- components: {
- TopSection,
- CardList,
- TopicCard,
- Breadcrumb
- },
- data() {
- return {
- course: {},
- topicData: [],
- }
- },
- mounted() {
- this.getCourseDetails().then(data => this.course = data);
- this.getTopics().then(data => this.topicData = data);
- },
- methods: {
- getCourseDetails() {
- return lms.call('get_course_details', {
- course_name: this.course_name
- });
- },
- getTopics() {
- return lms.call('get_topics', {
- course_name: this.course_name
- })
- }
- }
-};
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/pages/Home.vue b/erpnext/public/js/education/lms/pages/Home.vue
deleted file mode 100644
index 6554a76..0000000
--- a/erpnext/public/js/education/lms/pages/Home.vue
+++ /dev/null
@@ -1,48 +0,0 @@
-<template>
-<div>
- <TopSection :title="portal.title" :description="portal.description">
- <TopSectionButton/>
- </TopSection>
- <CardList :title="'Featured Programs'" :description="'Master ERPNext'">
- <ProgramCard slot="card-list-slot" v-for="item in featuredPrograms" :key="item.program.name" :program="item.program" :enrolled="item.is_enrolled"/>
- <AButton slot="list-bottom" :type="'primary'" :size="'md'" :route="'List/Program'">View All</AButton>
- </CardList>
-</div>
-</template>
-<script>
-import Button from '../components/Button.vue';
-import TopSection from "../components/TopSection.vue"
-import CardList from "../components/CardList.vue"
-import ProgramCard from "../components/ProgramCard.vue"
-import TopSectionButton from "../components/TopSectionButton.vue"
-
-export default {
- name: "Home",
- data() {
- return{
- portal: {},
- featuredPrograms: {},
- // enrolledPrograms: new Set()
- }
- },
- components: {
- AButton: Button,
- TopSection,
- CardList,
- ProgramCard,
- TopSectionButton
- },
- mounted() {
- this.getPortalDetails().then(data => this.portal = data);
- this.getFeaturedPrograms().then(data => this.featuredPrograms = data);
- },
- methods: {
- getPortalDetails() {
- return lms.call("get_portal_details")
- },
- getFeaturedPrograms() {
- return lms.call("get_featured_programs")
- }
- }
-};
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/pages/ListPage.vue b/erpnext/public/js/education/lms/pages/ListPage.vue
deleted file mode 100644
index cf5cecc..0000000
--- a/erpnext/public/js/education/lms/pages/ListPage.vue
+++ /dev/null
@@ -1,53 +0,0 @@
-<template>
- <div>
- <TopSection :title="'Programs at ' + portal.title" :description="portal.description">
- <AButton v-if="isLogin" :type="'primary'" :size="'lg'" :route="{ name: 'signup'}">Sign Up</AButton>
- </TopSection>
- <CardList :title="'All Programs'" :description="''">
- <ProgramCard slot="card-list-slot" v-for="item in masterData" :key="item.program.name" :program="item.program" :enrolled="item.is_enrolled"/>
- </CardList>
- </div>
-</template>
-<script>
-import ProgramCard from '../components/ProgramCard.vue';
-import CourseCard from "../components/CourseCard.vue"
-import Button from '../components/Button.vue';
-import TopSection from "../components/TopSection.vue"
-import CardList from "../components/CardList.vue"
-
-
-export default {
- props: ['master'],
- name: "ListPage",
- components: {
- AButton: Button,
- CourseCard,
- ProgramCard,
- CardList,
- TopSection
- },
- data() {
- return {
- portal: {},
- masterData: {}
- }
- },
- mounted() {
- this.getPortalDetails().then(data => this.portal = data);
- this.getMaster().then(data => this.masterData = data);
- },
- methods: {
- getPortalDetails() {
- return lms.call("get_portal_details")
- },
- getMaster() {
- return lms.call("get_all_programs")
- }
- },
- computed: {
- isLogin() {
- return !lms.store.checkLogin()
- }
- }
-};
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/pages/ProfilePage.vue b/erpnext/public/js/education/lms/pages/ProfilePage.vue
deleted file mode 100644
index beff5eb..0000000
--- a/erpnext/public/js/education/lms/pages/ProfilePage.vue
+++ /dev/null
@@ -1,50 +0,0 @@
-<template>
-<div>
- <ProfileInfo :enrolledPrograms="enrolledPrograms"></ProfileInfo>
- <div v-if="enrolledPrograms">
- <CardList :title="'Your Progress'" :description="''">
- <ProgressCard slot="card-list-slot" v-for="program in enrolledPrograms" :program="program" :key="program"/>
- </CardList>
- <CardList :title="''" :description="''">
- <ScoreCard slot="card-list-slot" v-for="program in enrolledPrograms" :program="program" :key="program"/>
- </CardList>
- </div>
- <div v-else>
- You haven't enrolled in any programs yet.
- </div>
-
-</div>
-</template>
-<script>
-import Button from '../components/Button.vue';
-import TopSection from "../components/TopSection.vue"
-import CardList from "../components/CardList.vue"
-import ProgressCard from "../components/ProgressCard.vue"
-import ProfileInfo from "../components/ProfileInfo.vue"
-import ScoreCard from "../components/ScoreCard.vue"
-
-export default {
- name: "ProfilePage",
- components: {
- AButton: Button,
- TopSection,
- CardList,
- ProfileInfo,
- ProgressCard,
- ScoreCard
- },
- data() {
- return {
- enrolledPrograms: {},
- }
- },
- mounted() {
- this.getEnrolledPrograms().then(data => this.enrolledPrograms = data);
- },
- methods: {
- getEnrolledPrograms() {
- return lms.call("get_program_enrollments")
- }
- }
-};
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/pages/ProgramPage.vue b/erpnext/public/js/education/lms/pages/ProgramPage.vue
deleted file mode 100644
index 415c861..0000000
--- a/erpnext/public/js/education/lms/pages/ProgramPage.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-<template>
-<div>
- <breadcrumb></breadcrumb>
- <TopSection v-bind:title="program.program_name" v-bind:description="program.description">
- </TopSection>
- <CardList :title="'Courses'" :description="''">
- <CourseCard slot="card-list-slot" v-for="course in courseData" :course="course" :program_name="program_name" :key="course.name"/>
- </CardList>
-</div>
-</template>
-<script>
-import TopSection from "../components/TopSection.vue"
-import CardList from "../components/CardList.vue"
-import CourseCard from "../components/CourseCard.vue"
-import Breadcrumb from "../components/Breadcrumb.vue"
-
-export default {
- props: ['program_name'],
- name: "ProgramPage",
- components: {
- TopSection,
- CardList,
- CourseCard,
- Breadcrumb
- },
- data() {
- return {
- program: {},
- courseData: [],
- }
- },
- mounted() {
- this.getProgramDetails().then(data => this.program = data);
- this.getCourses().then(data => this.courseData = data);
- },
- methods: {
- getProgramDetails() {
- return lms.call('get_program', {
- program_name: this.program_name
- });
- },
- getCourses() {
- return lms.call('get_courses', {
- program_name: this.program_name
- })
- }
- }
-};
-</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/quiz.js b/erpnext/public/js/education/lms/quiz.js
new file mode 100644
index 0000000..1b520eb
--- /dev/null
+++ b/erpnext/public/js/education/lms/quiz.js
@@ -0,0 +1,186 @@
+class Quiz {
+ constructor(wrapper, options) {
+ this.wrapper = wrapper;
+ Object.assign(this, options);
+ this.questions = []
+ this.refresh();
+ }
+
+ refresh() {
+ this.get_quiz();
+ }
+
+ get_quiz() {
+ frappe.call('erpnext.education.utils.get_quiz', {
+ quiz_name: this.name,
+ course: this.course
+ }).then(res => {
+ this.make(res.message)
+ });
+ }
+
+ make(data) {
+ data.questions.forEach(question_data => {
+ let question_wrapper = document.createElement('div');
+ let question = new Question({
+ wrapper: question_wrapper,
+ ...question_data
+ });
+ this.questions.push(question)
+ this.wrapper.appendChild(question_wrapper);
+ })
+ if (data.activity.is_complete) {
+ this.disable()
+ let indicator = 'red'
+ let message = 'Your are not allowed to attempt the quiz again.'
+ if (data.activity.result == 'Pass') {
+ indicator = 'green'
+ message = 'You have already cleared the quiz.'
+ }
+
+ this.set_quiz_footer(message, indicator, data.activity.score)
+ }
+ else {
+ this.make_actions();
+ }
+ }
+
+ make_actions() {
+ const button = document.createElement("button");
+ button.classList.add("btn", "btn-primary", "mt-5", "mr-2");
+
+ button.id = 'submit-button';
+ button.innerText = 'Submit';
+ button.onclick = () => this.submit();
+ this.submit_btn = button
+ this.wrapper.appendChild(button);
+ }
+
+ submit() {
+ this.submit_btn.innerText = 'Evaluating..'
+ this.submit_btn.disabled = true
+ this.disable()
+ frappe.call('erpnext.education.utils.evaluate_quiz', {
+ quiz_name: this.name,
+ quiz_response: this.get_selected(),
+ course: this.course,
+ program: this.program
+ }).then(res => {
+ this.submit_btn.remove()
+ if (!res.message) {
+ frappe.throw("Something went wrong while evaluating the quiz.")
+ }
+
+ let indicator = 'red'
+ let message = 'Fail'
+ if (res.message.status == 'Pass') {
+ indicator = 'green'
+ message = 'Congratulations, you cleared the quiz.'
+ }
+
+ this.set_quiz_footer(message, indicator, res.message.score)
+ });
+ }
+
+ set_quiz_footer(message, indicator, score) {
+ const div = document.createElement("div");
+ div.classList.add("mt-5");
+ div.innerHTML = `<div class="row">
+ <div class="col-md-8">
+ <h4>${message}</h4>
+ <h5 class="text-muted"><span class="indicator ${indicator}">Score: ${score}/100</span></h5>
+ </div>
+ <div class="col-md-4">
+ <a href="${this.next_url}" class="btn btn-primary pull-right">${this.quiz_exit_button}</a>
+ </div>
+ </div>`
+
+ this.wrapper.appendChild(div)
+ }
+
+ disable() {
+ this.questions.forEach(que => que.disable())
+ }
+
+ get_selected() {
+ let que = {}
+ this.questions.forEach(question => {
+ que[question.name] = question.get_selected()
+ })
+ return que
+ }
+}
+
+class Question {
+ constructor(opts) {
+ Object.assign(this, opts);
+ this.make();
+ }
+
+ make() {
+ this.make_question()
+ this.make_options()
+ }
+
+ get_selected() {
+ let selected = this.options.filter(opt => opt.input.checked)
+ if (this.type == 'Single Correct Answer') {
+ if (selected[0]) return selected[0].name
+ }
+ if (this.type == 'Multiple Correct Answer') {
+ return selected.map(opt => opt.name)
+ }
+ return null
+ }
+
+ disable() {
+ let selected = this.options.forEach(opt => opt.input.disabled = true)
+ }
+
+ make_question() {
+ let question_wrapper = document.createElement('h5');
+ question_wrapper.classList.add('mt-3');
+ question_wrapper.innerText = this.question;
+ this.wrapper.appendChild(question_wrapper);
+ }
+
+ make_options() {
+ let make_input = (name, value) => {
+ let input = document.createElement('input');
+ input.id = name;
+ input.name = this.name;
+ input.value = value;
+ input.type = 'radio';
+ if (this.type == 'Multiple Correct Answer')
+ input.type = 'checkbox';
+ input.classList.add('form-check-input');
+ return input;
+ }
+
+ let make_label = function(name, value) {
+ let label = document.createElement('label');
+ label.classList.add('form-check-label');
+ label.htmlFor = name;
+ label.innerText = value;
+ return label
+ }
+
+ let make_option = function (wrapper, option) {
+ let option_div = document.createElement('div')
+ option_div.classList.add('form-check', 'pb-1')
+ let input = make_input(option.name, option.option);
+ let label = make_label(option.name, option.option);
+ option_div.appendChild(input)
+ option_div.appendChild(label)
+ wrapper.appendChild(option_div)
+ return {input: input, ...option}
+ }
+
+ let options_wrapper = document.createElement('div')
+ options_wrapper.classList.add('ml-2')
+ let option_list = []
+ this.options.forEach(opt => option_list.push(make_option(options_wrapper, opt)))
+ this.options = option_list
+ this.wrapper.appendChild(options_wrapper)
+ }
+}
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/routes.js b/erpnext/public/js/education/lms/routes.js
deleted file mode 100644
index 483f222..0000000
--- a/erpnext/public/js/education/lms/routes.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import Home from "./pages/Home.vue";
-import ProgramPage from "./pages/ProgramPage.vue";
-import CoursePage from "./pages/CoursePage.vue";
-import ContentPage from "./pages/ContentPage.vue";
-import ListPage from "./pages/ListPage.vue";
-import ProfilePage from "./pages/ProfilePage.vue";
-
-const routes = [{
- name: 'home',
- path: '',
- component: Home
-},
-{
- name: 'program',
- path: '/Program/:program_name',
- component: ProgramPage,
- props: true
-},
-{
- name: 'course',
- path: '/Program/:program_name/:course_name/',
- component: CoursePage,
- props: true,
-},
-{
- name: 'content',
- path: '/Program/:program_name/:course_name/:topic/:type/:content',
- component: ContentPage,
- props: true,
- beforeRouteUpdate (to, from, next) {
- if (lms.store.checkProgramEnrollment(to.params.program_name)) {
- next();
- } else {
- next({
- name: 'program',
- params: {
- program_name: to.params.program_name
- }
- });
- }
- }
-},
-{
- name: 'list',
- path: '/List/:master',
- component: ListPage,
- props: true
-},
-{
- name: 'signup',
- path: '/Signup',
- beforeEnter(to, from, next) {
- window.location = window.location.origin.toString() + '/login#signup';
- },
- component: Home,
- props: true
-},
-{
- name: 'login',
- path: '/Login',
- beforeEnter(to, from, next) {
- window.location = window.location.origin.toString() + '/login#login';
- },
- component: Home,
- props: true
-},
-{
- name: 'logout',
- path: '/Logout',
- beforeEnter(to, from, next) {
- window.location = window.location.origin.toString() + '/?cmd=web_logout';
- },
- component: Home,
- props: true
-},
-{
- name: 'profile',
- path: '/Profile',
- component: ProfilePage,
- props: true,
- beforeEnter: (to, from, next) => {
- if (!lms.store.checkLogin()) {
- next({
- name: 'home'
- });
- } else {
- next();
- }
- }
-}];
-
-export default routes;
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback/customer_feedback.js b/erpnext/quality_management/doctype/customer_feedback/customer_feedback.js
deleted file mode 100644
index 16ae9a1..0000000
--- a/erpnext/quality_management/doctype/customer_feedback/customer_feedback.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2018, Frappe and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Customer Feedback', {
- onload: function(frm){
- frm.set_value("date", frappe.datetime.get_today());
- $(".grid-add-row").hide();
- frm.refresh();
- },
- template: function(frm){ // Used to fetch the parameters of the selected feedback template
- frm.fields_dict.feedback.grid.remove_all();
- if(frm.doc.template){
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Customer Feedback Template",
- name: frm.doc.template
- },
- callback: function (data) {
- for (var i = 0; i < data.message.feedback_parameter.length; i++ ){
- frm.add_child("feedback");
- frm.fields_dict.feedback.get_value()[i].parameter = data.message.feedback_parameter[i].parameter;
- }
- frm.refresh();
- }
- });
- }
- }
-});
diff --git a/erpnext/quality_management/doctype/customer_feedback/customer_feedback.json b/erpnext/quality_management/doctype/customer_feedback/customer_feedback.json
deleted file mode 100644
index ffa7e4d..0000000
--- a/erpnext/quality_management/doctype/customer_feedback/customer_feedback.json
+++ /dev/null
@@ -1,259 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "QMS-FDBK-.#####",
- "beta": 0,
- "creation": "2018-10-02 12:23:38.437696",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "customer",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Customer",
- "length": 0,
- "no_copy": 0,
- "options": "Customer",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "template",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Template",
- "length": 0,
- "no_copy": 0,
- "options": "Customer Feedback Template",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "feedback_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Feedback",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "template.feedback_values",
- "fieldname": "feedback",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "feedback",
- "length": 0,
- "no_copy": 0,
- "options": "Customer Feedback Table",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-12 14:39:18.044191",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Customer Feedback",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback/customer_feedback.py b/erpnext/quality_management/doctype/customer_feedback/customer_feedback.py
deleted file mode 100644
index 6211c42..0000000
--- a/erpnext/quality_management/doctype/customer_feedback/customer_feedback.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class CustomerFeedback(Document):
- pass
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback/customer_feedback_dashboard.py b/erpnext/quality_management/doctype/customer_feedback/customer_feedback_dashboard.py
deleted file mode 100644
index 44ae123..0000000
--- a/erpnext/quality_management/doctype/customer_feedback/customer_feedback_dashboard.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from frappe import _
-
-def get_data():
- return {
- 'fieldname': 'feedback',
- 'transactions': [
- {
- 'label': _('Action'),
- 'items': ['Quality Action']
- }
- ],
- }
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback/customer_feedback_list.js b/erpnext/quality_management/doctype/customer_feedback/customer_feedback_list.js
deleted file mode 100644
index 7c5f767..0000000
--- a/erpnext/quality_management/doctype/customer_feedback/customer_feedback_list.js
+++ /dev/null
@@ -1,11 +0,0 @@
-frappe.listview_settings['Customer Feedback'] = {
- add_fields: ["action"],
- get_indicator: function(doc) {
- if(doc.action == "No Action") {
- return [__("No Action"), "green", "action,=,No Action"];
- }
- else if(doc.action == "Action Initialised") {
- return [__("Action Initialised"), "red", "action,=,Action Initialised"];
- }
- }
-};
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback/test_customer_feedback.js b/erpnext/quality_management/doctype/customer_feedback/test_customer_feedback.js
deleted file mode 100644
index 1003ee5..0000000
--- a/erpnext/quality_management/doctype/customer_feedback/test_customer_feedback.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Customer Feedback", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(1);
-
- frappe.run_serially([
- // insert a new Customer Survey
- () => frappe.tests.make('Customer Feedback', [
- // values to be set
- {key: 'value'}
- ]),
- () => {
- assert.equal(cur_frm.doc.key, 'value');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/quality_management/doctype/customer_feedback/test_customer_feedback.py b/erpnext/quality_management/doctype/customer_feedback/test_customer_feedback.py
deleted file mode 100644
index b5d6141..0000000
--- a/erpnext/quality_management/doctype/customer_feedback/test_customer_feedback.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and Contributors
-# See license.txt
-from __future__ import unicode_literals
-
-import frappe
-import unittest
-from erpnext.quality_management.doctype.customer_feedback_template.test_customer_feedback_template import create_template
-class TestCustomerFeedback(unittest.TestCase):
- def test_customer_feedback(self):
- create_template()
- test_create_feedback = create_feedback()
- test_get_feedback = get_feedback()
- self.assertEquals(test_create_feedback.name, test_get_feedback.name)
-
-def create_feedback():
- feedback = frappe.get_doc({
- "doctype": "Customer Feedback",
- "template": "FDBK-TMPL-_Test Customer Feedback Template",
- "date": ""+ frappe.utils.nowdate() +""
- })
- feedback_exist = frappe.get_list("Customer Feedback", filters={"date": ""+ feedback.date +""}, limit=1)
- if len(feedback_exist) == 0:
- feedback.insert()
- return feedback
- else:
- return feedback_exist[0]
-
-def get_feedback():
- feedback = frappe.get_list("Customer Feedback", limit=1)
- return feedback[0]
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback_table/__init__.py b/erpnext/quality_management/doctype/customer_feedback_table/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_table/__init__.py
+++ /dev/null
diff --git a/erpnext/quality_management/doctype/customer_feedback_table/customer_feedback_table.json b/erpnext/quality_management/doctype/customer_feedback_table/customer_feedback_table.json
deleted file mode 100644
index b9516b2..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_table/customer_feedback_table.json
+++ /dev/null
@@ -1,142 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-10-15 15:36:27.193355",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "parameter",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Parameter",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fieldname": "rating",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Rating",
- "length": 0,
- "no_copy": 0,
- "options": "1\n2\n3\n4\n5",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "qualitative_feedback",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Qualitative Feedback",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-01 14:29:03.273927",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Customer Feedback Table",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback_table/customer_feedback_table.py b/erpnext/quality_management/doctype/customer_feedback_table/customer_feedback_table.py
deleted file mode 100644
index ef1b183..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_table/customer_feedback_table.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class CustomerFeedbackTable(Document):
- pass
diff --git a/erpnext/quality_management/doctype/customer_feedback_template/customer_feedback_template.js b/erpnext/quality_management/doctype/customer_feedback_template/customer_feedback_template.js
deleted file mode 100644
index e318bf7..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_template/customer_feedback_template.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2018, Frappe and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Customer Feedback Template', {
-});
diff --git a/erpnext/quality_management/doctype/customer_feedback_template/customer_feedback_template.json b/erpnext/quality_management/doctype/customer_feedback_template/customer_feedback_template.json
deleted file mode 100644
index 1d1e344..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_template/customer_feedback_template.json
+++ /dev/null
@@ -1,259 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "format:FDBK-TMPL-{template}",
- "beta": 0,
- "creation": "2018-10-18 15:11:26.215480",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "template",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Template",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_3",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "scope",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Scope",
- "length": 0,
- "no_copy": 0,
- "options": "Company\nDepartment",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.scope == 'Department'",
- "fieldname": "department",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Department",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "feedback_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Feedback",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "feedback_parameter",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Feedback",
- "length": 0,
- "no_copy": 0,
- "options": "Customer Feedback Template Table",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-01 14:27:07.935761",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Customer Feedback Template",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback_template/customer_feedback_template.py b/erpnext/quality_management/doctype/customer_feedback_template/customer_feedback_template.py
deleted file mode 100644
index 7f2eb3d..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_template/customer_feedback_template.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class CustomerFeedbackTemplate(Document):
- pass
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback_template/test_customer_feedback_template.js b/erpnext/quality_management/doctype/customer_feedback_template/test_customer_feedback_template.js
deleted file mode 100644
index 77168e0..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_template/test_customer_feedback_template.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Customer Feedback Template", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(1);
-
- frappe.run_serially([
- // insert a new Customer Feedback Template
- () => frappe.tests.make('Customer Feedback Template', [
- // values to be set
- {key: 'value'}
- ]),
- () => {
- assert.equal(cur_frm.doc.key, 'value');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/quality_management/doctype/customer_feedback_template/test_customer_feedback_template.py b/erpnext/quality_management/doctype/customer_feedback_template/test_customer_feedback_template.py
deleted file mode 100644
index 2bc4334..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_template/test_customer_feedback_template.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and Contributors
-# See license.txt
-from __future__ import unicode_literals
-
-import frappe
-import unittest
-
-class TestCustomerFeedbackTemplate(unittest.TestCase):
- def test_customer_feedback_template(self):
- test_create_template = create_template()
- test_get_template = get_template()
- self.assertEquals(test_get_template.name, test_create_template.name)
-
-def create_template():
- template = frappe.get_doc({
- "doctype": "Customer Feedback Template",
- "template": "_Test Customer Feedback Template",
- "scope": "Company",
- "feedback_parameter": [
- {
- "parameter": "_Test Customer Feedback Template Parameter",
- }
- ]
- })
- template_exist = frappe.get_list("Customer Feedback Template", filters={"template": ""+ template.template +""}, fields=["name"], limit=1)
- if len(template_exist) == 0:
- template.insert()
- return template
- else:
- return template_exist[0]
-
-def get_template():
- template = frappe.get_list("Customer Feedback Template", filters={"template": "_Test Customer Feedback Template"}, limit=1)
- return template[0]
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback_template_table/__init__.py b/erpnext/quality_management/doctype/customer_feedback_template_table/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_template_table/__init__.py
+++ /dev/null
diff --git a/erpnext/quality_management/doctype/customer_feedback_template_table/customer_feedback_template_table.json b/erpnext/quality_management/doctype/customer_feedback_template_table/customer_feedback_template_table.json
deleted file mode 100644
index d28bb5d..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_template_table/customer_feedback_template_table.json
+++ /dev/null
@@ -1,75 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-10-18 15:23:03.854925",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "parameter",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Parameter",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-01 14:28:50.626709",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Customer Feedback Template Table",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/customer_feedback_template_table/customer_feedback_template_table.py b/erpnext/quality_management/doctype/customer_feedback_template_table/customer_feedback_template_table.py
deleted file mode 100644
index 082046d..0000000
--- a/erpnext/quality_management/doctype/customer_feedback_template_table/customer_feedback_template_table.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class CustomerFeedbackTemplateTable(Document):
- pass
diff --git a/erpnext/quality_management/doctype/quality_action/quality_action.js b/erpnext/quality_management/doctype/quality_action/quality_action.js
index 8cf8aa9..7078247 100644
--- a/erpnext/quality_management/doctype/quality_action/quality_action.js
+++ b/erpnext/quality_management/doctype/quality_action/quality_action.js
@@ -5,83 +5,29 @@
onload: function(frm) {
frm.set_value("date", frappe.datetime.get_today());
frm.refresh();
- $(".grid-add-row").hide();
- if (frm.doc.review){
- frm.set_value("type", "Quality Review");
- }
- else{
- frm.set_value("type", "Customer Feedback");
- }
},
- review: function(frm){
- frm.fields_dict.description.grid.remove_all();
- if(frm.doc.review){
- var problems = "";
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Quality Review",
- name: frm.doc.review
- },
- callback: function (data) {
- for (var i = 0; i < data.message.values.length; i++){
- if (data.message.values[i].achieved < data.message.values[i].target){
- problems += data.message.values[i].objective +"-"+ data.message.values[i].achieved + " " + data.message.values[i].unit + "\n";
- }
- }
- problems= problems.replace(/\n$/, "").split("\n");
- for (i = 0; i < problems.length; i++){
- frm.add_child("description");
- frm.fields_dict.description.get_value()[i].problem = problems[i];
- }
- frm.refresh();
+ document_name: function(frm){
+ frappe.call({
+ "method": "frappe.client.get",
+ args: {
+ doctype: frm.doc.document_type,
+ name: frm.doc.document_name
+ },
+ callback: function(data){
+ frm.fields_dict.resolutions.grid.remove_all();
+ let objectives = [];
+
+ if(frm.doc.document_type === "Quality Review"){
+ for(let i in data.message.reviews) objectives.push(data.message.reviews[i].review);
+ } else {
+ for(let j in data.message.parameters) objectives.push(data.message.parameters[j].feedback);
}
- });
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Quality Goal",
- name: frm.doc.goal
- },
- callback: function (data) {
- frm.doc.procedure = data.message.procedure;
- frm.refresh();
+ for (var objective in objectives){
+ frm.add_child("resolutions");
+ frm.fields_dict.resolutions.get_value()[objective].problem = objectives[objective];
}
- });
- }
- else{
- frm.doc.goal = '';
- frm.doc.procedure = '';
- frm.refresh();
- }
+ frm.refresh();
+ }
+ });
},
- feedback: function(frm) {
- frm.fields_dict.description.grid.remove_all();
- if(frm.doc.feedback){
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Customer Feedback",
- name: frm.doc.feedback
- },
- callback: function(data){
- for (var i = 0; i < data.message.feedback.length; i++ ){
- frm.add_child("description");
- frm.fields_dict.description.get_value()[i].problem = data.message.feedback[i].parameter +"-"+ data.message.feedback[i].qualitative_feedback;
- }
- frm.refresh();
- }
- });
- }
- },
- type: function(frm){
- if(frm.doc.description){
- frm.fields_dict.description.grid.remove_all();
- frm.doc.review = '';
- frm.doc.feedback = '';
- frm.doc.goal = '';
- frm.doc.procedure = '';
- frm.refresh();
- }
- }
});
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_action/quality_action.json b/erpnext/quality_management/doctype/quality_action/quality_action.json
index e564a56..8835b47 100644
--- a/erpnext/quality_management/doctype/quality_action/quality_action.json
+++ b/erpnext/quality_management/doctype/quality_action/quality_action.json
@@ -1,493 +1,125 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "format:QMS-ACTN-{#####}",
- "beta": 0,
- "creation": "2018-10-02 11:40:43.666100",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "autoname": "format:ACTN-{#####}",
+ "creation": "2018-10-02 11:40:43.666100",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "corrective_preventive",
+ "document_type",
+ "goal",
+ "cb_00",
+ "date",
+ "document_name",
+ "procedure",
+ "status",
+ "sb_00",
+ "resolutions"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "action",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Corrective/Preventive",
- "length": 0,
- "no_copy": 0,
- "options": "Corrective\nPreventive",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "depends_on": "eval:doc.type == 'Quality Review'",
+ "fetch_from": "review.goal",
+ "fieldname": "goal",
+ "fieldtype": "Link",
+ "label": "Goal",
+ "options": "Quality Goal",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.type == 'Quality Review'",
- "fieldname": "review",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Review",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Review",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Date",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.type == 'Customer Feedback'",
- "fieldname": "feedback",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Feedback",
- "length": 0,
- "no_copy": 0,
- "options": "Customer Feedback",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "depends_on": "eval:doc.type == 'Quality Review'",
+ "fieldname": "procedure",
+ "fieldtype": "Link",
+ "label": "Procedure",
+ "options": "Quality Procedure",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.type == 'Quality Review'",
- "fetch_from": "review.goal",
- "fieldname": "goal",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Quality Goal",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Goal",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "Open",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Status",
+ "options": "Open\nClosed"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_3",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "document_name",
+ "fieldtype": "Dynamic Link",
+ "label": "Document Name",
+ "options": "document_type"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "type",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Type",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Review\nCustomer Feedback",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "document_type",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Document Type",
+ "options": "Quality Review\nQuality Feedback",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "Corrective",
+ "fieldname": "corrective_preventive",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Corrective/Preventive",
+ "options": "Corrective\nPreventive",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.type == 'Quality Review'",
- "fetch_from": "",
- "fieldname": "procedure",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Procedure",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Procedure",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "status_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Status",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break",
+ "label": "Resolution"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Under Review",
- "fieldname": "status",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "Under Review\nClose",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_10",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "problem_resolution",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Description",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "description",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Action Description",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Action Table",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "resolutions",
+ "fieldtype": "Table",
+ "label": "Resolutions",
+ "options": "Quality Action Resolution"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-12 14:27:07.724362",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Quality Action",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2019-05-28 13:10:44.092497",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Action",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "All",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_action/quality_action.py b/erpnext/quality_management/doctype/quality_action/quality_action.py
index 620252e..88d4bd8 100644
--- a/erpnext/quality_management/doctype/quality_action/quality_action.py
+++ b/erpnext/quality_management/doctype/quality_action/quality_action.py
@@ -3,18 +3,8 @@
# For license information, please see license.txt
from __future__ import unicode_literals
+import frappe
from frappe.model.document import Document
class QualityAction(Document):
- def validate(self):
- status_flag = ''
- for value in self.description:
- if value.resolution == None:
- value.status = 'Open'
- status_flag = 'Under Review'
- else:
- value.status = 'Close'
- if status_flag == 'Under Review':
- self.status = 'Under Review'
- else:
- self.status = 'Close'
\ No newline at end of file
+ pass
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_action/quality_action_list.js b/erpnext/quality_management/doctype/quality_action/quality_action_list.js
deleted file mode 100644
index da6b65d..0000000
--- a/erpnext/quality_management/doctype/quality_action/quality_action_list.js
+++ /dev/null
@@ -1,11 +0,0 @@
-frappe.listview_settings['Quality Action'] = {
- add_fields: ["status"],
- get_indicator: function(doc) {
- if(doc.status == "Planned") {
- return [__("Planned"), "green", "status,=,Planned"];
- }
- else{
- return [__("Under Review"), "red", "status,=,Under Review"];
- }
- }
-};
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_action/test_quality_action.py b/erpnext/quality_management/doctype/quality_action/test_quality_action.py
index c47955c..51178d6 100644
--- a/erpnext/quality_management/doctype/quality_action/test_quality_action.py
+++ b/erpnext/quality_management/doctype/quality_action/test_quality_action.py
@@ -19,28 +19,28 @@
create_review()
test_create_action = create_action()
test_get_action = get_action()
- self.assertEquals(test_create_action.name, test_get_action.name)
- self.assertEquals(test_create_action.goal, test_get_action.goal)
+
+ self.assertEquals(test_create_action, test_get_action)
def create_action():
- review = frappe.get_list("Quality Review", limit=1)
+ review = frappe.db.exists("Quality Review", {"goal": "GOAL-_Test Quality Goal"})
action = frappe.get_doc({
- 'doctype': 'Quality Action',
- 'action': 'Corrective',
- 'type': 'Quality Review',
- 'review': ''+ review[0].name +'',
- 'date': ''+ frappe.utils.nowdate() +'',
- 'goal': '_Test Quality Goal',
- 'procedure': '_Test Quality Procedure'
+ "doctype": "Quality Action",
+ "action": "Corrective",
+ "document_type": "Quality Review",
+ "document_name": review,
+ "date": frappe.utils.nowdate(),
+ "goal": "GOAL-_Test Quality Goal",
+ "procedure": "PRC-_Test Quality Procedure"
})
- action_exist = frappe.get_list("Quality Action", filters={"review": ""+ review[0].name +""}, fields=["name", "goal"], limit=1)
- if len(action_exist) == 0:
+ action_exist = frappe.db.exists("Quality Action", {"review": review})
+
+ if not action_exist:
action.insert()
- return action
+ return action.name
else:
- return action_exist[0]
+ return action_exist
def get_action():
- review = frappe.get_list("Quality Review", limit=1)
- action = frappe.get_list("Quality Action", filters={"review": ""+ review[0].name +""}, fields=["name", "goal"], limit=1)
- return action[0]
\ No newline at end of file
+ review = frappe.db.exists("Quality Review", {"goal": "GOAL-_Test Quality Goal"})
+ return frappe.db.exists("Quality Action", {"document_name": review})
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_action_table/__init__.py b/erpnext/quality_management/doctype/quality_action_resolution/__init__.py
similarity index 100%
rename from erpnext/quality_management/doctype/quality_action_table/__init__.py
rename to erpnext/quality_management/doctype/quality_action_resolution/__init__.py
diff --git a/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.json b/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.json
new file mode 100644
index 0000000..74370cc
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.json
@@ -0,0 +1,40 @@
+{
+ "creation": "2019-05-26 20:36:44.337186",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "problem",
+ "sb_00",
+ "resolution"
+ ],
+ "fields": [
+ {
+ "fieldname": "problem",
+ "fieldtype": "Long Text",
+ "in_list_view": 1,
+ "label": "Problem"
+ },
+ {
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "resolution",
+ "fieldtype": "Text Editor",
+ "in_list_view": 1,
+ "label": "Resolution"
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-05-28 13:09:50.435323",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Action Resolution",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py b/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py
new file mode 100644
index 0000000..de8873f
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class QualityActionResolution(Document):
+ pass
diff --git a/erpnext/quality_management/doctype/quality_action_table/quality_action_table.json b/erpnext/quality_management/doctype/quality_action_table/quality_action_table.json
deleted file mode 100644
index a5f7fb6..0000000
--- a/erpnext/quality_management/doctype/quality_action_table/quality_action_table.json
+++ /dev/null
@@ -1,205 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-10-15 15:36:53.624990",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "problem",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Problem",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "resolution",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Resolution",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "status",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "Open\nClose",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "responsible",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Responsible",
- "length": 0,
- "no_copy": 0,
- "options": "Role",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "completion_date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Completion Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-12 14:33:46.260600",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Quality Action Table",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_action_table/quality_action_table.py b/erpnext/quality_management/doctype/quality_action_table/quality_action_table.py
deleted file mode 100644
index 9beb148..0000000
--- a/erpnext/quality_management/doctype/quality_action_table/quality_action_table.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class QualityActionTable(Document):
- pass
diff --git a/erpnext/quality_management/doctype/customer_feedback/__init__.py b/erpnext/quality_management/doctype/quality_feedback/__init__.py
similarity index 100%
rename from erpnext/quality_management/doctype/customer_feedback/__init__.py
rename to erpnext/quality_management/doctype/quality_feedback/__init__.py
diff --git a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js
new file mode 100644
index 0000000..63747af
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Quality Feedback', {
+ refresh: function(frm) {
+ frm.set_value("date", frappe.datetime.get_today());
+ },
+ template: function(frm){
+ frappe.call({
+ "method": "frappe.client.get",
+ args: {
+ doctype: "Quality Feedback Template",
+ name: frm.doc.template
+ },
+ callback: function(data){
+ frm.fields_dict.parameters.grid.remove_all();
+ for (var i in data.message.parameters){
+ frm.add_child("parameters");
+ frm.fields_dict.parameters.get_value()[i].parameter = data.message.parameters[i].parameter;
+ }
+ frm.refresh();
+ }
+ });
+ }
+});
diff --git a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json
new file mode 100644
index 0000000..460438a
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json
@@ -0,0 +1,95 @@
+{
+ "autoname": "format:FDBK-{#####}",
+ "creation": "2019-05-26 21:23:05.308379",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "document_type",
+ "template",
+ "cb_00",
+ "document_name",
+ "date",
+ "sb_00",
+ "parameters"
+ ],
+ "fields": [
+ {
+ "fieldname": "template",
+ "fieldtype": "Link",
+ "label": "Template",
+ "options": "Quality Feedback Template",
+ "reqd": 1
+ },
+ {
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Date",
+ "read_only": 1
+ },
+ {
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fetch_from": "template.feedback_values",
+ "fieldname": "parameters",
+ "fieldtype": "Table",
+ "label": "Parameters",
+ "options": "Quality Feedback Parameter"
+ },
+ {
+ "fieldname": "document_type",
+ "fieldtype": "Select",
+ "label": "Type",
+ "options": "User\nCustomer",
+ "reqd": 1
+ },
+ {
+ "fieldname": "document_name",
+ "fieldtype": "Dynamic Link",
+ "label": "Name",
+ "options": "document_type",
+ "reqd": 1
+ }
+ ],
+ "modified": "2019-05-28 15:16:01.161662",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Feedback",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "All",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py
new file mode 100644
index 0000000..9894181
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class QualityFeedback(Document):
+ pass
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_feedback/test_quality_feedback.py b/erpnext/quality_management/doctype/quality_feedback/test_quality_feedback.py
new file mode 100644
index 0000000..3be1eb2
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback/test_quality_feedback.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from erpnext.quality_management.doctype.quality_feedback_template.test_quality_feedback_template import create_template
+
+class TestQualityFeedback(unittest.TestCase):
+
+ def test_quality_feedback(self):
+ create_template()
+ test_create_feedback = create_feedback()
+ test_get_feedback = get_feedback()
+
+ self.assertEqual(test_create_feedback, test_get_feedback)
+
+def create_feedback():
+ create_customer()
+
+ feedabck = frappe.get_doc({
+ "doctype": "Quality Feedback",
+ "template": "TMPL-_Test Feedback Template",
+ "document_type": "Customer",
+ "document_name": "Quality Feedback Customer",
+ "date": frappe.utils.nowdate(),
+ "parameters": [
+ {
+ "parameter": "Test Parameter",
+ "rating": 3,
+ "feedback": "Test Feedback"
+ }
+ ]
+ })
+
+ feedback_exists = frappe.db.exists("Quality Feedback", {"template": "TMPL-_Test Feedback Template"})
+
+ if not feedback_exists:
+ feedabck.insert()
+ return feedabck.name
+ else:
+ return feedback_exists
+
+def get_feedback():
+ return frappe.db.exists("Quality Feedback", {"template": "TMPL-_Test Feedback Template"})
+
+def create_customer():
+ if not frappe.db.exists("Customer", {"customer_name": "Quality Feedback Customer"}):
+ customer = frappe.get_doc({
+ "doctype": "Customer",
+ "customer_name": "Quality Feedback Customer"
+ }).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_action_table/__init__.py b/erpnext/quality_management/doctype/quality_feedback_parameter/__init__.py
similarity index 100%
copy from erpnext/quality_management/doctype/quality_action_table/__init__.py
copy to erpnext/quality_management/doctype/quality_feedback_parameter/__init__.py
diff --git a/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.json b/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.json
new file mode 100644
index 0000000..d0b368f
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.json
@@ -0,0 +1,57 @@
+{
+ "creation": "2019-05-26 21:25:01.715807",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "parameter",
+ "cb_00",
+ "rating",
+ "sb_00",
+ "feedback"
+ ],
+ "fields": [
+ {
+ "fieldname": "parameter",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Parameter",
+ "read_only": 1
+ },
+ {
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "1",
+ "fieldname": "rating",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Rating",
+ "options": "1\n2\n3\n4\n5",
+ "reqd": 1
+ },
+ {
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "feedback",
+ "fieldtype": "Text Editor",
+ "in_list_view": 1,
+ "label": "Feedback",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-05-26 21:50:48.951264",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Feedback Parameter",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py b/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py
new file mode 100644
index 0000000..d652e8a
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class QualityFeedbackParameter(Document):
+ pass
diff --git a/erpnext/quality_management/doctype/customer_feedback_template/__init__.py b/erpnext/quality_management/doctype/quality_feedback_template/__init__.py
similarity index 100%
rename from erpnext/quality_management/doctype/customer_feedback_template/__init__.py
rename to erpnext/quality_management/doctype/quality_feedback_template/__init__.py
diff --git a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.js b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.js
new file mode 100644
index 0000000..490eed9
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Quality Feedback Template', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json
new file mode 100644
index 0000000..31efd04
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json
@@ -0,0 +1,59 @@
+{
+ "autoname": "format:TMPL-{template}",
+ "creation": "2019-05-26 21:17:24.283061",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "template",
+ "cb_00",
+ "sb_00",
+ "parameters"
+ ],
+ "fields": [
+ {
+ "fieldname": "template",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Template",
+ "reqd": 1
+ },
+ {
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "parameters",
+ "fieldtype": "Table",
+ "label": "Parameters",
+ "options": "Quality Feedback Template Parameter"
+ }
+ ],
+ "modified": "2019-05-26 21:48:47.770610",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Feedback Template",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py
new file mode 100644
index 0000000..0c6dfc0
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class QualityFeedbackTemplate(Document):
+ pass
diff --git a/erpnext/quality_management/doctype/quality_feedback_template/test_quality_feedback_template.py b/erpnext/quality_management/doctype/quality_feedback_template/test_quality_feedback_template.py
new file mode 100644
index 0000000..36dbe13
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback_template/test_quality_feedback_template.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestQualityFeedbackTemplate(unittest.TestCase):
+
+ def test_quality_feedback_template(self):
+ test_create_template = create_template()
+ test_get_template = get_template()
+
+ self.assertEqual(test_create_template, test_get_template)
+
+def create_template():
+ template = frappe.get_doc({
+ "doctype": "Quality Feedback Template",
+ "template": "_Test Feedback Template",
+ "parameters": [
+ {
+ "parameter": "Test Parameter"
+ }
+ ]
+ })
+
+ template_exists = frappe.db.exists("Quality Feedback Template", {"template": "_Test Feedback Template"})
+
+ if not template_exists:
+ template.insert()
+ return template.name
+ else:
+ return template_exists
+
+def get_template():
+ return frappe.db.exists("Quality Feedback Template", {"template": "_Test Feedback Template"})
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_action_table/__init__.py b/erpnext/quality_management/doctype/quality_feedback_template_parameter/__init__.py
similarity index 100%
copy from erpnext/quality_management/doctype/quality_action_table/__init__.py
copy to erpnext/quality_management/doctype/quality_feedback_template_parameter/__init__.py
diff --git a/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.json b/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.json
new file mode 100644
index 0000000..02a9b03
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.json
@@ -0,0 +1,28 @@
+{
+ "creation": "2019-05-26 21:20:40.520197",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "parameter"
+ ],
+ "fields": [
+ {
+ "fieldname": "parameter",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Parameter"
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-05-26 21:23:53.574743",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Feedback Template Parameter",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py b/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py
new file mode 100644
index 0000000..3f3348f
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class QualityFeedbackTemplateParameter(Document):
+ pass
diff --git a/erpnext/quality_management/doctype/quality_goal/quality_goal.js b/erpnext/quality_management/doctype/quality_goal/quality_goal.js
index 3bb6e12..ff58c5a 100644
--- a/erpnext/quality_management/doctype/quality_goal/quality_goal.js
+++ b/erpnext/quality_management/doctype/quality_goal/quality_goal.js
@@ -2,40 +2,7 @@
// For license information, please see license.txt
frappe.ui.form.on('Quality Goal', {
- onload: function(frm){
- if(frm.doc.measurable == "No"){
- hide_target_unit(frm);
- }
- else{
- show_target_unit(frm);
- }
- },
- revision: function(frm) {
- if(!frm.doc.revised_on){
- frm.set_value("revised_on", frappe.datetime.get_today());
- }
- },
- measurable: function(frm) {
- frm.fields_dict.objective.grid.remove_all();
- if(frm.doc.measurable == "No"){
- hide_target_unit(frm);
- }
- else{
- show_target_unit(frm);
- }
+ refresh: function(frm) {
+ frm.doc.created_by = frappe.session.user;
}
});
-
-function hide_target_unit(frm){
- // hides target and unit columns as the goal cannot be measured in numeric values
- frm.fields_dict.objective.grid.docfields[1].hidden = 1;
- frm.fields_dict.objective.grid.docfields[2].hidden = 1;
- frm.refresh();
-}
-
-function show_target_unit(frm){
- // shows target and unit columns as the goal can be measured in numeric values
- frm.fields_dict.objective.grid.docfields[1].hidden = 0;
- frm.fields_dict.objective.grid.docfields[2].hidden = 0;
- frm.refresh();
-}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_goal/quality_goal.json b/erpnext/quality_management/doctype/quality_goal/quality_goal.json
index 93f1bd1..c326109 100644
--- a/erpnext/quality_management/doctype/quality_goal/quality_goal.json
+++ b/erpnext/quality_management/doctype/quality_goal/quality_goal.json
@@ -1,824 +1,149 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "format:{goal}",
- "beta": 0,
- "creation": "2018-10-02 12:17:41.727541",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "autoname": "format:GOAL-{goal}",
+ "creation": "2018-10-02 12:17:41.727541",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "goal",
+ "frequency",
+ "created_by",
+ "cb_00",
+ "procedure",
+ "weekday",
+ "quarter",
+ "date",
+ "sb_00",
+ "revision",
+ "cb_01",
+ "revised_on",
+ "sb_01",
+ "objectives"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "goal",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "fieldname": "created_by",
+ "fieldtype": "Link",
+ "label": "Created By",
+ "options": "User",
+ "read_only": 1
+ },
+ {
+ "default": "None",
+ "fieldname": "frequency",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Monitoring Frequency",
+ "options": "None\nDaily\nWeekly\nMonthly\nQuarterly"
+ },
+ {
+ "fieldname": "procedure",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Procedure",
+ "options": "Quality Procedure"
+ },
+ {
+ "depends_on": "eval:doc.frequency == 'Monthly' || doc.frequency == 'Quarterly';",
+ "fieldname": "date",
+ "fieldtype": "Select",
+ "label": "Date",
+ "options": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30"
+ },
+ {
+ "default": "0",
+ "fieldname": "revision",
+ "fieldtype": "Int",
+ "label": "Revision",
+ "read_only": 1
+ },
+ {
+ "fieldname": "revised_on",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Revised On",
+ "read_only": 1
+ },
+ {
+ "depends_on": "eval:doc.frequency == 'Weekly';",
+ "fieldname": "weekday",
+ "fieldtype": "Select",
+ "label": "Weekday",
+ "options": "Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday"
+ },
+ {
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break",
+ "label": "Revision and Revised On"
+ },
+ {
+ "fieldname": "cb_01",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "sb_01",
+ "fieldtype": "Section Break",
+ "label": "Objectives"
+ },
+ {
+ "fieldname": "objectives",
+ "fieldtype": "Table",
+ "label": "Objectives",
+ "options": "Quality Goal Objective"
+ },
+ {
+ "fieldname": "goal",
+ "fieldtype": "Data",
+ "label": "Goal",
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "created_by",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Created By",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "None",
- "fieldname": "frequency",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Monitoring Frequency",
- "length": 0,
- "no_copy": 0,
- "options": "None\nDaily\nWeekly\nMonthly\nQuarterly\nHalf Yearly\nYearly",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "January-April-July-October",
- "depends_on": "eval:doc.frequency == 'Quarterly'",
- "fieldname": "quarterly",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Day",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "January-July",
- "depends_on": "eval:doc.frequency == 'Half Yearly'",
- "fieldname": "half",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Day",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "January",
- "depends_on": "eval:doc.frequency == 'Yearly'",
- "fieldname": "yearly",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Day",
- "length": 0,
- "no_copy": 0,
- "options": "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Procedure",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Procedure",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "scope",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Scope",
- "length": 0,
- "no_copy": 0,
- "options": "Company\nDepartment",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.frequency == 'Daily'",
- "fieldname": "daily",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Day",
- "length": 0,
- "no_copy": 0,
- "options": "Everyday",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.frequency == 'Weekly'",
- "fieldname": "weekly",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Day",
- "length": 0,
- "no_copy": 0,
- "options": "Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.frequency == 'Quarterly' || doc.frequency == 'Half Yearly' || doc.frequency == 'Yearly' || doc.frequency == 'Monthly'",
- "fieldname": "date",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Date",
- "length": 0,
- "no_copy": 0,
- "options": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.scope == 'Department'",
- "fieldname": "department",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Department",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_8",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Revision and Revised On",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "revision",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Revision",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_10",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "revised_on",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Revised On",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "measurable_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Measurable Goal",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Yes",
- "fieldname": "measurable",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Measurable Goal",
- "length": 0,
- "no_copy": 0,
- "options": "Yes\nNo",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_20",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Target and Unit are disabled",
- "depends_on": "eval:doc.measurable == 'No'",
- "fieldname": "measurable_display",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Measurable",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_11",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Goal Objectives",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "objective",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Objective",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Objective",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "default": "January-April-July-October",
+ "depends_on": "eval:doc.frequency == 'Quarterly';",
+ "fieldname": "quarter",
+ "fieldtype": "Select",
+ "label": "Quarter",
+ "options": "January-April-July-October",
+ "read_only": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-12 14:35:18.498549",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Quality Goal",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2019-05-28 14:49:12.768863",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Goal",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "All",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_goal/quality_goal.py b/erpnext/quality_management/doctype/quality_goal/quality_goal.py
index 236c72a..4ae015e 100644
--- a/erpnext/quality_management/doctype/quality_goal/quality_goal.py
+++ b/erpnext/quality_management/doctype/quality_goal/quality_goal.py
@@ -3,8 +3,12 @@
# For license information, please see license.txt
from __future__ import unicode_literals
+import frappe
+
from frappe.model.document import Document
class QualityGoal(Document):
- pass
+ def validate(self):
+ self.revision += 1
+ self.revised_on = frappe.utils.today()
diff --git a/erpnext/quality_management/doctype/quality_goal/quality_goal_dashboard.py b/erpnext/quality_management/doctype/quality_goal/quality_goal_dashboard.py
index 0acc1da..22af3c0 100644
--- a/erpnext/quality_management/doctype/quality_goal/quality_goal_dashboard.py
+++ b/erpnext/quality_management/doctype/quality_goal/quality_goal_dashboard.py
@@ -1,16 +1,12 @@
from frappe import _
def get_data():
- return {
- 'fieldname': 'goal',
- 'transactions': [
- {
- 'label': _('Review'),
- 'items': ['Quality Review']
- },
- {
- 'label': _('Action'),
- 'items': ['Quality Action']
- }
- ]
- }
\ No newline at end of file
+ return {
+ 'fieldname': 'goal',
+ 'transactions': [
+ {
+ 'label': _('Review'),
+ 'items': ['Quality Review']
+ }
+ ]
+ }
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_goal/test_quality_goal.py b/erpnext/quality_management/doctype/quality_goal/test_quality_goal.py
index 19512d9..d77187a 100644
--- a/erpnext/quality_management/doctype/quality_goal/test_quality_goal.py
+++ b/erpnext/quality_management/doctype/quality_goal/test_quality_goal.py
@@ -14,33 +14,31 @@
create_unit()
test_create_goal = create_goal()
test_get_goal = get_goal()
+
self.assertEquals(test_create_goal, test_get_goal)
def create_goal():
goal = frappe.get_doc({
"doctype": "Quality Goal",
"goal": "_Test Quality Goal",
- "revision": "1",
- "procedure": "_Test Quality Procedure",
- "frequency": "Daily",
- "measureable": "Yes",
- "objective": [
+ "procedure": "PRC-_Test Quality Procedure",
+ "objectives": [
{
"objective": "_Test Quality Objective",
"target": "4",
- "unit": "_Test UOM"
+ "uom": "_Test UOM"
}
]
})
- goal_exist = frappe.db.exists("Quality Goal", ""+ goal.goal +"")
+ goal_exist = frappe.db.exists("Quality Goal", {"goal": goal.goal})
if not goal_exist:
goal.insert()
- return goal.goal
+ return goal.name
else:
return goal_exist
def get_goal():
- goal = frappe.db.exists("Quality Goal", "_Test Quality Goal")
+ goal = frappe.db.exists("Quality Goal", "GOAL-_Test Quality Goal")
return goal
def create_unit():
@@ -48,6 +46,6 @@
"doctype": "UOM",
"uom_name": "_Test UOM",
})
- unit_exist = frappe.db.exists("UOM", ""+ unit.uom_name +"")
+ unit_exist = frappe.db.exists("UOM", unit.uom_name)
if not unit_exist:
unit.insert()
diff --git a/erpnext/quality_management/doctype/quality_objective/__init__.py b/erpnext/quality_management/doctype/quality_goal_objective/__init__.py
similarity index 100%
rename from erpnext/quality_management/doctype/quality_objective/__init__.py
rename to erpnext/quality_management/doctype/quality_goal_objective/__init__.py
diff --git a/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.json b/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.json
new file mode 100644
index 0000000..e3dbd66
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.json
@@ -0,0 +1,51 @@
+{
+ "autoname": "format:{####}",
+ "creation": "2019-05-26 15:03:43.996455",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "objective",
+ "cb_00",
+ "target",
+ "uom"
+ ],
+ "fields": [
+ {
+ "fetch_from": "goal.objective",
+ "fieldname": "objective",
+ "fieldtype": "Text",
+ "in_list_view": 1,
+ "label": "Objective",
+ "reqd": 1
+ },
+ {
+ "fieldname": "target",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Target"
+ },
+ {
+ "fieldname": "uom",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "UOM",
+ "options": "UOM"
+ },
+ {
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-05-26 16:12:54.832058",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Goal Objective",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py b/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py
new file mode 100644
index 0000000..f4bd357
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class QualityGoalObjective(Document):
+ pass
diff --git a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json
index 45183c5..6985632 100644
--- a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json
+++ b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json
@@ -1,225 +1,93 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "format:QMS-MTN-{date}",
- "beta": 0,
- "creation": "2018-10-15 16:25:41.548432",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "autoname": "format:MTNG-{date}",
+ "creation": "2018-10-15 16:25:41.548432",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "date",
+ "cb_00",
+ "status",
+ "sb_00",
+ "agenda",
+ "sb_01",
+ "minutes"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Meeting Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Date",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "Open",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "label": "Status",
+ "options": "Open\nClose"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Open",
- "fieldname": "status",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "Open\nClose",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "minutes",
+ "fieldtype": "Table",
+ "label": "Minutes",
+ "options": "Quality Meeting Minutes"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "minutes_break",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Minutes",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "minutes",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Minutes",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Meeting Table",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break",
+ "label": "Agenda"
+ },
+ {
+ "fieldname": "agenda",
+ "fieldtype": "Table",
+ "label": "Agenda",
+ "options": "Quality Meeting Agenda"
+ },
+ {
+ "fieldname": "sb_01",
+ "fieldtype": "Section Break",
+ "label": "Minutes"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-10-18 14:44:04.494395",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Quality Meeting",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2019-05-26 23:12:23.364357",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Meeting",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "All",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py
index 88653a9..f8de229 100644
--- a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py
+++ b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py
@@ -6,13 +6,4 @@
from frappe.model.document import Document
class QualityMeeting(Document):
- def validate(self):
- problem = ''
- for data in self.minutes:
- if data.status == 'Open':
- problem = 'set'
-
- if problem == 'set':
- self.status = 'Open'
- else:
- self.status = 'Close'
\ No newline at end of file
+ pass
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_meeting/test_quality_meeting.py b/erpnext/quality_management/doctype/quality_meeting/test_quality_meeting.py
index b680a1b..e61b5df 100644
--- a/erpnext/quality_management/doctype/quality_meeting/test_quality_meeting.py
+++ b/erpnext/quality_management/doctype/quality_meeting/test_quality_meeting.py
@@ -5,27 +5,41 @@
import frappe
import unittest
+from erpnext.quality_management.doctype.quality_review.test_quality_review import create_review
class TestQualityMeeting(unittest.TestCase):
def test_quality_meeting(self):
+ create_review()
test_create_meeting = create_meeting()
test_get_meeting = get_meeting()
- self.assertEquals(test_create_meeting.name, test_get_meeting.name)
+ self.assertEquals(test_create_meeting, test_get_meeting)
def create_meeting():
meeting = frappe.get_doc({
"doctype": "Quality Meeting",
- "scope": "Company",
- "status": "Close",
- "date": ""+ frappe.as_unicode(frappe.utils.nowdate()) +""
+ "status": "Open",
+ "date": frappe.utils.nowdate(),
+ "agenda": [
+ {
+ "agenda": "Test Agenda"
+ }
+ ],
+ "minutes": [
+ {
+ "document_type": "Quality Review",
+ "document_name": frappe.db.exists("Quality Review", {"goal": "GOAL-_Test Quality Goal"}),
+ "minute": "Test Minute"
+ }
+ ]
})
- meeting_exist = frappe.get_list("Quality Meeting", filters={"date": ""+ meeting.date +""}, fields=["name"], limit=1)
- if len(meeting_exist) == 0:
+ meeting_exist = frappe.db.exists("Quality Meeting", {"date": frappe.utils.nowdate(), "status": "Open"})
+
+ if not meeting_exist:
meeting.insert()
- return meeting
+ return meeting.name
else:
- return meeting_exist[0]
+ return meeting_exist
def get_meeting():
- meeting = frappe.get_list("Quality Meeting", limit=1)
- return meeting[0]
\ No newline at end of file
+ meeting = frappe.db.exists("Quality Meeting", {"date": frappe.utils.nowdate(), "status": "Open"})
+ return meeting
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_meeting_table/__init__.py b/erpnext/quality_management/doctype/quality_meeting_agenda/__init__.py
similarity index 100%
rename from erpnext/quality_management/doctype/quality_meeting_table/__init__.py
rename to erpnext/quality_management/doctype/quality_meeting_agenda/__init__.py
diff --git a/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.js b/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.js
new file mode 100644
index 0000000..09989dc
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Quality Meeting Agenda', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.json b/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.json
new file mode 100644
index 0000000..e53d186
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.json
@@ -0,0 +1,28 @@
+{
+ "creation": "2019-05-26 20:46:57.999300",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "agenda"
+ ],
+ "fields": [
+ {
+ "fieldname": "agenda",
+ "fieldtype": "Text Editor",
+ "in_list_view": 1,
+ "label": "Agenda"
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-05-26 20:49:01.328146",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Meeting Agenda",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py b/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py
new file mode 100644
index 0000000..5d77975
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class QualityMeetingAgenda(Document):
+ pass
diff --git a/erpnext/quality_management/doctype/quality_meeting_agenda/test_quality_meeting_agenda.py b/erpnext/quality_management/doctype/quality_meeting_agenda/test_quality_meeting_agenda.py
new file mode 100644
index 0000000..4750cc1
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_meeting_agenda/test_quality_meeting_agenda.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestQualityMeetingAgenda(unittest.TestCase):
+ pass
diff --git a/erpnext/quality_management/doctype/quality_meeting_table/__init__.py b/erpnext/quality_management/doctype/quality_meeting_minutes/__init__.py
similarity index 100%
copy from erpnext/quality_management/doctype/quality_meeting_table/__init__.py
copy to erpnext/quality_management/doctype/quality_meeting_minutes/__init__.py
diff --git a/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.json b/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.json
new file mode 100644
index 0000000..3b9133a
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.json
@@ -0,0 +1,55 @@
+{
+ "creation": "2019-05-26 20:45:26.226428",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "document_type",
+ "cb_00",
+ "document_name",
+ "sb_00",
+ "minute"
+ ],
+ "fields": [
+ {
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "minute",
+ "fieldtype": "Text Editor",
+ "in_list_view": 1,
+ "label": "Minute"
+ },
+ {
+ "fieldname": "document_type",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Document Type",
+ "options": "Quality Review\nQuality Action\nQuality Feedback",
+ "reqd": 1
+ },
+ {
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "document_name",
+ "fieldtype": "Dynamic Link",
+ "in_list_view": 1,
+ "label": "Document Name",
+ "options": "document_type"
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-05-26 22:00:24.833920",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Meeting Minutes",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py b/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py
new file mode 100644
index 0000000..47b2c95
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class QualityMeetingMinutes(Document):
+ pass
diff --git a/erpnext/quality_management/doctype/quality_meeting_table/quality_meeting_table.json b/erpnext/quality_management/doctype/quality_meeting_table/quality_meeting_table.json
deleted file mode 100644
index 8e34a62..0000000
--- a/erpnext/quality_management/doctype/quality_meeting_table/quality_meeting_table.json
+++ /dev/null
@@ -1,175 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-10-15 16:28:59.840039",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "review",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Review",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Review",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "action",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Action",
- "length": 0,
- "no_copy": 0,
- "options": "Under Review\nPlanned",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "responsible",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Responsible",
- "length": 0,
- "no_copy": 0,
- "options": "Role",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "status",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "Open\nClose",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-01 14:34:53.964306",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Quality Meeting Table",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_meeting_table/quality_meeting_table.py b/erpnext/quality_management/doctype/quality_meeting_table/quality_meeting_table.py
deleted file mode 100644
index 2e39c24..0000000
--- a/erpnext/quality_management/doctype/quality_meeting_table/quality_meeting_table.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class QualityMeetingTable(Document):
- pass
diff --git a/erpnext/quality_management/doctype/quality_objective/quality_objective.json b/erpnext/quality_management/doctype/quality_objective/quality_objective.json
deleted file mode 100644
index 49ffde9..0000000
--- a/erpnext/quality_management/doctype/quality_objective/quality_objective.json
+++ /dev/null
@@ -1,144 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "format:{####}",
- "beta": 0,
- "creation": "2018-10-02 16:47:59.600155",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "goal.objective",
- "fieldname": "objective",
- "fieldtype": "Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Objective",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "target",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Target",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "unit",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Unit",
- "length": 0,
- "no_copy": 0,
- "options": "UOM",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-11 13:31:16.044780",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Quality Objective",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_objective/quality_objective.py b/erpnext/quality_management/doctype/quality_objective/quality_objective.py
deleted file mode 100644
index 9e6a8fd..0000000
--- a/erpnext/quality_management/doctype/quality_objective/quality_objective.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class QualityObjective(Document):
- pass
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json
index 8733c7c..7b241ef 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json
@@ -1,386 +1,106 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "format:{procedure}",
- "beta": 0,
- "creation": "2018-10-06 00:06:29.756804",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "autoname": "format:PRC-{procedure}",
+ "creation": "2018-10-06 00:06:29.756804",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "procedure",
+ "parent_quality_procedure",
+ "is_group",
+ "sb_00",
+ "processes",
+ "lft",
+ "rgt",
+ "old_parent"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Procedure",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "parent_quality_procedure",
+ "fieldtype": "Link",
+ "label": "Parent Procedure",
+ "options": "Quality Procedure",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "parent_quality_procedure",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Parent Procedure",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Procedure",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "is_group",
+ "fieldtype": "Check",
+ "label": "Is Group",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "is_group",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Is Group",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "lft",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "label": "Lft",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "rgt",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "label": "Rgt",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "department",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Department",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "old_parent",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "old_parent",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure_steps_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Procedure Steps",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break",
+ "label": "Processes"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure_step",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Procedure",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Procedure Table",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "processes",
+ "fieldtype": "Table",
+ "label": "Processes",
+ "options": "Quality Procedure Process"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lft",
- "fieldtype": "Int",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Lft",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "rgt",
- "fieldtype": "Int",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Rgt",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "old_parent",
- "fieldtype": "Data",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "old_parent",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "procedure",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Procedure",
+ "reqd": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-12 14:30:19.803693",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Quality Procedure",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2019-05-26 22:11:53.771428",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Procedure",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "All",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
index 126b8c7..52c3320 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
@@ -11,12 +11,11 @@
nsm_parent_field = 'parent_quality_procedure'
def before_save(self):
- for data in self.procedure_step:
- if data.procedure == 'Procedure' and data.procedure_name:
- data.step = data.procedure_name
- doc = frappe.get_doc("Quality Procedure", data.procedure_name)
- if(doc.parent_quality_procedure):
- frappe.throw(_("'"+ data.procedure_name +"' already has a Parent Procedure '"+ doc.parent_quality_procedure +"'"))
+ for process in self.processes:
+ if process.procedure:
+ doc = frappe.get_doc("Quality Procedure", process.procedure)
+ if doc.parent_quality_procedure:
+ frappe.throw(_("{0} already has a Parent Procedure {1}.".format(process.procedure, doc.parent_quality_procedure)))
self.is_group = 1
def on_update(self):
@@ -28,25 +27,28 @@
def on_trash(self):
if self.parent_quality_procedure:
doc = frappe.get_doc("Quality Procedure", self.parent_quality_procedure)
- for data in doc.procedure_step:
- if data.procedure_name == self.name:
- doc.procedure_step.remove(data)
- doc.save()
+ for process in doc.processes:
+ if process.procedure == self.name:
+ doc.processes.remove(process)
+ doc.save(ignore_permissions=True)
+
flag_is_group = 0
doc.load_from_db()
- for data in doc.procedure_step:
- if data.procedure == "Procedure":
+
+ for process in doc.processes:
+ if process.procedure:
flag_is_group = 1
+
if flag_is_group == 0:
doc.is_group = 0
- doc.save()
+ doc.save(ignore_permissions=True)
def set_parent(self):
- for data in self.procedure_step:
- if data.procedure == 'Procedure' and data.procedure_name:
- doc = frappe.get_doc("Quality Procedure", data.procedure_name)
+ for process in self.processes:
+ if process.procedure:
+ doc = frappe.get_doc("Quality Procedure", process.procedure)
doc.parent_quality_procedure = self.name
- doc.save()
+ doc.save(ignore_permissions=True)
@frappe.whitelist()
def get_children(doctype, parent=None, parent_quality_procedure=None, is_root=False):
@@ -57,8 +59,11 @@
@frappe.whitelist()
def add_node():
from frappe.desk.treeview import make_tree_args
+
args = frappe.form_dict
args = make_tree_args(**args)
+
if args.parent_quality_procedure == 'All Quality Procedures':
args.parent_quality_procedure = None
+
frappe.get_doc(args).insert()
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure_dashboard.py b/erpnext/quality_management/doctype/quality_procedure/quality_procedure_dashboard.py
index 8eff33c..407028b 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure_dashboard.py
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure_dashboard.py
@@ -1,20 +1,20 @@
from frappe import _
def get_data():
- return {
- 'fieldname': 'procedure',
- 'transactions': [
- {
- 'label': _('Goal'),
- 'items': ['Quality Goal']
- },
- {
- 'label': _('Review'),
- 'items': ['Quality Review']
- },
- {
- 'label': _('Action'),
- 'items': ['Quality Action']
- }
- ],
- }
\ No newline at end of file
+ return {
+ 'fieldname': 'procedure',
+ 'transactions': [
+ {
+ 'label': _('Goal'),
+ 'items': ['Quality Goal']
+ },
+ {
+ 'label': _('Review'),
+ 'items': ['Quality Review']
+ },
+ {
+ 'label': _('Action'),
+ 'items': ['Quality Action']
+ }
+ ],
+ }
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py
index af7adec..79f8771 100644
--- a/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py
+++ b/erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py
@@ -11,25 +11,26 @@
test_create_procedure = create_procedure()
test_create_nested_procedure = create_nested_procedure()
test_get_procedure, test_get_nested_procedure = get_procedure()
- self.assertEquals(test_create_procedure, test_get_procedure.name)
- self.assertEquals(test_create_nested_procedure, test_get_nested_procedure.name)
- self.assertEquals(test_get_nested_procedure.name, test_get_procedure.parent_quality_procedure)
+
+ self.assertEquals(test_create_procedure, test_get_procedure.get("name"))
+ self.assertEquals(test_create_nested_procedure, test_get_nested_procedure.get("name"))
def create_procedure():
procedure = frappe.get_doc({
"doctype": "Quality Procedure",
"procedure": "_Test Quality Procedure",
- "procedure_step": [
+ "processes": [
{
- "procedure": "Step",
- "step": "_Test Quality Procedure Table",
+ "process_description": "_Test Quality Procedure Table",
}
]
})
- procedure_exist = frappe.db.exists("Quality Procedure",""+ procedure.procedure +"")
+
+ procedure_exist = frappe.db.exists("Quality Procedure", "PRC-_Test Quality Procedure")
+
if not procedure_exist:
procedure.insert()
- return procedure.procedure
+ return procedure.name
else:
return procedure_exist
@@ -37,21 +38,22 @@
nested_procedure = frappe.get_doc({
"doctype": "Quality Procedure",
"procedure": "_Test Nested Quality Procedure",
- "procedure_step": [
+ "processes": [
{
- "procedure": "Procedure",
- "procedure_name": "_Test Quality Procedure",
+ "procedure": "PRC-_Test Quality Procedure"
}
]
})
- nested_procedure_exist = frappe.db.exists("Quality Procedure",""+ nested_procedure.procedure +"")
+
+ nested_procedure_exist = frappe.db.exists("Quality Procedure", "PRC-_Test Nested Quality Procedure")
+
if not nested_procedure_exist:
nested_procedure.insert()
- return nested_procedure.procedure
+ return nested_procedure.name
else:
return nested_procedure_exist
def get_procedure():
- procedure = frappe.get_all("Quality Procedure", filters={"procedure": "_Test Quality Procedure"}, fields=["name", "parent_quality_procedure"], limit=1)
- nested_procedure = frappe.get_all("Quality Procedure", filters={"procedure": "_Test Nested Quality Procedure"}, fields=["name", "parent_quality_procedure"], limit=1)
- return procedure[0], nested_procedure[0]
\ No newline at end of file
+ procedure = frappe.get_doc("Quality Procedure", "PRC-_Test Quality Procedure")
+ nested_procedure = frappe.get_doc("Quality Procedure", "PRC-_Test Nested Quality Procedure")
+ return {"name": procedure.name}, {"name": nested_procedure.name, "parent_quality_procedure": nested_procedure.parent_quality_procedure}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_procedure_table/__init__.py b/erpnext/quality_management/doctype/quality_procedure_process/__init__.py
similarity index 100%
rename from erpnext/quality_management/doctype/quality_procedure_table/__init__.py
rename to erpnext/quality_management/doctype/quality_procedure_process/__init__.py
diff --git a/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.json b/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.json
new file mode 100644
index 0000000..f5c0fbc
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.json
@@ -0,0 +1,36 @@
+{
+ "creation": "2019-05-26 00:10:00.248885",
+ "doctype": "DocType",
+ "engine": "InnoDB",
+ "field_order": [
+ "process_description",
+ "procedure"
+ ],
+ "fields": [
+ {
+ "fieldname": "process_description",
+ "fieldtype": "Text Editor",
+ "in_list_view": 1,
+ "label": "Process Description"
+ },
+ {
+ "description": "Link existing Quality Procedure.",
+ "fieldname": "procedure",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Procedure",
+ "options": "Quality Procedure"
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-05-26 22:05:49.007189",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Procedure Process",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py b/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py
new file mode 100644
index 0000000..0d9a286
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class QualityProcedureProcess(Document):
+ pass
diff --git a/erpnext/quality_management/doctype/quality_procedure_table/quality_procedure_table.json b/erpnext/quality_management/doctype/quality_procedure_table/quality_procedure_table.json
deleted file mode 100644
index 965edbc..0000000
--- a/erpnext/quality_management/doctype/quality_procedure_table/quality_procedure_table.json
+++ /dev/null
@@ -1,176 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-10-17 15:48:57.617831",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 0,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Procedure",
- "length": 0,
- "no_copy": 0,
- "options": "Step\nProcedure",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.procedure == \"Procedure\"",
- "fieldname": "procedure_name",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Procedure",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Procedure",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.procedure == \"Step\"",
- "fieldname": "step",
- "fieldtype": "Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Step",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "responsible_individual",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Responsible Individual",
- "length": 0,
- "no_copy": 0,
- "options": "Role",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-01 14:26:33.558345",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Quality Procedure Table",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_procedure_table/quality_procedure_table.py b/erpnext/quality_management/doctype/quality_procedure_table/quality_procedure_table.py
deleted file mode 100644
index 6fe927a..0000000
--- a/erpnext/quality_management/doctype/quality_procedure_table/quality_procedure_table.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class QualityProcedureTable(Document):
- pass
diff --git a/erpnext/quality_management/doctype/quality_review/quality_review.js b/erpnext/quality_management/doctype/quality_review/quality_review.js
index 48b5c88..b624581 100644
--- a/erpnext/quality_management/doctype/quality_review/quality_review.js
+++ b/erpnext/quality_management/doctype/quality_review/quality_review.js
@@ -4,69 +4,25 @@
frappe.ui.form.on('Quality Review', {
onload: function(frm){
frm.set_value("date", frappe.datetime.get_today());
- $(".grid-add-row").hide();
- if(frm.doc.measurable == "Yes"){
- show_target_achieved_unit(frm);
- }
- else{
- hide_target_achieved_unit(frm);
- }
- frm.refresh();
},
goal: function(frm) {
- frm.fields_dict.values.grid.remove_all();
- if (frm.doc.goal){
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Quality Goal",
- name: frm.doc.goal
- },
- callback: function (data) {
- for (var i = 0; i < data.message.objective.length; i++ ){
- frm.add_child("values");
- frm.fields_dict.values.get_value()[i].objective = data.message.objective[i].objective;
- if(frm.doc.measurable == "Yes"){
- if(i < 1){
- show_target_achieved_unit(frm);
- }
- frm.fields_dict.values.get_value()[i].target = data.message.objective[i].target;
- frm.fields_dict.values.get_value()[i].achieved = 0;
- frm.fields_dict.values.get_value()[i].unit = data.message.objective[i].unit;
- }
- if(frm.doc.measurable == "No"){
- if(i < 1){
- hide_target_achieved_unit(frm);
- }
- frm.fields_dict.values.get_value()[i].yes_no = "No";
- }
- }
- frm.refresh();
+ frappe.call({
+ "method": "frappe.client.get",
+ args: {
+ doctype: "Quality Goal",
+ name: frm.doc.goal
+ },
+ callback: function(data){
+ frm.fields_dict.reviews.grid.remove_all();
+ let objectives = data.message.objectives;
+ for (var i in objectives) {
+ frm.add_child("reviews");
+ frm.fields_dict.reviews.get_value()[i].objective = objectives[i].objective;
+ frm.fields_dict.reviews.get_value()[i].target = objectives[i].target;
+ frm.fields_dict.reviews.get_value()[i].uom = objectives[i].uom;
}
- });
- }
- else{
- frm.doc.procedure = '';
- frm.doc.scope = '';
- frm.doc.action = '';
- frm.doc.measurable = '';
- frm.refresh();
- }
+ frm.refresh();
+ }
+ });
},
-});
-
-function show_target_achieved_unit(frm){
- // shows target, achieved and unit columns as the goal can be measured in numeric values
- frm.fields_dict.values.grid.docfields[1].hidden = 0;
- frm.fields_dict.values.grid.docfields[2].hidden = 0;
- frm.fields_dict.values.grid.docfields[3].hidden = 0;
- frm.fields_dict.values.grid.docfields[4].hidden = 1;
-}
-
-function hide_target_achieved_unit(frm){
- // hides target and unit columns as the goal cannot be measured in numeric values
- frm.fields_dict.values.grid.docfields[1].hidden = 1;
- frm.fields_dict.values.grid.docfields[2].hidden = 1;
- frm.fields_dict.values.grid.docfields[3].hidden = 1;
- frm.fields_dict.values.grid.docfields[4].hidden = 0;
-}
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_review/quality_review.json b/erpnext/quality_management/doctype/quality_review/quality_review.json
index 689c1c5..bd5e935 100644
--- a/erpnext/quality_management/doctype/quality_review/quality_review.json
+++ b/erpnext/quality_management/doctype/quality_review/quality_review.json
@@ -1,424 +1,110 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "QMS-REV-.#####",
- "beta": 0,
- "creation": "2018-10-02 11:45:16.301955",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "autoname": "format:REV-{#####}",
+ "creation": "2018-10-02 11:45:16.301955",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "goal",
+ "date",
+ "cb_00",
+ "procedure",
+ "status",
+ "sb_00",
+ "reviews",
+ "sb_01",
+ "additional_information"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "",
- "fieldname": "goal",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Quality Goal",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Goal",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Date",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Evaluation Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "goal.procedure",
+ "fieldname": "procedure",
+ "fieldtype": "Link",
+ "label": "Procedure",
+ "options": "Quality Procedure",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "goal.measurable",
- "fieldname": "measurable",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Measurable Goal",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "additional_information",
+ "fieldtype": "Text",
+ "label": "Additional Information"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_4",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "goal.procedure",
- "fieldname": "procedure",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Procedure",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Procedure",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break",
+ "label": "Review"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "goal.scope",
- "fieldname": "scope",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Scope",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "collapsible": 1,
+ "fieldname": "sb_01",
+ "fieldtype": "Section Break",
+ "label": "Additional Information"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.scope == 'Department'",
- "fetch_from": "goal.department",
- "fieldname": "department",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Department",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "reviews",
+ "fieldtype": "Table",
+ "label": "Reviews",
+ "options": "Quality Review Objective"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "values_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Values",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "Open",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "label": "Status",
+ "options": "Open\nClosed"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "values",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Values",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Review Table",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "additional_info_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Additional Information",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "additional_information",
- "fieldtype": "Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Additional Information",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "goal",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Goal",
+ "options": "Quality Goal",
+ "reqd": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-12 14:25:02.383387",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Quality Review",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2019-05-26 23:12:47.302189",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Review",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "All",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_review/quality_review.py b/erpnext/quality_management/doctype/quality_review/quality_review.py
index 8a28335..2bc8867 100644
--- a/erpnext/quality_management/doctype/quality_review/quality_review.py
+++ b/erpnext/quality_management/doctype/quality_review/quality_review.py
@@ -5,63 +5,50 @@
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
-import datetime
+
class QualityReview(Document):
pass
def review():
- now = datetime.datetime.now()
- day = now.day
- day_name = now.strftime("%A")
- month=now.strftime("%B")
+ day = frappe.utils.getdate().day
+ weekday = frappe.utils.getdate().strftime("%A")
+ month = frappe.utils.getdate().strftime("%B")
- for data in frappe.get_all("Quality Goal",fields=['name', 'frequency', 'date', 'weekly', 'measurable']):
- if data.frequency == 'Daily':
- create_review(data.name, data.measurable)
+ for goal in frappe.get_list("Quality Goal", fields=['name', 'frequency', 'date', 'weekday']):
+ if goal.frequency == 'Daily':
+ create_review(goal.name)
- elif data.frequency == 'Weekly':
- if data.weekly == day_name:
- create_review(data.name, data.measurable)
+ elif goal.frequency == 'Weekly' and goal.weekday == weekday:
+ create_review(goal.name)
- elif data.frequency == 'Monthly':
- if data.date == str(day):
- create_review(data.name, data.measurable)
+ elif goal.frequency == 'Monthly' and goal.date == str(day):
+ create_review(goal.name)
- elif data.frequency == 'Quarterly':
- if (month == 'January' or month == 'April' or month == 'July' or month == 'October') and str(day) == data.date:
- create_review(data.name, data.measurable)
+ elif goal.frequency == 'Quarterly' and goal.data == str(day) and get_quarter(month):
+ create_review(goal.name)
- elif data.frequency == 'Half Yearly':
- if (month == 'January' or month == 'July') and str(day) == data.date:
- create_review(data.name, data.measurable)
+def create_review(goal):
+ goal = frappe.get_doc("Quality Goal", goal)
- elif data.frequency == 'Yearly':
- if month == data.yearly and str(day) == data.date:
- create_review(data.name, data.measurable)
-
- else:
- pass
-
-def create_review(name, measurable):
- objectives = frappe.get_all("Quality Objective", filters={'parent': name }, fields=['objective', 'target', 'unit'])
- doc = frappe.get_doc({
+ review = frappe.get_doc({
"doctype": "Quality Review",
- "goal": name,
- "date": frappe.as_unicode(frappe.utils.nowdate()),
- "measurable": measurable,
+ "goal": goal.name,
+ "date": frappe.utils.getdate()
})
- if measurable == 'Yes':
- for objective in objectives:
- doc.append("values",{
- 'objective': objective.objective,
- 'target': objective.target,
- 'achieved': 0,
- 'unit': objective.unit
- })
+
+ for objective in goal.objectives:
+ review.append("reviews",
+ {
+ "objective": objective.objective,
+ "target": objective.target,
+ "uom": objective.uom
+ }
+ )
+
+ review.insert(ignore_permissions=True)
+
+def get_quarter(month):
+ if month in ["January", "April", "July", "October"]:
+ return True
else:
- for objective in objectives:
- doc.append("values",{
- 'objective': objective.objective,
- })
- doc.insert()
- frappe.db.commit()
\ No newline at end of file
+ return False
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_review/quality_review_dashboard.py b/erpnext/quality_management/doctype/quality_review/quality_review_dashboard.py
deleted file mode 100644
index 85e4ccc..0000000
--- a/erpnext/quality_management/doctype/quality_review/quality_review_dashboard.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from frappe import _
-
-def get_data():
- return {
- 'fieldname': 'review',
- 'transactions': [
- {
- 'label': _('Action'),
- 'items': ['Quality Action']
- },
- {
- 'label': _('Meeting'),
- 'items': ['Quality Meeting']
- }
- ],
- }
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_review/test_quality_review.py b/erpnext/quality_management/doctype/quality_review/test_quality_review.py
index 421d20d..8add6db 100644
--- a/erpnext/quality_management/doctype/quality_review/test_quality_review.py
+++ b/erpnext/quality_management/doctype/quality_review/test_quality_review.py
@@ -17,31 +17,30 @@
create_goal()
test_create_review = create_review()
test_get_review = get_review()
- self.assertEquals(test_create_review.name, test_get_review.name)
+ self.assertEquals(test_create_review, test_get_review)
def create_review():
review = frappe.get_doc({
"doctype": "Quality Review",
- "goal": "_Test Quality Goal",
- "procedure": "_Test Quality Procedure",
- "scope": "Company",
- "date": ""+ frappe.utils.nowdate() +"",
- "values": [
+ "goal": "GOAL-_Test Quality Goal",
+ "procedure": "PRC-_Test Quality Procedure",
+ "date": frappe.utils.nowdate(),
+ "reviews": [
{
"objective": "_Test Quality Objective",
"target": "100",
- "achieved": "100",
- "unit": "_Test UOM"
+ "uom": "_Test UOM",
+ "review": "Test Review"
}
]
})
- review_exist = frappe.get_list("Quality Review", filters={"goal": "_Test Quality Goal"}, limit=1)
- if len(review_exist) == 0:
- review.insert()
- return review
+ review_exist = frappe.db.exists("Quality Review", {"goal": "GOAL-_Test Quality Goal"})
+ if not review_exist:
+ review.insert(ignore_permissions=True)
+ return review.name
else:
- return review_exist[0]
+ return review_exist
def get_review():
- review = frappe.get_list("Quality Review", filters={"goal": "_Test Quality Goal"}, limit=1)
- return review[0]
\ No newline at end of file
+ review = frappe.db.exists("Quality Review", {"goal": "GOAL-_Test Quality Goal"})
+ return review
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_objective/__init__.py b/erpnext/quality_management/doctype/quality_review_objective/__init__.py
similarity index 100%
copy from erpnext/quality_management/doctype/quality_objective/__init__.py
copy to erpnext/quality_management/doctype/quality_review_objective/__init__.py
diff --git a/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.json b/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.json
new file mode 100644
index 0000000..91f7bc0
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.json
@@ -0,0 +1,64 @@
+{
+ "creation": "2019-05-26 15:17:44.796958",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "objective",
+ "cb_00",
+ "target",
+ "uom",
+ "sb_00",
+ "review"
+ ],
+ "fields": [
+ {
+ "fieldname": "objective",
+ "fieldtype": "Text",
+ "in_list_view": 1,
+ "label": "Objective",
+ "read_only": 1
+ },
+ {
+ "fieldname": "target",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Target",
+ "read_only": 1
+ },
+ {
+ "fetch_from": "target_unit",
+ "fieldname": "uom",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "UOM",
+ "options": "UOM",
+ "read_only": 1
+ },
+ {
+ "fieldname": "review",
+ "fieldtype": "Text Editor",
+ "in_list_view": 1,
+ "label": "Review"
+ },
+ {
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break",
+ "label": "Review"
+ },
+ {
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-05-26 16:14:12.586128",
+ "modified_by": "Administrator",
+ "module": "Quality Management",
+ "name": "Quality Review Objective",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py b/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py
new file mode 100644
index 0000000..3092a1e
--- /dev/null
+++ b/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class QualityReviewObjective(Document):
+ pass
diff --git a/erpnext/quality_management/doctype/quality_review_table/__init__.py b/erpnext/quality_management/doctype/quality_review_table/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/quality_management/doctype/quality_review_table/__init__.py
+++ /dev/null
diff --git a/erpnext/quality_management/doctype/quality_review_table/quality_review_table.json b/erpnext/quality_management/doctype/quality_review_table/quality_review_table.json
deleted file mode 100644
index 442c4c6..0000000
--- a/erpnext/quality_management/doctype/quality_review_table/quality_review_table.json
+++ /dev/null
@@ -1,207 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-10-09 13:03:37.666929",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "objective",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "objective",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "target",
- "fieldtype": "Int",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Target",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "achieved",
- "fieldtype": "Int",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Achieved",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "target_unit",
- "fieldname": "unit",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Unit",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "yes_no",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Yes/No",
- "length": 0,
- "no_copy": 0,
- "options": "No\nYes",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-03 11:10:53.818818",
- "modified_by": "Administrator",
- "module": "Quality Management",
- "name": "Quality Review Table",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_review_table/quality_review_table.py b/erpnext/quality_management/doctype/quality_review_table/quality_review_table.py
deleted file mode 100644
index 5760cbc..0000000
--- a/erpnext/quality_management/doctype/quality_review_table/quality_review_table.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class QualityReviewTable(Document):
- pass
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index fc2fc96..8893cab 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -261,3 +261,19 @@
exemptions["monthly_house_rent"] = monthly_rent
exemptions["total_eligible_hra_exemption"] = eligible_hra
return exemptions
+
+@frappe.whitelist()
+def get_gstins_for_company(company):
+ company_gstins =[]
+ if company:
+ company_gstins = frappe.db.sql("""select
+ distinct `tabAddress`.gstin
+ from
+ `tabAddress`, `tabDynamic Link`
+ where
+ `tabDynamic Link`.parent = `tabAddress`.name and
+ `tabDynamic Link`.parenttype = 'Address' and
+ `tabDynamic Link`.link_doctype = 'Company' and
+ `tabDynamic Link`.link_name = '{0}'""".format(company))
+ return company_gstins
+
diff --git a/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.js b/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.js
index 1ece14b..3a0f0c9 100644
--- a/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.js
+++ b/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.js
@@ -3,5 +3,31 @@
/* eslint-disable */
{% include "erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js" %}
+{% include "erpnext/regional/report/india_gst_common/india_gst_common.js" %}
-frappe.query_reports["GST Itemised Sales Register"] = frappe.query_reports["Item-wise Sales Register"]
\ No newline at end of file
+let filters = frappe.query_reports["Item-wise Sales Register"]["filters"];
+
+// Add GSTIN filter
+filters = filters.concat({
+ "fieldname":"company_gstin",
+ "label": __("Company GSTIN"),
+ "fieldtype": "Select",
+ "placeholder":"Company GSTIN",
+ "options": [""],
+ "width": "80"
+}, {
+ "fieldname":"invoice_type",
+ "label": __("Invoice Type"),
+ "fieldtype": "Select",
+ "placeholder":"Invoice Type",
+ "options": ["", "Regular", "SEZ", "Export", "Deemed Export"]
+});
+
+// Handle company on change
+for (var i = 0; i < filters.length; ++i) {
+ if (filters[i].fieldname === 'company') {
+ filters[i].on_change = fetch_gstins;
+ }
+}
+
+frappe.query_reports["GST Itemised Sales Register"] = { "filters": filters, "onload": fetch_gstins };
diff --git a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js
index df0ef25..dcb81cb 100644
--- a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js
+++ b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js
@@ -2,6 +2,8 @@
// For license information, please see license.txt
/* eslint-disable */
+{% include "erpnext/regional/report/india_gst_common/india_gst_common.js" %}
+
frappe.query_reports["HSN-wise-summary of outward supplies"] = {
"filters": [
{
@@ -10,7 +12,8 @@
"fieldtype": "Link",
"options": "Company",
"reqd": 1,
- "default": frappe.defaults.get_user_default("Company")
+ "default": frappe.defaults.get_user_default("Company"),
+ "on_change": fetch_gstins
},
{
"fieldname":"gst_hsn_code",
@@ -18,6 +21,17 @@
"fieldtype": "Link",
"options": "GST HSN Code",
"width": "80"
+ },
+ {
+ "fieldname":"company_gstin",
+ "label": __("Company GSTIN"),
+ "fieldtype": "Select",
+ "placeholder":"Company GSTIN",
+ "options": [""],
+ "width": "80"
}
- ]
-}
+ ],
+ onload: (report) => {
+ fetch_gstins(report);
+ }
+};
diff --git a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py
index 165458c..e938e29 100644
--- a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py
+++ b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py
@@ -87,7 +87,8 @@
conditions = ""
for opts in (("company", " and company=%(company)s"),
- ("gst_hsn_code", " and gst_hsn_code=%(gst_hsn_code)s")):
+ ("gst_hsn_code", " and gst_hsn_code=%(gst_hsn_code)s"),
+ ("company_gstin", " and company_gstin=%(company_gstin)s")):
if filters.get(opts[0]):
conditions += opts[1]
@@ -193,7 +194,7 @@
add_column_index.append(i)
for row in data:
- if merged_hsn_dict.has_key(row[0]):
+ if row[0] in merged_hsn_dict:
to_add_row = merged_hsn_dict.get(row[0])
# add columns from the add_column_index table
diff --git a/erpnext/regional/report/india_gst_common/india_gst_common.js b/erpnext/regional/report/india_gst_common/india_gst_common.js
new file mode 100644
index 0000000..4960601
--- /dev/null
+++ b/erpnext/regional/report/india_gst_common/india_gst_common.js
@@ -0,0 +1,21 @@
+function fetch_gstins(report) {
+ var company_gstins = report.get_filter('company_gstin');
+ var company = report.get_filter_value('company');
+ if (company) {
+ frappe.call({
+ method:'erpnext.regional.india.utils.get_gstins_for_company',
+ async: false,
+ args: {
+ company: company
+ },
+ callback: function(r) {
+ r.message.unshift("");
+ company_gstins.df.options = r.message;
+ company_gstins.refresh();
+ }
+ });
+ } else {
+ company_gstins.df.options = [""];
+ company_gstins.refresh();
+ }
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 5a287b1..fc715c9 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -76,9 +76,8 @@
"is_customer_provided_item",
"customer",
"supplier_details",
+ "manufacturers",
"delivered_by_supplier",
- "manufacturer",
- "manufacturer_part_no",
"column_break2",
"supplier_items",
"foreign_trade_details",
@@ -198,6 +197,7 @@
"search_index": 1
},
{
+ "default": "0",
"fieldname": "is_item_from_hub",
"fieldtype": "Check",
"label": "Is Item from Hub",
@@ -218,11 +218,13 @@
"fieldtype": "Column Break"
},
{
+ "default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disabled"
},
{
+ "default": "0",
"fieldname": "allow_alternative_item",
"fieldtype": "Check",
"label": "Allow Alternative Item"
@@ -263,6 +265,7 @@
"label": "Standard Selling Rate"
},
{
+ "default": "0",
"fieldname": "is_fixed_asset",
"fieldtype": "Check",
"label": "Is Fixed Asset",
@@ -439,6 +442,7 @@
"label": "Serial Nos and Batches"
},
{
+ "default": "0",
"depends_on": "eval:doc.is_stock_item",
"fieldname": "has_batch_no",
"fieldtype": "Check",
@@ -448,6 +452,7 @@
"oldfieldtype": "Select"
},
{
+ "default": "0",
"depends_on": "has_batch_no",
"fieldname": "create_new_batch",
"fieldtype": "Check",
@@ -462,12 +467,14 @@
"translatable": 1
},
{
+ "default": "0",
"depends_on": "has_batch_no",
"fieldname": "has_expiry_date",
"fieldtype": "Check",
"label": "Has Expiry Date"
},
{
+ "default": "0",
"depends_on": "has_batch_no",
"fieldname": "retain_sample",
"fieldtype": "Check",
@@ -485,6 +492,7 @@
"fieldtype": "Column Break"
},
{
+ "default": "0",
"depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset",
"fieldname": "has_serial_no",
"fieldtype": "Check",
@@ -601,6 +609,7 @@
"read_only": 1
},
{
+ "default": "0",
"fieldname": "is_customer_provided_item",
"fieldtype": "Check",
"label": "Is Customer Provided Item"
@@ -619,26 +628,15 @@
"label": "Supplier Details"
},
{
+ "default": "0",
"fieldname": "delivered_by_supplier",
"fieldtype": "Check",
"label": "Delivered by Supplier (Drop Ship)",
"print_hide": 1
},
{
- "fieldname": "manufacturer",
- "fieldtype": "Link",
- "label": "Manufacturer",
- "options": "Manufacturer"
- },
- {
- "fieldname": "manufacturer_part_no",
- "fieldtype": "Data",
- "label": "Manufacturer Part Number"
- },
- {
"fieldname": "column_break2",
"fieldtype": "Column Break",
- "label": "Item Code for Suppliers",
"oldfieldtype": "Column Break",
"width": "50%"
},
@@ -718,6 +716,7 @@
"options": "Account"
},
{
+ "default": "0",
"fieldname": "enable_deferred_revenue",
"fieldtype": "Check",
"label": "Enable Deferred Revenue"
@@ -747,6 +746,7 @@
"options": "Account"
},
{
+ "default": "0",
"fieldname": "enable_deferred_expense",
"fieldtype": "Check",
"label": "Enable Deferred Expense"
@@ -800,6 +800,7 @@
"options": "fa fa-search"
},
{
+ "default": "0",
"fieldname": "inspection_required_before_purchase",
"fieldtype": "Check",
"label": "Inspection Required before Purchase",
@@ -807,6 +808,7 @@
"oldfieldtype": "Select"
},
{
+ "default": "0",
"fieldname": "inspection_required_before_delivery",
"fieldtype": "Check",
"label": "Inspection Required before Delivery"
@@ -840,6 +842,7 @@
"read_only": 1
},
{
+ "default": "0",
"description": "If subcontracted to a vendor",
"fieldname": "is_sub_contracted_item",
"fieldtype": "Check",
@@ -867,6 +870,7 @@
"options": "fa fa-globe"
},
{
+ "default": "0",
"depends_on": "eval:!doc.variant_of",
"fieldname": "show_in_website",
"fieldtype": "Check",
@@ -874,6 +878,7 @@
"search_index": 1
},
{
+ "default": "0",
"depends_on": "variant_of",
"fieldname": "show_variant_in_website",
"fieldtype": "Check",
@@ -1016,6 +1021,12 @@
"fieldtype": "Check",
"label": "Synced With Hub",
"read_only": 1
+ },
+ {
+ "fieldname": "manufacturers",
+ "fieldtype": "Table",
+ "label": "Manufacturers",
+ "options": "Item Manufacturer"
}
],
"has_web_view": 1,
@@ -1023,7 +1034,7 @@
"idx": 2,
"image_field": "image",
"max_attachments": 1,
- "modified": "2019-05-16 09:32:27.056036",
+ "modified": "2019-06-02 04:45:59.911507",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",
diff --git a/erpnext/stock/doctype/item/item_dashboard.py b/erpnext/stock/doctype/item/item_dashboard.py
index 8e4f74d..b3733d3 100644
--- a/erpnext/stock/doctype/item/item_dashboard.py
+++ b/erpnext/stock/doctype/item/item_dashboard.py
@@ -41,7 +41,7 @@
},
{
'label': _('Manufacture'),
- 'items': ['Work Order']
+ 'items': ['Work Order', 'Item Manufacturer']
}
]
}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/templates/item.html b/erpnext/stock/doctype/item/templates/item.html
new file mode 100644
index 0000000..db12309
--- /dev/null
+++ b/erpnext/stock/doctype/item/templates/item.html
@@ -0,0 +1,7 @@
+{% extends "templates/web.html" %}
+
+{% block page_content %}
+<h1>{{ title }}</h1>
+{% endblock %}
+
+<!-- this is a sample default web page template -->
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/templates/item_row.html b/erpnext/stock/doctype/item/templates/item_row.html
new file mode 100644
index 0000000..2b99981
--- /dev/null
+++ b/erpnext/stock/doctype/item/templates/item_row.html
@@ -0,0 +1,4 @@
+<div>
+ <a href={{ route }}>{{ title }}</a>
+</div>
+<!-- this is a sample default list template -->
\ No newline at end of file
diff --git a/erpnext/manufacturing/report/bom_items_and_scraps/__init__.py b/erpnext/stock/doctype/item_manufacturer/__init__.py
similarity index 100%
copy from erpnext/manufacturing/report/bom_items_and_scraps/__init__.py
copy to erpnext/stock/doctype/item_manufacturer/__init__.py
diff --git a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.js b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.js
new file mode 100644
index 0000000..a4df923
--- /dev/null
+++ b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Item Manufacturer', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.json b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.json
new file mode 100644
index 0000000..956c92e
--- /dev/null
+++ b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.json
@@ -0,0 +1,105 @@
+{
+ "allow_import": 1,
+ "creation": "2019-06-02 04:41:37.332911",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "item_code",
+ "manufacturer",
+ "manufacturer_part_no",
+ "column_break_3",
+ "item_name",
+ "description"
+ ],
+ "fields": [
+ {
+ "fieldname": "manufacturer",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Manufacturer",
+ "options": "Manufacturer",
+ "reqd": 1
+ },
+ {
+ "fieldname": "manufacturer_part_no",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Manufacturer Part Number",
+ "reqd": 1
+ },
+ {
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "label": "Item Code",
+ "options": "Item",
+ "reqd": 1
+ },
+ {
+ "fetch_from": "item_code.item_name",
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "item_code.description",
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description",
+ "read_only": 1
+ }
+ ],
+ "modified": "2019-06-06 19:07:31.175919",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Item Manufacturer",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock User",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Item Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "title_field": "item_code",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py
new file mode 100644
index 0000000..67eab82
--- /dev/null
+++ b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+from frappe import _
+from frappe.model.document import Document
+
+class ItemManufacturer(Document):
+ def validate(self):
+ self.validate_duplicate_entry()
+
+ def validate_duplicate_entry(self):
+ if self.is_new():
+ filters = {
+ 'item_code': self.item_code,
+ 'manufacturer': self.manufacturer,
+ 'manufacturer_part_no': self.manufacturer_part_no
+ }
+
+ if frappe.db.exists("Item Manufacturer", filters):
+ frappe.throw(_("Duplicate entry against the item code {0} and manufacturer {1}")
+ .format(self.item_code, self.manufacturer))
+
+@frappe.whitelist()
+def get_item_manufacturer_part_no(item_code, manufacturer):
+ return frappe.db.get_value("Item Manufacturer",
+ {'item_code': item_code, 'manufacturer': manufacturer}, 'manufacturer_part_no')
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item_manufacturer/test_item_manufacturer.py b/erpnext/stock/doctype/item_manufacturer/test_item_manufacturer.py
new file mode 100644
index 0000000..1cef20c
--- /dev/null
+++ b/erpnext/stock/doctype/item_manufacturer/test_item_manufacturer.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestItemManufacturer(unittest.TestCase):
+ pass
diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.json b/erpnext/stock/doctype/material_request_item/material_request_item.json
index 9f4f14a..795971b 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.json
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.json
@@ -15,6 +15,10 @@
"brand",
"image_section",
"image",
+ "manufacture_details",
+ "manufacturer",
+ "column_break_12",
+ "manufacturer_part_no",
"quantity_and_warehouse",
"qty",
"uom",
@@ -378,11 +382,32 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "manufacture_details",
+ "fieldtype": "Section Break",
+ "label": "Manufacture"
+ },
+ {
+ "fieldname": "manufacturer",
+ "fieldtype": "Link",
+ "label": "Manufacturer",
+ "options": "Manufacturer"
+ },
+ {
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "manufacturer_part_no",
+ "fieldtype": "Data",
+ "label": "Manufacturer Part Number",
+ "read_only": 1
}
],
"idx": 1,
"istable": 1,
- "modified": "2019-05-25 22:03:10.517886",
+ "modified": "2019-06-02 06:49:36.493957",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request Item",
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index 66df86b..bb5cd52 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -19,6 +19,10 @@
"image_section",
"image",
"image_view",
+ "manufacture_details",
+ "manufacturer",
+ "column_break_16",
+ "manufacturer_part_no",
"received_and_accepted",
"received_qty",
"qty",
@@ -788,11 +792,33 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "manufacture_details",
+ "fieldtype": "Section Break",
+ "label": "Manufacture"
+ },
+ {
+ "fieldname": "manufacturer",
+ "fieldtype": "Link",
+ "label": "Manufacturer",
+ "options": "Manufacturer"
+ },
+ {
+ "fieldname": "column_break_16",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "manufacturer_part_no",
+ "fieldtype": "Data",
+ "label": "Manufacturer Part Number",
+ "read_only": 1
}
],
"idx": 1,
"istable": 1,
- "modified": "2019-06-01 23:25:20.732134",
+ "modified": "2019-06-02 06:37:48.198745",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index f694af8..791fad8 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -14,6 +14,7 @@
from erpnext.stock.doctype.item.item import get_item_defaults, get_uom_conv_factor
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
from erpnext.setup.doctype.brand.brand import get_brand_defaults
+from erpnext.stock.doctype.item_manufacturer.item_manufacturer import get_item_manufacturer_part_no
from six import string_types, iteritems
@@ -312,6 +313,14 @@
for fieldname in ("item_name", "item_group", "barcodes", "brand", "stock_uom"):
out[fieldname] = item.get(fieldname)
+ if args.get("manufacturer"):
+ part_no = get_item_manufacturer_part_no(args.get("item_code"), args.get("manufacturer"))
+ if part_no:
+ out["manufacturer_part_no"] = part_no
+ else:
+ out["manufacturer_part_no"] = None
+ out["manufacturer"] = None
+
return out
@frappe.whitelist()
diff --git a/erpnext/www/lms.html b/erpnext/www/lms.html
deleted file mode 100644
index aa76ca0..0000000
--- a/erpnext/www/lms.html
+++ /dev/null
@@ -1,39 +0,0 @@
-{% extends "templates/web.html" %}
-
-{% block title %}{{ heading or "LMS"}}{% endblock %}
-
-{% block navbar %}{% endblock %}
-
-{% block content %}
-{% if lms_enabled %}
-<div id="lms-app"></div>
-<script type="text/javascript" src="/assets/js/lms.min.js"></script>
-{% else %}
-<style>
-.hero-and-content {
- background-color: #f5f7fa;
-}
-header, footer {
- display: none;
-}
-html, body {
- background-color: #f5f7fa;
-}
-{% include "templates/styles/card_style.css" %}
-</style>
-
-<div class='page-card'>
- <div class='page-card-head'>
- <span class='indicator darkgrey'>{{_("Page Missing or Moved")}}</span>
- </div>
- <p>{{_("The page you are looking for is missing. This could be because it is moved or there is a typo in the link.")}}</p>
- <div><a href='/' class='btn btn-primary btn-sm'>{{ _("Home") }}</a></div>
-</div>
-<p class='text-muted text-center small' style='margin-top: -20px;'>{{ _("Error Code: {0}").format('404') }}</p>
-<style>
-.hero-and-content {
- background-color: #f5f7fa;
-}
-</style>
-{% endif %}
-{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/lms.py b/erpnext/www/lms.py
deleted file mode 100644
index 7561d73..0000000
--- a/erpnext/www/lms.py
+++ /dev/null
@@ -1,242 +0,0 @@
-from __future__ import unicode_literals
-import erpnext.education.utils as utils
-import frappe
-from frappe import _
-
-# LMS Utils to Update State for Vue Store
-@frappe.whitelist()
-def get_program_enrollments():
- student = utils.get_current_student()
- if student == None:
- return None
- return student.get_program_enrollments()
-
-@frappe.whitelist()
-def get_all_course_enrollments():
- student = utils.get_current_student()
- if student == None:
- return None
- return student.get_all_course_enrollments()
-
-# Vue Client Functions
-@frappe.whitelist(allow_guest=True)
-def get_portal_details():
- """
- Returns portal details from Education Settings Doctype. This contains the Title and Description for LMS amoung other things.
- """
- from erpnext import get_default_company
-
- settings = frappe.get_doc("Education Settings")
- title = settings.portal_title or get_default_company()
- description = settings.description
- return dict(title=title, description=description)
-
-@frappe.whitelist(allow_guest=True)
-def get_featured_programs():
- featured_program_names = frappe.get_all("Program", filters={"is_published": True, "is_featured": True})
- if featured_program_names:
- featured_list = [utils.get_program_and_enrollment_status(program['name']) for program in featured_program_names]
- return featured_list
- else:
- return get_all_programs()[:2]
-
-@frappe.whitelist(allow_guest=True)
-def get_all_programs():
- program_names = frappe.get_all("Program", filters={"is_published": True})
- if program_names:
- program_list = [utils.get_program_and_enrollment_status(program['name']) for program in program_names]
- return program_list
-
-@frappe.whitelist(allow_guest=True)
-def get_program(program_name):
- try:
- return frappe.get_doc('Program', program_name)
- except frappe.DoesNotExistError:
- frappe.throw(_("Program {0} does not exist.".format(program_name)))
-
-# Functions to get program & course details
-@frappe.whitelist(allow_guest=True)
-def get_courses(program_name):
- program = frappe.get_doc('Program', program_name)
- courses = program.get_course_list()
- return courses
-
-@frappe.whitelist()
-def get_next_content(current_content, current_content_type, topic):
- if frappe.session.user == "Guest":
- return None
- topic = frappe.get_doc("Topic", topic)
- content_list = [{'content_type':item.doctype, 'content':item.name} for item in topic.get_contents()]
- current_index = content_list.index({'content': current_content, 'content_type': current_content_type})
- try:
- return content_list[current_index + 1]
- except IndexError:
- return None
-
-def get_quiz_with_answers(quiz_name):
- try:
- quiz = frappe.get_doc("Quiz", quiz_name).get_questions()
- quiz_output = [{'name':question.name, 'question':question.question, 'options':[{'name': option.name, 'option':option.option, 'is_correct':option.is_correct} for option in question.options]} for question in quiz]
- return quiz_output
- except:
- frappe.throw("Quiz {0} does not exist".format(quiz_name))
- return None
-
-@frappe.whitelist()
-def get_quiz_without_answers(quiz_name, course_name):
- try:
- quiz = frappe.get_doc("Quiz", quiz_name)
- questions = quiz.get_questions()
- except:
- frappe.throw("Quiz {0} does not exist".format(quiz_name))
- return None
-
- if utils.check_super_access():
- quiz_output = [{'name':question.name, 'question':question.question, 'type': question.type, 'options':[{'name': option.name, 'option':option.option} for option in question.options]} for question in questions]
- return { 'quizData': quiz_output, 'status': None}
-
- enrollment = utils.get_course_enrollment(course_name).name
- quiz_progress = {}
- quiz_progress['is_complete'], quiz_progress['score'], quiz_progress['result'] = utils.check_quiz_completion(quiz, enrollment)
- quiz_output = [{'name':question.name, 'question':question.question, 'type': question.type, 'options':[{'name': option.name, 'option':option.option} for option in question.options]} for question in questions]
- return { 'quizData': quiz_output, 'status': quiz_progress}
-
-@frappe.whitelist()
-def evaluate_quiz(course, quiz_response, quiz_name):
- """LMS Function: Evaluates a simple multiple choice quiz.
- :param course: name of the course
- :param quiz_response: contains user selected choices for a quiz in the form of a string formatted as a dictionary. The function uses `json.loads()` to convert it to a python dictionary.
- :param quiz_name: Name of the quiz attempted
- """
- import json
- quiz_response = json.loads(quiz_response)
- quiz = frappe.get_doc("Quiz", quiz_name)
- answers, score, status = quiz.evaluate(quiz_response, quiz_name)
- print(answers)
-
- course_enrollment = utils.get_course_enrollment(course)
- if course_enrollment:
- course_enrollment.add_quiz_activity(quiz_name, quiz_response, answers, score, status)
-
- return score
-
-@frappe.whitelist()
-def enroll_in_program(program_name):
- student = utils.get_current_student()
- if not student:
- student = utils.create_student_from_current_user()
- program_enrollment = student.enroll_in_program(program_name)
- return program_name
-
-# Academdy Activity
-@frappe.whitelist()
-def add_activity(course, content_type, content):
- if not utils.get_current_student():
- return
- enrollment = utils.get_course_enrollment(course)
- enrollment.add_activity(content_type, content)
-
-@frappe.whitelist()
-def get_student_course_details(course_name, program_name):
- """
- Return the porgress of a course in a program as well as the content to continue from.
- :param course_name:
- :param program_name:
- """
- student = utils.get_current_student()
- if not student:
- return {'flag':'Start Course' }
-
- course_enrollment = utils.get_course_enrollment(course_name)
- program_enrollment = utils.get_program_enrollment(program_name)
-
- if not program_enrollment:
- return None
-
- if not course_enrollment:
- course_enrollment = utils.enroll_in_course(course_name, program_name)
-
- progress = course_enrollment.get_progress(student)
- count = sum([activity['is_complete'] for activity in progress])
- if count == 0:
- return {'flag':'Start Course'}
- elif count == len(progress):
- return {'flag':'Completed'}
- elif count < len(progress):
- next_item = next(item for item in progress if item['is_complete']==False)
- return {'flag':'Continue'}
-
-@frappe.whitelist()
-def get_student_topic_details(topic_name, course_name):
- """
- Return the porgress of a course in a program as well as the content to continue from.
- :param topic_name:
- :param course_name:
- """
- topic = frappe.get_doc("Topic", topic_name)
- student = utils.get_current_student()
- if not student:
- topic_content = topic.get_all_children()
- if topic_content:
- return {'flag':'Start Course', 'content_type': topic_content[0].content_type, 'content': topic_content[0].content}
- else:
- return None
- course_enrollment = utils.get_course_enrollment(course_name)
- progress = student.get_topic_progress(course_enrollment.name, topic)
- if not progress:
- return { 'flag':'Start Topic', 'content_type': None, 'content': None }
- count = sum([activity['is_complete'] for activity in progress])
- if count == 0:
- return {'flag':'Start Topic', 'content_type': progress[0]['content_type'], 'content': progress[0]['content']}
- elif count == len(progress):
- return {'flag':'Completed', 'content_type': progress[0]['content_type'], 'content': progress[0]['content']}
- elif count < len(progress):
- next_item = next(item for item in progress if item['is_complete']==False)
- return {'flag':'Continue', 'content_type': next_item['content_type'], 'content': next_item['content']}
-
-@frappe.whitelist()
-def get_program_progress(program_name):
- program_enrollment = frappe.get_doc("Program Enrollment", utils.get_program_enrollment(program_name))
- if not program_enrollment:
- return None
- else:
- return program_enrollment.get_program_progress()
-
-@frappe.whitelist()
-def get_joining_date():
- student = utils.get_current_student()
- if student:
- return student.joining_date
-
-@frappe.whitelist()
-def get_quiz_progress_of_program(program_name):
- program_enrollment = frappe.get_doc("Program Enrollment", utils.get_program_enrollment(program_name))
- if not program_enrollment:
- return None
- else:
- return program_enrollment.get_quiz_progress()
-
-
-@frappe.whitelist(allow_guest=True)
-def get_course_details(course_name):
- try:
- course = frappe.get_doc('Course', course_name)
- return course
- except:
- return None
-
-# Functions to get program & course details
-@frappe.whitelist(allow_guest=True)
-def get_topics(course_name):
- try:
- course = frappe.get_doc('Course', course_name)
- return course.get_topics()
- except frappe.DoesNotExistError:
- frappe.throw(_("Course {0} does not exist.".format(course_name)))
-
-@frappe.whitelist()
-def get_content(content_type, content):
- try:
- return frappe.get_doc(content_type, content)
- except frappe.DoesNotExistError:
- frappe.throw(_("{0} {1} does not exist.".format(content_type, content)))
\ No newline at end of file
diff --git a/erpnext/manufacturing/report/bom_items_and_scraps/__init__.py b/erpnext/www/lms/__init__.py
similarity index 100%
copy from erpnext/manufacturing/report/bom_items_and_scraps/__init__.py
copy to erpnext/www/lms/__init__.py
diff --git a/erpnext/www/lms/content.html b/erpnext/www/lms/content.html
new file mode 100644
index 0000000..9b8c45c
--- /dev/null
+++ b/erpnext/www/lms/content.html
@@ -0,0 +1,208 @@
+{% extends "templates/base.html" %}
+{% block title %}{{ content.name or 'Content Page' }}{% endblock %}
+
+{% block head_include %}
+ <style>
+ .lms-content {
+ line-height: 1.8em;
+ }
+
+ .lms-content h1 {
+ margin-top: 1em;
+ }
+
+ .lms-content h2 {
+ margin-top: 1em;
+ }
+
+ .lms-content h3 {
+ margin-top: 0.8em;
+ }
+
+ .lms-content h4 {
+ margin-top: 0.6em;
+ }
+
+ section {
+ padding: 5rem 0 5rem 0;
+ }
+ .plyr--video .plyr__control.plyr__tab-focus,
+ .plyr--video .plyr__control:hover,
+ .plyr--video .plyr__control[aria-expanded='true'] {
+ background: #5e64ff !important;
+ }
+
+ .plyr__control--overlaid:focus,
+ .plyr__control--overlaid:hover {
+ background: #5e64ff !important;
+ }
+
+ .plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]::before {
+ background: #5e64ff !important;
+ }
+
+ .plyr__menu__container
+ .plyr__control[role='menuitemradio'][aria-checked='true']::before {
+ background: #5e64ff;
+ }
+ .plyr--full-ui input[type='range'] {
+ color: #5e64ff !important;
+ }
+
+ .plyr__control--overlaid {
+ background: rgba(94, 100, 255, 0.8) !important;
+ }
+ </style>
+ <link rel="stylesheet" href="https://cdn.plyr.io/3.5.3/plyr.css" />
+{% endblock %}
+
+{% macro title() %}
+ <div class="mb-3">
+ <a href="#" class="text-muted">
+ Back to Course
+ </a>
+ </div>
+ <div>
+ <h1>{{ content.name }} <span class="small text-muted">({{ position + 1 }}/{{length}})</span></h1>
+ </div>
+{% endmacro %}
+
+{% macro navigation() %}
+ {% if previous %}
+ <a href="/lms/content?program={{ program }}&course={{ course }}&topic={{ topic }}&type={{ previous.content_type }}&content={{ previous.content }}" class='btn text-muted' style="box-shadow: none;">Previous</a>
+ {% else %}
+ <a href="/lms/course?name={{ course }}&program={{ program }}" class='btn text-muted' style="box-shadow: none;">Back to Course</a>
+ {% endif %}
+
+ {% if next %}
+ <button id="nextButton" onclick="handle('/lms/content?program={{ program }}&course={{ course }}&topic={{ topic }}&type={{ next.content_type }}&content={{ next.content }}')" class='btn btn-primary' disabled="true">Next</button>
+ {% else %}
+ <button id="nextButton" onclick="handle('/lms/course?name={{ course }}&program={{ program }}')" class='btn btn-primary' disabled="true">Finish Topic</button>
+ {% endif %}
+{% endmacro %}
+
+{% macro video() %}
+<div class="mb-5">
+ {{ title() }}
+ <div class="text-muted">
+ {% if content.duration %}
+ {{ content.duration }} Mins
+ {% endif %}
+
+ {% if content.publish_date and content.duration%}
+ -
+ {% endif %}
+
+ {% if content.publish_date %}
+ Published on {{ content.publish_date.strftime('%d, %b %Y') }}
+ {% endif %}
+ </div>
+</div>
+<div id="player" data-plyr-provider="{{ content.provider|lower }}" data-plyr-embed-id="{{ content.url }}"></div>
+<div class="my-5 lms-content">
+ {{ content.description }}
+</div>
+{% endmacro %}
+
+{% macro article() %}
+<div class="mb-5">
+ {{ title() }}
+ <div class="text-muted">
+ {% if content.author or content.publish_date %}
+ Published
+ {% endif %}
+ {% if content.author %}
+ by {{ content.author }}
+ {% endif %}
+ {% if content.publish_date %}
+ on {{ content.publish_date.strftime('%d, %b %Y') }}
+ {% endif %}
+ </div>
+</div>
+<div class="lms-content">
+ {{ content.content }}
+</div>
+{% endmacro %}
+
+{% macro quiz() %}
+<div class="mb-5">
+ {{ title() }}
+</div>
+<div id="quiz-wrapper">
+</div>
+{% endmacro %}
+
+{% block content %}
+<section class="section">
+ <div>
+ <div class='container pb-5'>
+ {% if content_type=='Video' %}
+ {{ video() }}
+ {% elif content_type=='Article'%}
+ {{ article() }}
+ {% elif content_type=='Quiz' %}
+ {{ quiz() }}
+ {% endif %}
+ <div class="pull-right" {{ 'hidden' if content_type=='Quiz'}}>
+ {{ navigation() }}
+ </div>
+ </div>
+ </div>
+</section>
+{% endblock %}
+
+{% block script %}
+ {% if content_type=='Video' %}
+ <script src="https://cdn.plyr.io/3.5.3/plyr.js"></script>
+ {% elif content_type == 'Quiz' %}
+ <script src='/assets/erpnext/js/education/lms/quiz.js'></script>
+ {% endif %}
+ <script>
+ {% if content_type == 'Video' %}
+ const player = new Plyr('#player');
+ {% elif content_type == 'Quiz' %}
+ {% if next %}
+ const quiz_exit_button = 'Next'
+ const next_url = '/lms/content?program={{ program }}&course={{ course }}&topic={{ topic }}&type={{ next.content_type }}&content={{ next.content }}'
+ {% else %}
+ const quiz_exit_button = 'Finish Course'
+ const next_url = '/lms/course?name={{ course }}&program={{ program }}'
+ {% endif %}
+ frappe.ready(() => {
+ const quiz = new Quiz(document.getElementById('quiz-wrapper'), {
+ name: '{{ content.name }}',
+ course: '{{ course }}',
+ program: '{{ program }}',
+ quiz_exit_button: quiz_exit_button,
+ next_url: next_url
+ })
+ window.quiz = quiz;
+ })
+ {% endif %}
+
+ {% if content_type != 'Quiz' %}
+
+ frappe.ready(() => {
+ next = document.getElementById('nextButton')
+ next.disabled = false;
+ })
+
+
+ function handle(url) {
+ opts = {
+ method: "erpnext.education.utils.add_activity",
+ args: {
+ course: "{{ course }}",
+ content_type: "{{ content_type }}",
+ content: "{{ content.name }}",
+ program: "{{ program }}"
+ }
+ }
+ frappe.call(opts).then(res => {
+ window.location.href = url;
+ })
+ }
+
+ {% endif %}
+ </script>
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/lms/content.py b/erpnext/www/lms/content.py
new file mode 100644
index 0000000..0c04845
--- /dev/null
+++ b/erpnext/www/lms/content.py
@@ -0,0 +1,68 @@
+from __future__ import unicode_literals
+import erpnext.education.utils as utils
+import frappe
+
+no_cache = 1
+
+def get_context(context):
+ # Load Query Parameters
+ try:
+ program = frappe.form_dict['program']
+ content = frappe.form_dict['content']
+ content_type = frappe.form_dict['type']
+ course = frappe.form_dict['course']
+ topic = frappe.form_dict['topic']
+ except KeyError:
+ frappe.local.flags.redirect_location = '/lms'
+ raise frappe.Redirect
+
+
+ # Check if user has access to the content
+ has_program_access = utils.allowed_program_access(program)
+ has_content_access = allowed_content_access(program, content, content_type)
+
+ if frappe.session.user == "Guest" or not has_program_access or not has_content_access:
+ frappe.local.flags.redirect_location = '/lms'
+ raise frappe.Redirect
+
+
+ # Set context for content to be displayer
+ context.content = frappe.get_doc(content_type, content).as_dict()
+ context.content_type = content_type
+ context.program = program
+ context.course = course
+ context.topic = topic
+
+ topic = frappe.get_doc("Topic", topic)
+ content_list = [{'content_type':item.content_type, 'content':item.content} for item in topic.topic_content]
+
+ # Set context for progress numbers
+ context.position = content_list.index({'content': content, 'content_type': content_type})
+ context.length = len(content_list)
+
+ # Set context for navigation
+ context.previous = get_previous_content(content_list, context.position)
+ context.next = get_next_content(content_list, context.position)
+
+def get_next_content(content_list, current_index):
+ try:
+ return content_list[current_index + 1]
+ except IndexError:
+ return None
+
+def get_previous_content(content_list, current_index):
+ if current_index == 0:
+ return None
+ else:
+ return content_list[current_index - 1]
+
+def allowed_content_access(program, content, content_type):
+ contents_of_program = frappe.db.sql("""select `tabTopic Content`.content, `tabTopic Content`.content_type
+ from `tabCourse Topic`,
+ `tabProgram Course`,
+ `tabTopic Content`
+ where `tabCourse Topic`.parent = `tabProgram Course`.course
+ and `tabTopic Content`.parent = `tabCourse Topic`.topic
+ and `tabProgram Course`.parent = %(program)s""", {'program': program})
+
+ return (content, content_type) in contents_of_program
\ No newline at end of file
diff --git a/erpnext/www/lms/course.html b/erpnext/www/lms/course.html
new file mode 100644
index 0000000..f8618e0
--- /dev/null
+++ b/erpnext/www/lms/course.html
@@ -0,0 +1,125 @@
+{% extends "templates/base.html" %}
+{% block title %}{{ course.course_name }}{% endblock %}
+{% from "www/lms/macros/hero.html" import hero %}
+{% from "www/lms/macros/card.html" import null_card %}
+
+{% block head_include %}
+ <style>
+ div.card-hero-img {
+ height: 220px;
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-color: rgb(250, 251, 252);
+ }
+
+ .card-image-wrapper {
+ display: flex;
+ overflow: hidden;
+ height: 220px;
+ background-color: rgb(250, 251, 252);
+ justify-content: center;
+ }
+
+ .image-body {
+ align-self: center;
+ color: #d1d8dd;
+ font-size: 24px;
+ font-weight: 600;
+ line-height: 1;
+ padding: 20px;
+ }
+ section {
+ padding: 5rem 0 5rem 0;
+ }
+ </style>
+{% endblock %}
+
+
+{% macro card(topic) %}
+<div class="col-sm-4 mb-4 text-left">
+ <div class="card h-100">
+ {% if has_access %}
+ <a href="/lms/topic?program={{ program }}&course={{ course.name }}&topic={{ topic.name }}" class="no-decoration no-underline">
+ {% else %}
+ <div onclick="show_singup()">
+ {% endif %}
+ {% if topic.hero_image %}
+ <div class="card-hero-img" style="background-image: url('{{ topic.hero_image }})'"></div>
+ {% else %}
+ <div class="card-image-wrapper text-center">
+ <div class="image-body"><i class="fa fa-picture-o" aria-hidden="true"></i></div>
+ </div>
+ {% endif %}
+ <div class='card-body'>
+ <h5 class='card-title'>{{ topic.topic_name }}</h5>
+ <div>
+ <ol class="list-unstyled">
+ {% for content in topic.topic_content %}
+ <li>
+ {% if has_access %}
+ <a class="text-muted" href="/lms/content?program={{ program }}&course={{ course.name }}&topic={{ topic.name }}&type={{ content.content_type }}&content={{ content.content }}">
+ {{ content.content }}
+ </a>
+ {% else %}
+ <span class="text-muted">{{ content.content }}</span>
+ {% endif %}
+ </li>
+ {% endfor %}
+ </ol>
+ </div>
+ </div>
+ {% if has_access %}
+ <div class='card-footer'>
+ {% if progress[topic.name].completed %}
+ <span class="indicator green">Completed</span>
+ {% elif progress[topic.name].started %}
+ <span class="indicator orange">In Progress</span>
+ {% else %}
+ <span class="indicator blue">Start</span>
+ {% endif %}
+ </div>
+ </a>
+ {% else %}
+ </div>
+ {% endif %}
+ </div>
+</div>
+{% endmacro %}
+
+{% block content %}
+<section class="section">
+ {{ hero(course.course_name, course.description, has_access, {'name': 'Program', 'url': '/lms/program?program=' + program }) }}
+ <div class='container'>
+ <div class="row mt-5">
+ {% for topic in topics %}
+ {{ card(topic) }}
+ {% endfor %}
+ {% if topics %}
+ {% for n in range(3 - ((topics|length)%3)) %}
+ {{ null_card() }}
+ {% endfor %}
+ {% endif %}
+ </div>
+ </div>
+</section>
+{% endblock %}
+
+{% block script %}
+<script>
+ function show_singup() {
+ if (frappe.session.user == "Guest") {
+ let signup_dialog = new frappe.ui.Dialog({
+ title: __('Sign Up'),
+ primary_action: function() {
+ window.location.href = '/login#signup'
+ },
+ primary_action_label: 'Sign Up'
+ })
+ signup_dialog.set_message('You have to sign up to access the course');
+ signup_dialog.$message.show()
+ signup_dialog.show();
+ }
+ }
+</script>
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/lms/course.py b/erpnext/www/lms/course.py
new file mode 100644
index 0000000..e7ed2e3
--- /dev/null
+++ b/erpnext/www/lms/course.py
@@ -0,0 +1,19 @@
+from __future__ import unicode_literals
+import erpnext.education.utils as utils
+import frappe
+
+no_cache = 1
+
+def get_context(context):
+ context.education_settings = frappe.get_single("Education Settings")
+ course = frappe.get_doc('Course', frappe.form_dict['name'])
+ context.program = frappe.form_dict['program']
+ context.course = course
+
+ context.topics = course.get_topics()
+ context.has_access = utils.allowed_program_access(context.program)
+ context.progress = get_topic_progress(context.topics, course, context.program)
+
+def get_topic_progress(topics, course, program):
+ progress = {topic.name: utils.get_topic_progress(topic, course.name, program) for topic in topics}
+ return progress
diff --git a/erpnext/www/lms/index.html b/erpnext/www/lms/index.html
new file mode 100644
index 0000000..3e107ac
--- /dev/null
+++ b/erpnext/www/lms/index.html
@@ -0,0 +1,65 @@
+{% extends "templates/base.html" %}
+{% block title %}{{ education_settings.portal_title }}{% endblock %}
+{% from "www/lms/macros/card.html" import program_card %}
+{% from "www/lms/macros/card.html" import null_card %}
+
+{% block head_include %}
+ <meta name="description" content="{{ education_settings.description }}" />
+ <meta name="keywords" content="ERP Software, Cloud ERP, Open Source ERP, Accounting Software, Online ERP, Online Accounting, ERP for small business" />
+ <style>
+ div.card-hero-img {
+ height: 220px;
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-color: rgb(250, 251, 252);
+ }
+
+ .card-image-wrapper {
+ display: flex;
+ overflow: hidden;
+ height: 220px;
+ background-color: rgb(250, 251, 252);
+ justify-content: center;
+ }
+
+ .image-body {
+ align-self: center;
+ color: #d1d8dd;
+ font-size: 24px;
+ font-weight: 600;
+ line-height: 1;
+ padding: 20px;
+ }
+
+ section {
+ padding: 5rem 0 5rem 0;
+ }
+ </style>
+{% endblock %}
+
+{% block content %}
+<section class="top-section" style="padding: 6rem 0rem;">
+ <div class='container pb-5'>
+ <h1>{{ education_settings.portal_title }}</h1>
+ <p class='lead'>{{ education_settings.description }}</p>
+ <p class="mt-4">
+ {% if frappe.session.user == 'Guest' %}
+ <a class="btn btn-primary btn-lg" href="'/login#signup'">Sign Up</a>
+ {% endif %}
+ </p>
+ </div>
+ <div class='container'>
+ <div class="row mt-5">
+ {% for program in featured_programs %}
+ {{ program_card(program.program, program.has_access) }}
+ {% endfor %}
+ {% if featured_programs %}
+ {% for n in range(3 - ((featured_programs|length)%3)) %}
+ {{ null_card() }}
+ {% endfor %}
+ {% endif %}
+ </div>
+ </div>
+</section>
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/lms/index.py b/erpnext/www/lms/index.py
new file mode 100644
index 0000000..00f66e7
--- /dev/null
+++ b/erpnext/www/lms/index.py
@@ -0,0 +1,16 @@
+from __future__ import unicode_literals
+import erpnext.education.utils as utils
+import frappe
+
+no_cache = 1
+
+def get_context(context):
+ context.education_settings = frappe.get_single("Education Settings")
+ if not context.education_settings.enable_lms:
+ frappe.local.flags.redirect_location = '/'
+ raise frappe.Redirect
+ context.featured_programs = get_featured_programs()
+
+
+def get_featured_programs():
+ return utils.get_portal_programs()
\ No newline at end of file
diff --git a/erpnext/www/lms/macros/card.html b/erpnext/www/lms/macros/card.html
new file mode 100644
index 0000000..9964d2d
--- /dev/null
+++ b/erpnext/www/lms/macros/card.html
@@ -0,0 +1,34 @@
+{% macro program_card(program, has_access) %}
+<div class="col-sm-4 mb-4 text-left">
+ <a href="/lms/program?program={{ program.name }}" class="no-decoration no-underline">
+ <div class="card h-100">
+ {% if program.hero_image %}
+ <div class="card-hero-img" style="background-image: url('{{ program.hero_image }}')"></div>
+ {% else %}
+ <div class="card-image-wrapper text-center">
+ <div class="image-body"><i class="fa fa-picture-o" aria-hidden="true"></i></div>
+ </div>
+ {% endif %}
+ <div class='card-body'>
+ <h5 class='card-title'>{{ program.program_name }}</h5>
+ <div class="text-muted">{{ program.description[:110] + '...' if program.description else '' }}</div>
+ </div>
+ {% if has_access or program.intro_video%}
+ <div class='card-footer'>
+ {% if has_access %} <span class="indicator green">Enrolled</span>
+ {% elif program.intro_video %} <span><a href="{{ program.intro_video }}" target="blank">Watch Intro</a></span>
+ {% endif %}
+ </div>
+ {% endif %}
+ </div>
+ </a>
+</div>
+{% endmacro %}
+
+
+{% macro null_card() %}
+<div class="col-sm-4 mb-4 text-left">
+ <div class="h-100" style="border: 1px solid rgba(209,216,221,0.5);border-radius: 0.25rem;background-color: rgb(250, 251, 252);">
+ </div>
+</div>
+{% endmacro %}
\ No newline at end of file
diff --git a/erpnext/www/lms/macros/hero.html b/erpnext/www/lms/macros/hero.html
new file mode 100644
index 0000000..66bb861
--- /dev/null
+++ b/erpnext/www/lms/macros/hero.html
@@ -0,0 +1,55 @@
+{% macro hero(title, description, has_access, back) %}
+ <div class='container pb-5'>
+ <div class="mb-3">
+ <a href="{{ back.url }}" class="text-muted">
+ Back to {{ back.name }}
+ </a>
+ </div>
+ <h1>{{ title }}</h1>
+ <p class='lead' style="max-width: 100%;">{{ description or ''}}</p>
+ <p class="mt-4">
+ {% if frappe.session.user == 'Guest' %}
+ <a id="signup" class="btn btn-primary btn-lg" href="/login#signup">Sign Up</a>
+ {% elif not has_access %}
+ <button id="enroll" class="btn btn-primary btn-lg" onclick="enroll()" disabled>Enroll</button>
+ {% endif %}
+ </p>
+ </div>
+
+{% block script %}
+<script type="text/javascript">
+ frappe.ready(() => {
+ btn = document.getElementById('enroll');
+ if (btn) btn.disabled = false;
+ })
+
+ function enroll() {
+ let params = frappe.utils.get_query_params()
+
+ let btn = document.getElementById('enroll');
+ btn.disbaled = true;
+ btn.innerText = 'Enrolling...'
+
+ let opts = {
+ method: 'erpnext.education.utils.enroll_in_program',
+ args: {
+ program_name: params.program
+ }
+ }
+
+ frappe.call(opts).then(res => {
+ let success_dialog = new frappe.ui.Dialog({
+ title: __('Success'),
+ secondary_action: function() {
+ window.location.reload()
+ }
+ })
+ success_dialog.set_message('You have successfully enrolled for the program ');
+ success_dialog.$message.show()
+ success_dialog.show();
+ btn.disbaled = false;
+ })
+ }
+</script>
+{% endblock %}
+{% endmacro %}
\ No newline at end of file
diff --git a/erpnext/www/lms/profile.html b/erpnext/www/lms/profile.html
new file mode 100644
index 0000000..9508dae
--- /dev/null
+++ b/erpnext/www/lms/profile.html
@@ -0,0 +1,64 @@
+{% extends "templates/base.html" %}
+{% block title %}Profile{% endblock %}
+{% from "www/lms/macros/hero.html" import hero %}
+
+{% block head_include %}
+ <style>
+ section {
+ padding: 5rem 0 5rem 0;
+ }
+ </style>
+{% endblock %}
+
+{% macro card(program) %}
+<div class="col-sm-4 mb-4 text-left">
+ <a href="/lms/program?program={{ program.name }}" class="no-decoration no-underline">
+ <div class="card h-100">
+ <div class='card-body'>
+ <h5 class='card-title'>{{ program.program }}</h5>
+ <ul class="list-unstyled text-muted">
+ {% for course in program.progress %}
+ <li>
+ {% if course.completed %} <span class="indicator green">
+ {% elif course.started %} <span class="indicator orange">
+ {% else %} <span class="indicator blue">
+ {% endif %}
+ <a class="text-muted" href="/lms/course?name={{ course.name }}&program={{ program.name }}">{{ course.course }}</a>
+ </span>
+ </li>
+ {% endfor %}
+ </ul>
+ </div>
+ <div class='card-footer'>
+ <span class="small">{{ program.completion }}% Complete</span>
+ </div>
+ </div>
+ </a>
+</div>
+{% endmacro %}
+
+{% block content %}
+<section class="section">
+ <div class='container pb-5'>
+ <div class="mb-3 row">
+ <div class="col-md-7">
+ <a href="/lms" class="text-muted">
+ Back to Home
+ </a>
+ </div>
+ <div class="col-md-5 text-right">
+ <a href="/update-profile?name={{ frappe.session.user }}" target="blank" class="mt-0 text-muted">Edit Profile</a>
+ </div>
+ </div>
+ <h1>{{ student.first_name }} {{ student.last_name or '' }}</h1>
+ <p class="lead" style="max-width: 100%;">{{ student.name }}</p>
+ </div>
+ <div class='container'>
+ <div class="row mt-5">
+ {% for program in progress %}
+ {{ card(program) }}
+ {% endfor %}
+ </div>
+ </div>
+</section>
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/lms/profile.py b/erpnext/www/lms/profile.py
new file mode 100644
index 0000000..4788ea6
--- /dev/null
+++ b/erpnext/www/lms/profile.py
@@ -0,0 +1,26 @@
+from __future__ import unicode_literals
+import erpnext.education.utils as utils
+import frappe
+
+no_cache = 1
+
+def get_context(context):
+ if frappe.session.user == "Guest":
+ frappe.local.flags.redirect_location = '/lms'
+ raise frappe.Redirect
+
+ context.student = utils.get_current_student()
+ if not context.student:
+ context.student = frappe.get_doc('User', frappe.session.user)
+ context.progress = get_program_progress(context.student.name)
+
+def get_program_progress(student):
+ enrolled_programs = frappe.get_all("Program Enrollment", filters={'student':student}, fields=['program'])
+ student_progress = []
+ for list_item in enrolled_programs:
+ program = frappe.get_doc("Program", list_item.program)
+ progress = utils.get_program_progress(program)
+ completion = utils.get_program_completion(program)
+ student_progress.append({'program': program.program_name, 'name': program.name, 'progress':progress, 'completion': completion})
+
+ return student_progress
\ No newline at end of file
diff --git a/erpnext/www/lms/program.html b/erpnext/www/lms/program.html
new file mode 100644
index 0000000..b6d6966
--- /dev/null
+++ b/erpnext/www/lms/program.html
@@ -0,0 +1,87 @@
+{% extends "templates/base.html" %}
+{% block title %}{{ program.program_name }}{% endblock %}
+{% from "www/lms/macros/hero.html" import hero %}
+{% from "www/lms/macros/card.html" import null_card %}
+
+{% block head_include %}
+ <style>
+ div.card-hero-img {
+ height: 220px;
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-color: rgb(250, 251, 252);
+ }
+
+ .card-image-wrapper {
+ display: flex;
+ overflow: hidden;
+ height: 220px;
+ background-color: rgb(250, 251, 252);
+ justify-content: center;
+ }
+
+ .image-body {
+ align-self: center;
+ color: #d1d8dd;
+ font-size: 24px;
+ font-weight: 600;
+ line-height: 1;
+ padding: 20px;
+ }
+
+ section {
+ padding: 5rem 0 5rem 0;
+ }
+ </style>
+{% endblock %}
+
+
+{% macro card(course) %}
+<div class="col-sm-4 mb-4 text-left">
+ <a href="/lms/course?name={{ course.name }}&program={{ program.name }}" class="no-decoration no-underline">
+ <div class="card h-100">
+ {% if course.hero_image %}
+ <div class="card-hero-img" style="background-image: url('{{ course.hero_image }}')"></div>
+ {% else %}
+ <div class="card-image-wrapper text-center">
+ <div class="image-body"><i class="fa fa-picture-o" aria-hidden="true"></i></div>
+ </div>
+ {% endif %}
+ <div class='card-body'>
+ <h5 class='card-title'>{{ course.course_name }}</h5>
+ <div class="text-muted">{{ course.description[:110] + '...' if course.description else '' }}</div>
+ </div>
+ {% if has_access and progress[course.name] %}
+ <div class='card-footer'>
+ {% if progress[course.name].completed %}
+ <span class="indicator green">Completed</span>
+ {% elif progress[course.name].started %}
+ <span class="indicator orange">In Progress</span>
+ {% else %}
+ <span class="indicator blue">Start</span>
+ {% endif %}
+ </div>
+ {% endif %}
+ </div>
+ </a>
+</div>
+{% endmacro %}
+
+{% block content %}
+<section class="section">
+ {{ hero(program.program_name, program.description, has_access, {'name': 'Home', 'url': '/lms'}) }}
+ <div class='container'>
+ <div class="row mt-5">
+ {% for course in courses %}
+ {{ card(course) }}
+ {% endfor %}
+ {% if courses %}
+ {% for n in range(3 - ((courses|length)%3)) %}
+ {{ null_card() }}
+ {% endfor %}
+ {% endif %}
+ </div>
+ </div>
+</section>
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/lms/program.py b/erpnext/www/lms/program.py
new file mode 100644
index 0000000..1fcb3d3
--- /dev/null
+++ b/erpnext/www/lms/program.py
@@ -0,0 +1,23 @@
+from __future__ import unicode_literals
+import erpnext.education.utils as utils
+import frappe
+from frappe import _
+
+no_cache = 1
+
+def get_context(context):
+ context.education_settings = frappe.get_single("Education Settings")
+ context.program = get_program(frappe.form_dict['program'])
+ context.courses = [frappe.get_doc("Course", course.course) for course in context.program.courses]
+ context.has_access = utils.allowed_program_access(frappe.form_dict['program'])
+ context.progress = get_course_progress(context.courses, context.program)
+
+def get_program(program_name):
+ try:
+ return frappe.get_doc('Program', program_name)
+ except frappe.DoesNotExistError:
+ frappe.throw(_("Program {0} does not exist.".format(program_name)))
+
+def get_course_progress(courses, program):
+ progress = {course.name: utils.get_course_progress(course, program) for course in courses}
+ return progress
\ No newline at end of file
diff --git a/erpnext/www/lms/topic.html b/erpnext/www/lms/topic.html
new file mode 100644
index 0000000..3bbfbd0
--- /dev/null
+++ b/erpnext/www/lms/topic.html
@@ -0,0 +1,58 @@
+{% extends "templates/base.html" %}
+{% block title %}Topic Title{% endblock %}
+{% from "www/lms/macros/hero.html" import hero %}
+{% from "www/lms/macros/card.html" import null_card %}
+
+{% block head_include %}
+ <style>
+ section {
+ padding: 5rem 0 5rem 0;
+ }
+ </style>
+{% endblock %}
+
+
+{% macro card(content, index, length) %}
+<div class="col-sm-{{ 12 if length%3 == 1 and index == 1 else 6 if length%3 == 2 and index in [1,2] else 4}} mb-4 text-left">
+ <a href="/lms/content?program={{ program }}&course={{ course }}&topic={{ topic.name }}&type={{ content.content_type }}&content={{ content.content.name }}" class="no-decoration no-underline">
+ <div class="card h-100">
+ <div class='card-body'>
+ <div class="text-muted">{{ content.content_type or '' }}</div>
+ <h5 class='card-title'>{{ content.content.name }}</h5>
+ </div>
+ {% if has_access %}
+ <div class='card-footer'>
+ {% if content.content_type == 'Quiz' %}
+ {% if content.result == 'Fail' %} <span class="indicator red">Fail <span class="text-muted">({{ content.score }}/100)</span></span>
+ {% elif content.result == 'Pass' %} <span class="indicator green">Pass <span class="text-muted">({{ content.score }}/100)</span>
+ {% else %} <span class="indicator blue">Start</span>
+ {% endif %}
+ {% else %}
+ {% if content.completed %} <span class="indicator green">Completed</span>
+ {% else %} <span class="indicator blue">Start</span>
+ {% endif %}
+ {% endif %}
+ </div>
+ {% endif %}
+ </div>
+ </a>
+</div>
+{% endmacro %}
+
+{% block content %}
+<section class="section">
+ {{ hero(topic.topic_name, topic.description, has_access, {'name': 'Course', 'url': '/lms/course?name=' + course +'&program=' + program}) }}
+ <div class='container'>
+ <div class="row mt-5">
+ {% for content in contents %}
+ {{ card(content, loop.index, topic.contents|length) }}
+ {% endfor %}
+ {% if contents %}
+ {% for n in range(3 - ((contents|length)%3)) %}
+ {{ null_card() }}
+ {% endfor %}
+ {% endif %}
+ </div>
+ </div>
+</section>
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/lms/topic.py b/erpnext/www/lms/topic.py
new file mode 100644
index 0000000..0af0778
--- /dev/null
+++ b/erpnext/www/lms/topic.py
@@ -0,0 +1,41 @@
+from __future__ import unicode_literals
+import erpnext.education.utils as utils
+import frappe
+
+no_cache = 1
+
+def get_context(context):
+ course = frappe.form_dict['course']
+ program = frappe.form_dict['program']
+ topic = frappe.form_dict['topic']
+
+ context.program = program
+ context.course = course
+ context.topic = frappe.get_doc("Topic", topic)
+ context.contents = get_contents(context.topic, course, program)
+ context.has_access = utils.allowed_program_access(program)
+
+def get_contents(topic, course, program):
+ student = utils.get_current_student()
+ if student:
+ course_enrollment = utils.get_or_create_course_enrollment(course, program)
+ contents = topic.get_contents()
+ progress = []
+ if contents:
+ for content in contents:
+ if content.doctype in ('Article', 'Video'):
+ if student:
+ status = utils.check_content_completion(content.name, content.doctype, course_enrollment.name)
+ else:
+ status = True
+ progress.append({'content': content, 'content_type': content.doctype, 'completed': status})
+ elif content.doctype == 'Quiz':
+ if student:
+ status, score, result = utils.check_quiz_completion(content, course_enrollment.name)
+ else:
+ status = False
+ score = None
+ result = None
+ progress.append({'content': content, 'content_type': content.doctype, 'completed': status, 'score': score, 'result': result})
+
+ return progress
\ No newline at end of file
diff --git a/erpnext/www/test_lms.py b/erpnext/www/test_lms.py
deleted file mode 100644
index e63f4c9..0000000
--- a/erpnext/www/test_lms.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies and Contributors
-# See license.txt
-from __future__ import unicode_literals
-from erpnext.education.doctype.program.test_program import make_program_and_linked_courses
-
-import frappe
-import unittest
-
-class TestLms(unittest.TestCase):
- pass
\ No newline at end of file