diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 42f538df662..0c7daad89f6 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from erpnext.hooks import regional_overrides -__version__ = '9.1.6' +__version__ = '9.1.7' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index 04f7e1be4fa..6856f62d0c6 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -88,7 +88,7 @@ def update_pos_profile_data(doc, pos_profile, company_data): doc.naming_series = pos_profile.get('naming_series') or 'SINV-' doc.letter_head = pos_profile.get('letter_head') or company_data.default_letter_head doc.ignore_pricing_rule = pos_profile.get('ignore_pricing_rule') or 0 - doc.apply_discount_on = pos_profile.get('apply_discount_on') or '' + doc.apply_discount_on = pos_profile.get('apply_discount_on') or 'Grand Total' doc.customer_group = pos_profile.get('customer_group') or get_root('Customer Group') doc.territory = pos_profile.get('territory') or get_root('Territory') doc.terms = frappe.db.get_value('Terms and Conditions', pos_profile.get('tc_name'), 'terms') or doc.terms or '' diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index 57a8a186b96..c442062ab6f 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -84,6 +84,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.get_data_from_server(function () { me.make_control(); me.create_new(); + me.make(); }); }, @@ -382,7 +383,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }, setup: function () { - this.make(); this.set_primary_action(); this.party_field.$input.attr('disabled', false); if(this.selected_row) { @@ -1341,6 +1341,12 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.wrapper.find('input.discount-percentage').on("change", function () { me.frm.doc.additional_discount_percentage = flt($(this).val(), precision("additional_discount_percentage")); + + if(me.frm.doc.additional_discount_percentage && me.frm.doc.discount_amount) { + // Reset discount amount + me.frm.doc.discount_amount = 0; + } + var total = me.frm.doc.grand_total if (me.frm.doc.apply_discount_on == 'Net Total') { @@ -1348,15 +1354,15 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ } me.frm.doc.discount_amount = flt(total * flt(me.frm.doc.additional_discount_percentage) / 100, precision("discount_amount")); - me.wrapper.find('input.discount-amount').val(me.frm.doc.discount_amount) me.refresh(); + me.wrapper.find('input.discount-amount').val(me.frm.doc.discount_amount) }); this.wrapper.find('input.discount-amount').on("change", function () { me.frm.doc.discount_amount = flt($(this).val(), precision("discount_amount")); me.frm.doc.additional_discount_percentage = 0.0; - me.wrapper.find('input.discount-percentage').val(0); me.refresh(); + me.wrapper.find('input.discount-percentage').val(0); }); }, @@ -1517,6 +1523,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ var me = this; this.wrapper.find(".net-total").text(format_currency(me.frm.doc.total, me.frm.doc.currency)); this.wrapper.find(".grand-total").text(format_currency(me.frm.doc.grand_total, me.frm.doc.currency)); + this.wrapper.find('input.discount-percentage').val(this.frm.doc.additional_discount_percentage); + this.wrapper.find('input.discount-amount').val(this.frm.doc.discount_amount); }, set_primary_action: function () { diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js index 6605a651705..5d196874c98 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js @@ -1,7 +1,7 @@ QUnit.module('Buying'); QUnit.test("test: purchase order", function(assert) { - assert.expect(11); + assert.expect(16); let done = assert.async(); frappe.run_serially([ @@ -40,7 +40,6 @@ QUnit.test("test: purchase order", function(assert) { // Get supplier details assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct"); assert.ok(cur_frm.doc.schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 1), "Schedule Date correct"); - assert.ok($('div.control-value.like-disabled-input.for-description').text().includes('Contact 3'), "Contact display correct"); assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Contact email correct"); // Get item details assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item name correct"); @@ -53,7 +52,7 @@ QUnit.test("test: purchase order", function(assert) { assert.ok(cur_frm.doc.items[1].qty == 2, "Quantity correct"); assert.ok(cur_frm.doc.items[1].schedule_date == cur_frm.doc.schedule_date, "Schedule Date correct"); // Calculate total - assert.ok(cur_frm.doc.total == 500, "Total correct"); + assert.ok(cur_frm.doc.total == 700, "Total correct"); // Get terms assert.ok(cur_frm.doc.terms == 'This is a term.', "Terms correct"); }, @@ -70,7 +69,7 @@ QUnit.test("test: purchase order", function(assert) { () => frappe.tests.click_button('Submit'), () => frappe.tests.click_button('Yes'), - () => frappe.timeout(0.3), + () => frappe.timeout(1), () => { assert.ok(cur_frm.doc.status == 'To Receive and Bill', "Submitted successfully"); diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js index a4d68aa946d..1fcfe75bb03 100644 --- a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js +++ b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js @@ -27,6 +27,7 @@ QUnit.test("test: request_for_quotation", function(assert) { {tc_name: 'Test Term 1'} ]); }, + () => frappe.timeout(3), () => { assert.ok(cur_frm.doc.transaction_date == date, "Date correct"); assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct"); @@ -38,7 +39,7 @@ QUnit.test("test: request_for_quotation", function(assert) { assert.ok(cur_frm.doc.message_for_supplier == 'Please supply the specified items at the best possible rates', "Reply correct"); assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Term name correct"); }, - () => frappe.timeout(0.3), + () => frappe.timeout(3), () => cur_frm.print_doc(), () => frappe.timeout(1), () => { @@ -65,7 +66,7 @@ QUnit.test("test: request_for_quotation", function(assert) { assert.ok(cur_frm.doc.docstatus == 1, "Quotation request submitted"); }, () => frappe.click_button('Send Supplier Emails'), - () => frappe.timeout(4), + () => frappe.timeout(6), () => { assert.ok($('div.modal.fade.in > div.modal-dialog > div > div.modal-body.ui-front > div.msgprint').text().includes("Email sent to supplier Test Supplier"), "Send emails working"); }, diff --git a/erpnext/buying/doctype/supplier/test_supplier.js b/erpnext/buying/doctype/supplier/test_supplier.js index 99a5bc616dc..05ea04422dd 100644 --- a/erpnext/buying/doctype/supplier/test_supplier.js +++ b/erpnext/buying/doctype/supplier/test_supplier.js @@ -56,7 +56,8 @@ QUnit.test("test: supplier", function(assert) { () => frappe.click_button('New Contact'), () => { return frappe.tests.set_form_values(cur_frm, [ - {first_name: "Contact 3"} + {first_name: "Contact 3"}, + {email_id: "test@supplier.com"} ]); }, () => cur_frm.save(), diff --git a/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.js deleted file mode 100644 index 7097a6dcb2b..00000000000 --- a/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.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: Supplier Quotation", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('Supplier Quotation', [ - // insert a new Supplier Quotation - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js index 76be06c6fbb..2d2b29cb916 100644 --- a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js +++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js @@ -27,12 +27,13 @@ QUnit.test("test: supplier quotation", function(assert) { {terms: 'This is a term'} ]); }, + () => frappe.timeout(3), () => { // Get Supplier details assert.ok(cur_frm.doc.supplier == 'Test Supplier', "Supplier correct"); assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct"); // Get Contact details - assert.ok(cur_frm.doc.contact_display == 'Contact 3', "Conatct correct"); + assert.ok(cur_frm.doc.contact_person == 'Contact 3-Test Supplier', "Conatct correct"); assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Email correct"); // Get uom assert.ok(cur_frm.doc.items[0].uom == 'Unit', "Multi uom correct"); diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py index 43f625af42a..ec281bb6ef7 100644 --- a/erpnext/config/hr.py +++ b/erpnext/config/hr.py @@ -176,6 +176,10 @@ def get_data(): { "label": _("Training"), "items": [ + { + "type": "doctype", + "name": "Training Program" + }, { "type": "doctype", "name": "Training Event" diff --git a/erpnext/docs/assets/img/human-resources/training_event.png b/erpnext/docs/assets/img/human-resources/training_event.png index 04162eb1e7c..bd1d6dc77a0 100644 Binary files a/erpnext/docs/assets/img/human-resources/training_event.png and b/erpnext/docs/assets/img/human-resources/training_event.png differ diff --git a/erpnext/docs/assets/img/human-resources/training_program.png b/erpnext/docs/assets/img/human-resources/training_program.png new file mode 100644 index 00000000000..97bd2bf7b6d Binary files /dev/null and b/erpnext/docs/assets/img/human-resources/training_program.png differ diff --git a/erpnext/docs/user/manual/en/human-resources/training.md b/erpnext/docs/user/manual/en/human-resources/training.md index 2aa06791f05..4d39bf1a69c 100644 --- a/erpnext/docs/user/manual/en/human-resources/training.md +++ b/erpnext/docs/user/manual/en/human-resources/training.md @@ -1,8 +1,13 @@ # Training +### Training Program + +Create Training Program and schedule Training Events under it. It has a dashboard linked to Training Event to view which event is under the Training Program. + +Employee ### Training Event -Schedule seminars, workshops, conferences etc using Training Event. You can also invite your employees to attend the event using this feature. +Schedule seminars, workshops, conferences etc using Training Event linked to a Training Program. You can also invite your employees to attend the event using this feature. Employee @@ -14,11 +19,11 @@ By default the status of the employee will be 'Open'. Employee -When you submit the Training Event, a notifcation will be sent to the employee notifying that the Training has been scheduled. This is sent via Email Alert "Training Scheduled". You can modifiy this Email Alert to customize the message. +When you submit the Training Event, a notification will be sent to the employee notifying that the Training has been scheduled. This is sent via Email Alert "Training Scheduled". You can modify this Email Alert to customize the message. ### Training Result -After compleation of the training Employee-wise training results can be stored based on the Feedback received from the Trainer. +After completion of the training Employee-wise training results can be stored based on the Feedback received from the Trainer. Employee diff --git a/erpnext/hr/doctype/offer_letter/test_offer_letter.js b/erpnext/hr/doctype/offer_letter/test_offer_letter.js index 20695326129..5b61d64eb53 100644 --- a/erpnext/hr/doctype/offer_letter/test_offer_letter.js +++ b/erpnext/hr/doctype/offer_letter/test_offer_letter.js @@ -27,7 +27,7 @@ QUnit.test("Test: Offer Letter [HR]", function (assert) { ]}, ]); }, - () => frappe.timeout(8), + () => frappe.timeout(12), () => frappe.click_button('Submit'), () => frappe.timeout(2), () => frappe.click_button('Yes'), diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.js b/erpnext/hr/doctype/salary_slip/test_salary_slip.js index a49c973d132..619e5300ca7 100644 --- a/erpnext/hr/doctype/salary_slip/test_salary_slip.js +++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.js @@ -15,7 +15,7 @@ QUnit.test("test salary slip", function(assert) { { employee: employee_name} ]); }, - () => frappe.timeout(1), + () => frappe.timeout(3), () => { // To check if all the calculations are correctly done if(ename === 'Test Employee 1') @@ -43,7 +43,7 @@ QUnit.test("test salary slip", function(assert) { () => salary_slip('Test Employee 1'), () => frappe.timeout(6), () => salary_slip('Test Employee 3'), - () => frappe.timeout(3), + () => frappe.timeout(5), () => done() ]); }); \ No newline at end of file diff --git a/erpnext/hr/doctype/salary_structure/test_salary_structure.js b/erpnext/hr/doctype/salary_structure/test_salary_structure.js index 5e028cfa063..542fa503549 100644 --- a/erpnext/hr/doctype/salary_structure/test_salary_structure.js +++ b/erpnext/hr/doctype/salary_structure/test_salary_structure.js @@ -1,5 +1,5 @@ QUnit.test("test Salary Structure", function(assert) { - assert.expect(6); + assert.expect(7); let done = assert.async(); let employee_name1; @@ -9,6 +9,7 @@ QUnit.test("test Salary Structure", function(assert) { employee_name1 = r.name; } ), + () => frappe.timeout(5), () => frappe.db.get_value('Employee', {'employee_name': "Test Employee 3"}, 'name', (r) => { // Creating Salary Structure for employees); @@ -48,12 +49,14 @@ QUnit.test("test Salary Structure", function(assert) { ]); } ), - () => frappe.timeout(3), + () => frappe.timeout(15), () => { - // To check if all the fields are correctly set - assert.ok(cur_frm.doc.employees[0].employee_name.includes('Test Employee 1') && - cur_frm.doc.employees[1].employee_name.includes('Test Employee 3'), - 'Employee names are correctly set'); + // To check if all the fields are correctly set + assert.ok(cur_frm.doc.employees[0].employee_name=='Test Employee 1', + 'Employee 1 name correctly set'); + + assert.ok(cur_frm.doc.employees[1].employee_name=='Test Employee 3', + 'Employee 2 name correctly set'); assert.ok(cur_frm.doc.employees[0].base==25000, 'Base value for first employee is correctly set'); diff --git a/erpnext/hr/doctype/training_event/test_training_event.py b/erpnext/hr/doctype/training_event/test_training_event.py index 03416ee1f43..57123e304f5 100644 --- a/erpnext/hr/doctype/training_event/test_training_event.py +++ b/erpnext/hr/doctype/training_event/test_training_event.py @@ -5,8 +5,38 @@ from __future__ import unicode_literals import frappe import unittest - -# test_records = frappe.get_test_records('Training Event') +from frappe.utils import today, add_days +from erpnext.hr.doctype.salary_structure.test_salary_structure import make_employee class TestTrainingEvent(unittest.TestCase): - pass + def setUp(self): + create_training_program("Basic Training") + self.employee = make_employee("robert_loan@trainig.com") + self.employee2 = make_employee("suzie.tan@trainig.com") + + def test_create_training_event(self): + if not frappe.db.get_value("Training Event", "Basic Training Event"): + frappe.get_doc({ + "doctype": "Training Event", + "event_name": "Basic Training Event", + "training_program": "Basic Training", + "location": "Union Square", + "start_time": add_days(today(), 5), + "end_time": add_days(today(), 6), + "introduction": "Welcome to the Basic Training Event", + "employees": get_attendees(self.employee, self.employee2) + }).insert() + +def create_training_program(training_program): + if not frappe.db.get_value("Training Program", training_program): + frappe.get_doc({ + "doctype": "Training Program", + "training_program": training_program, + "description": training_program + }).insert() + +def get_attendees(employee, employee2): + return [ + {"employee": employee}, + {"employee": employee2} + ] \ No newline at end of file diff --git a/erpnext/hr/doctype/training_event/training_event.json b/erpnext/hr/doctype/training_event/training_event.json index cb8518bf9ba..4b812a992e0 100644 --- a/erpnext/hr/doctype/training_event/training_event.json +++ b/erpnext/hr/doctype/training_event/training_event.json @@ -42,6 +42,37 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "training_program", + "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": "Training Program", + "length": 0, + "no_copy": 0, + "options": "Training Program", + "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, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 1, @@ -778,7 +809,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-10-06 10:59:09.217283", + "modified": "2017-10-23 06:13:29.065781", "modified_by": "Administrator", "module": "HR", "name": "Training Event", @@ -806,7 +837,7 @@ "write": 1 } ], - "quick_entry": 1, + "quick_entry": 0, "read_only": 0, "read_only_onload": 0, "search_fields": "event_name", diff --git a/erpnext/hr/doctype/training_program/__init__.py b/erpnext/hr/doctype/training_program/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.js b/erpnext/hr/doctype/training_program/test_training_program.js similarity index 66% rename from erpnext/buying/doctype/purchase_order/test_purchase_order.js rename to erpnext/hr/doctype/training_program/test_training_program.js index e9db270b4fd..3a62b2fa221 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.js +++ b/erpnext/hr/doctype/training_program/test_training_program.js @@ -2,15 +2,15 @@ // rename this file from _test_[name] to test_[name] to activate // and remove above this line -QUnit.test("test: Purchase Order", function (assert) { +QUnit.test("test: Training Program", function (assert) { let done = assert.async(); // number of asserts assert.expect(1); - frappe.run_serially('Purchase Order', [ - // insert a new Purchase Order - () => frappe.tests.make([ + frappe.run_serially([ + // insert a new Training Program + () => frappe.tests.make('Training Program', [ // values to be set {key: 'value'} ]), diff --git a/erpnext/hr/doctype/training_program/test_training_program.py b/erpnext/hr/doctype/training_program/test_training_program.py new file mode 100644 index 00000000000..9d5b28616b1 --- /dev/null +++ b/erpnext/hr/doctype/training_program/test_training_program.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +class TestTrainingProgram(unittest.TestCase): + pass diff --git a/erpnext/hr/doctype/training_program/training_program.js b/erpnext/hr/doctype/training_program/training_program.js new file mode 100644 index 00000000000..7d85cab59dc --- /dev/null +++ b/erpnext/hr/doctype/training_program/training_program.js @@ -0,0 +1,5 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Training Program', { +}); \ No newline at end of file diff --git a/erpnext/hr/doctype/training_program/training_program.json b/erpnext/hr/doctype/training_program/training_program.json new file mode 100644 index 00000000000..d9b33d5de7d --- /dev/null +++ b/erpnext/hr/doctype/training_program/training_program.json @@ -0,0 +1,454 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "field:training_program", + "beta": 0, + "creation": "2017-10-11 04:43:17.230065", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "training_program", + "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": "Training Program", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 1, + "bold": 1, + "collapsible": 0, + "columns": 0, + "default": "Scheduled", + "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": "Scheduled\nCompleted\nCancelled", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "company", + "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": "Company", + "length": 0, + "no_copy": 0, + "options": "Company", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 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, + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "trainer_name", + "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": "Trainer 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": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "trainer_email", + "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": "Trainer Email", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_8", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "supplier", + "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": "Supplier", + "length": 0, + "no_copy": 0, + "options": "Supplier", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "contact_number", + "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": "Contact Number", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 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, + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 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, + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "amended_from", + "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": "Amended From", + "length": 0, + "no_copy": 1, + "options": "Training Program", + "permlevel": 0, + "print_hide": 1, + "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, + "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": "2017-10-16 05:34:23.055153", + "modified_by": "Administrator", + "module": "HR", + "name": "Training Program", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 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": "HR 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": 1, + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "training_program", + "track_changes": 1, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/hr/doctype/training_program/training_program.py b/erpnext/hr/doctype/training_program/training_program.py new file mode 100644 index 00000000000..7a3720b66b6 --- /dev/null +++ b/erpnext/hr/doctype/training_program/training_program.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +from frappe.model.document import Document + +class TrainingProgram(Document): + pass diff --git a/erpnext/hr/doctype/training_program/training_program_dashboard.py b/erpnext/hr/doctype/training_program/training_program_dashboard.py new file mode 100644 index 00000000000..b5d9f19a26c --- /dev/null +++ b/erpnext/hr/doctype/training_program/training_program_dashboard.py @@ -0,0 +1,12 @@ +from frappe import _ + +def get_data(): + return { + 'fieldname': 'training_program', + 'transactions': [ + { + 'label': _('Training Event'), + 'items': ['Training Event'] + }, + ] + } \ No newline at end of file diff --git a/erpnext/hr/email_alert/training_scheduled/training_scheduled.json b/erpnext/hr/email_alert/training_scheduled/training_scheduled.json index e1631f86839..0782f0cfc11 100644 --- a/erpnext/hr/email_alert/training_scheduled/training_scheduled.json +++ b/erpnext/hr/email_alert/training_scheduled/training_scheduled.json @@ -10,8 +10,8 @@ "idx": 0, "is_standard": 1, "message": "

{{_(\"Training Event\")}}

\n\n

{{ doc.introduction }}

\n\n

{{_(\"Details\")}}

\n{{_(\"Event Name\")}}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}\n
{{_(\"Event Location\")}}: {{ doc.location }}\n
{{_(\"Start Time\")}}: {{ doc.start_time }}\n
{{_(\"End Time\")}}: {{ doc.end_time }}\n", - "modified": "2017-08-13 22:49:42.338881", - "modified_by": "Administrator", + "modified": "2017-08-13 22:49:42.338881", + "modified_by": "Administrator", "module": "HR", "name": "Training Scheduled", "owner": "Administrator", diff --git a/erpnext/manufacturing/doctype/operation/test_operation.js b/erpnext/manufacturing/doctype/operation/test_operation.js index 5aafe42ab9e..42553ce721f 100644 --- a/erpnext/manufacturing/doctype/operation/test_operation.js +++ b/erpnext/manufacturing/doctype/operation/test_operation.js @@ -14,7 +14,7 @@ QUnit.test("test: operation", function (assert) { ] ); }, - () => frappe.timeout(1), + () => frappe.timeout(3), () => { assert.ok(cur_frm.docname.includes('Assemble Keyboard'), 'Assemble Keyboard created successfully'); @@ -31,7 +31,7 @@ QUnit.test("test: operation", function (assert) { ] ); }, - () => frappe.timeout(1), + () => frappe.timeout(3), // Create a CPU operation () => { @@ -42,7 +42,7 @@ QUnit.test("test: operation", function (assert) { ] ); }, - () => frappe.timeout(1), + () => frappe.timeout(3), () => done() ]); diff --git a/erpnext/patches/v8_0/disable_instructor_role.py b/erpnext/patches/v8_0/disable_instructor_role.py index 94ebd9cac6b..4ba78d172cb 100644 --- a/erpnext/patches/v8_0/disable_instructor_role.py +++ b/erpnext/patches/v8_0/disable_instructor_role.py @@ -12,6 +12,7 @@ def execute(): domains = frappe.db.sql_list("select domain from tabCompany") if "Education" not in domains: - role = frappe.get_doc("Role", "Instructor") - role.disabled = 1 - role.save(ignore_permissions=True) \ No newline at end of file + if frappe.db.exists("Role", "Instructor"): + role = frappe.get_doc("Role", "Instructor") + role.disabled = 1 + role.save(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/restaurant/doctype/restaurant/test_restaurant.js b/erpnext/restaurant/doctype/restaurant/test_restaurant.js index 1cc7c7f069a..f4a13432e25 100644 --- a/erpnext/restaurant/doctype/restaurant/test_restaurant.js +++ b/erpnext/restaurant/doctype/restaurant/test_restaurant.js @@ -15,9 +15,11 @@ QUnit.test("test: Restaurant", function (assert) { // values to be set {__newname: 'Test Restaurant 1'}, {company: 'Test Company'}, - {invoice_series_prefix: 'Test-Rest-1-Inv-'} + {invoice_series_prefix: 'Test-Rest-1-Inv-'}, + {default_customer: 'Test Customer 1'} ]) }, + () => frappe.timeout(3), () => { assert.equal(cur_frm.doc.company, 'Test Company'); }, @@ -26,9 +28,11 @@ QUnit.test("test: Restaurant", function (assert) { // values to be set {__newname: 'Test Restaurant 2'}, {company: 'Test Company'}, - {invoice_series_prefix: 'Test-Rest-3-Inv-'} + {invoice_series_prefix: 'Test-Rest-3-Inv-'}, + {default_customer: 'Test Customer 2'} ]); }, + () => frappe.timeout(3), () => { assert.equal(cur_frm.doc.company, 'Test Company'); }, diff --git a/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js b/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js index 25057d83340..f5ab9f09012 100644 --- a/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js +++ b/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js @@ -16,7 +16,7 @@ QUnit.test("test: Restaurant Menu", function (assert) { {item_group: "Products"}, {is_stock_item: 1}, ], - "Test Product 3": [ + "Food Item 3": [ {item_code: "Food Item 3"}, {item_group: "Products"}, {is_stock_item: 1}, @@ -50,6 +50,7 @@ QUnit.test("test: Restaurant Menu", function (assert) { ]} ]); }, + () => frappe.timeout(2), () => { return frappe.tests.make("Restaurant Menu", [ {__newname: 'Restaurant Menu 2'}, @@ -66,6 +67,7 @@ QUnit.test("test: Restaurant Menu", function (assert) { ]} ]); }, + () => frappe.timeout(2), () => frappe.set_route('Form', 'Restaurant', 'Test Restaurant 1'), () => cur_frm.set_value('active_menu', 'Restaurant Menu 1'), () => cur_frm.save(), diff --git a/erpnext/schools/doctype/student_admission/test_student_admission.js b/erpnext/schools/doctype/student_admission/test_student_admission.js index 3e997caeb00..767f237f959 100644 --- a/erpnext/schools/doctype/student_admission/test_student_admission.js +++ b/erpnext/schools/doctype/student_admission/test_student_admission.js @@ -2,7 +2,7 @@ QUnit.module('schools'); QUnit.test('Test: Student Admission', function(assert) { - assert.expect(9); + assert.expect(10); let done = assert.async(); frappe.run_serially([ () => { diff --git a/erpnext/schools/doctype/student_applicant/student_applicant.py b/erpnext/schools/doctype/student_applicant/student_applicant.py index 7fa44a65e65..465b4e474ab 100644 --- a/erpnext/schools/doctype/student_applicant/student_applicant.py +++ b/erpnext/schools/doctype/student_applicant/student_applicant.py @@ -41,9 +41,14 @@ class StudentApplicant(Document): def validation_from_student_admission(self): student_admission = get_student_admission_data(self.student_admission, self.program) if student_admission: - if not (getdate(student_admission.minimum_age) >= getdate(self.date_of_birth) >= - getdate(student_admission.maximum_age)): - frappe.throw(_("Not eligible for the admission in this program as per DOB")) + if (( + student_admission.minimum_age + and getdate(student_admission.minimum_age) > getdate(self.date_of_birth) + ) or ( + student_admission.maximum_age + and getdate(student_admission.maximum_age) < getdate(self.date_of_birth) + )): + frappe.throw(_("Not eligible for the admission in this program as per DOB")) def on_payment_authorized(self, *args, **kwargs): self.db_set('paid', 1) diff --git a/erpnext/schools/doctype/student_group/test_student_group.js b/erpnext/schools/doctype/student_group/test_student_group.js index 634ad18254d..bee5067d9b8 100644 --- a/erpnext/schools/doctype/student_group/test_student_group.js +++ b/erpnext/schools/doctype/student_group/test_student_group.js @@ -4,15 +4,10 @@ QUnit.module('schools'); QUnit.test('Test: Student Group', function(assert){ assert.expect(2); let done = assert.async(); - let instructor_code; let group_based_on = ["test-batch-wise-group", "test-course-wise-group"]; let tasks = []; frappe.run_serially([ - // Saving Instructor code beforehand - () => frappe.db.get_value('Instructor', {'instructor_name': 'Instructor 1'}, 'name'), - (instructor) => {instructor_code = instructor.message.name;}, - // Creating a Batch and Course based group () => { return frappe.tests.make('Student Group', [ @@ -22,12 +17,7 @@ QUnit.test('Test: Student Group', function(assert){ {group_based_on: 'Batch'}, {student_group_name: group_based_on[0]}, {max_strength: 10}, - {batch: 'A'}, - {instructors: [ - [ - {instructor: instructor_code} - ] - ]} + {batch: 'A'} ]); }, () => { @@ -40,11 +30,6 @@ QUnit.test('Test: Student Group', function(assert){ {max_strength: 10}, {batch: 'A'}, {course: 'Test_Sub'}, - {instructors: [ - [ - {instructor: instructor_code} - ] - ]} ]); }, diff --git a/erpnext/setup/doctype/customer_group/customer_group.py b/erpnext/setup/doctype/customer_group/customer_group.py index 0f1ee818637..7472c51affd 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.py +++ b/erpnext/setup/doctype/customer_group/customer_group.py @@ -17,11 +17,11 @@ class CustomerGroup(NestedSet): def validate_name_with_customer(self): if frappe.db.exists("Customer", self.name): - frappe.msgprint(_("An Customer exists with same name"), raise_exception=1) + frappe.msgprint(_("A customer with the same name already exists"), raise_exception=1) def get_parent_customer_groups(customer_group): lft, rgt = frappe.db.get_value("Customer Group", customer_group, ['lft', 'rgt']) return frappe.db.sql("""select name from `tabCustomer Group` where lft <= %s and rgt >= %s - order by lft asc""", (lft, rgt), as_dict=True) \ No newline at end of file + order by lft asc""", (lft, rgt), as_dict=True) diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 4b3c2c503bb..38c138db0ae 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -131,6 +131,6 @@ erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_i erpnext/accounts/doctype/payment_entry/tests/test_payment_against_invoice.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_last_purchase_rate.js erpnext/restaurant/doctype/restaurant/test_restaurant.js -erpnext/restaurant/doctype/test_restaurant_table/test_restaurant_table.js +erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.js erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.js