diff --git a/.travis.yml b/.travis.yml index a70062fea3..92c15e0319 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,4 +58,5 @@ script: - bench reinstall --yes - bench execute erpnext.setup.setup_wizard.utils.complete - bench execute erpnext.setup.utils.enable_all_roles_and_domains + - bench --verbose run-setup-wizard-ui-test - bench run-ui-tests --app erpnext diff --git a/erpnext/__init__.py b/erpnext/__init__.py index cf6ca02e7f..70ae35a556 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from erpnext.hooks import regional_overrides -__version__ = '8.10.0' +__version__ = '8.10.2' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py index adb7bc1338..1e694e7e3a 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py @@ -78,6 +78,7 @@ def get_chart(chart_template, existing_company=None): for folder in folders: path = os.path.join(os.path.dirname(__file__), folder) for fname in os.listdir(path): + fname = frappe.as_unicode(fname) if fname.endswith(".json"): with open(os.path.join(path, fname), "r") as f: chart = f.read() @@ -105,6 +106,7 @@ def get_charts_for_country(country): path = os.path.join(os.path.dirname(__file__), folder) for fname in os.listdir(path): + fname = frappe.as_unicode(fname) if (fname.startswith(country_code) or fname.startswith(country)) and fname.endswith(".json"): with open(os.path.join(path, fname), "r") as f: _get_chart_name(f.read()) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_général.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json similarity index 99% rename from erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_général.json rename to erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json index d7b464a381..f6015f3744 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_général.json +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json @@ -1607,4 +1607,4 @@ "root_type": "Income" } } -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/account/test_account.js b/erpnext/accounts/doctype/account/test_account.js index 7b23ef01dd..039e33e011 100644 --- a/erpnext/accounts/doctype/account/test_account.js +++ b/erpnext/accounts/doctype/account/test_account.js @@ -5,7 +5,9 @@ QUnit.test("test account", function(assert) { let done = assert.async(); frappe.run_serially([ () => frappe.set_route('Tree', 'Account'), + () => frappe.timeout(3), () => frappe.click_button('Expand All'), + () => frappe.timeout(1), () => frappe.click_link('Debtors'), () => frappe.click_button('Edit'), () => frappe.timeout(1), diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json index 49af59b388..8860b092e0 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, "autoname": "field:title", @@ -12,6 +13,7 @@ "editable_grid": 0, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -40,6 +42,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -69,6 +72,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -99,6 +103,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -129,6 +134,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -159,6 +165,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -189,6 +196,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -217,6 +225,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -247,6 +256,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -275,6 +285,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -303,6 +314,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -331,6 +343,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -359,6 +372,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -387,6 +401,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -417,6 +432,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -447,6 +463,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -477,6 +494,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -507,6 +525,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -537,6 +556,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -567,6 +587,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -597,6 +618,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -627,6 +649,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -655,6 +678,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -683,6 +707,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -711,6 +736,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -739,6 +765,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -767,6 +794,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -796,6 +824,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -824,6 +853,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -851,6 +881,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -880,6 +911,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -910,6 +942,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -941,6 +974,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -969,6 +1003,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1000,6 +1035,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1028,6 +1064,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1058,6 +1095,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1085,13 +1123,14 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, "depends_on": "eval:doc.price_or_discount==\"Price\"", "fieldname": "price", - "fieldtype": "Float", + "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -1114,6 +1153,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1143,6 +1183,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1173,6 +1214,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1202,6 +1244,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1230,18 +1273,18 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "icon": "fa fa-gift", "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-17 16:21:28.446208", + "modified": "2017-08-31 16:34:41.614743", "modified_by": "Administrator", "module": "Accounts", "name": "Pricing Rule", diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index f36fdf7907..2b3459ad27 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -320,8 +320,7 @@ def make_invoice(doc_list={}, email_queue_list={}, customers_list={}): si_doc.set_posting_time = 1 si_doc.customer = get_customer_id(doc) si_doc.due_date = doc.get('posting_date') - submit_invoice(si_doc, name, doc) - name_list.append(name) + name_list = submit_invoice(si_doc, name, doc, name_list) else: name_list.append(name) @@ -475,19 +474,29 @@ def validate_item(doc): frappe.db.commit() -def submit_invoice(si_doc, name, doc): +def submit_invoice(si_doc, name, doc, name_list): try: si_doc.insert() si_doc.submit() frappe.db.commit() + name_list.append(name) except Exception as e: if frappe.message_log: frappe.message_log.pop() frappe.db.rollback() - save_invoice(e, si_doc, name) + frappe.log_error(frappe.get_traceback()) + name_list = save_invoice(e, si_doc, name, name_list) -def save_invoice(e, si_doc, name): - if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}): - si_doc.docstatus = 0 - si_doc.flags.ignore_mandatory = True - si_doc.due_date = si_doc.posting_date - si_doc.insert() + return name_list + +def save_invoice(e, si_doc, name, name_list): + try: + if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}): + si_doc.docstatus = 0 + si_doc.flags.ignore_mandatory = True + si_doc.due_date = si_doc.posting_date + si_doc.insert() + name_list.append(name) + except Exception: + frappe.log_error(frappe.get_traceback()) + + return name_list diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index e0a453c5c9..2b0daba9bc 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1167,8 +1167,15 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount"))) def test_multiple_uom_in_selling(self): - si = frappe.copy_doc(test_records[1]) + frappe.db.sql("""delete from `tabItem Price` + where price_list='_Test Price List' and item_code='_Test Item'""") + item_price = frappe.new_doc("Item Price") + item_price.price_list = "_Test Price List" + item_price.item_code = "_Test Item" + item_price.price_list_rate = 100 + item_price.insert() + si = frappe.copy_doc(test_records[1]) si.items[0].uom = "_Test UOM 1" si.items[0].conversion_factor = None si.items[0].price_list_rate = None diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_item.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_item.js new file mode 100644 index 0000000000..60059841cd --- /dev/null +++ b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_item.js @@ -0,0 +1,45 @@ +QUnit.module('Sales Invoice'); + +QUnit.test("test sales Invoice with serialize item", function(assert) { + assert.expect(5); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Sales Invoice', [ + {customer: 'Test Customer 1'}, + {items: [ + [ + {'qty': 2}, + {'item_code': 'Test Product 4'}, + ] + ]}, + {update_stock:1}, + {customer_address: 'Test1-Billing'}, + {shipping_address_name: 'Test1-Shipping'}, + {contact_person: 'Contact 1-Test Customer 1'}, + {taxes_and_charges: 'TEST In State GST'}, + {tc_name: 'Test Term 1'}, + {terms: 'This is Test'} + ]); + }, + () => cur_frm.save(), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct"); + // get tax details + assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct"); + // get tax account head details + assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct"); + // get batch number + assert.ok(cur_frm.doc.items[0].batch_no=='TEST-BATCH-001', " Batch Details correct"); + // grand_total Calculated + assert.ok(cur_frm.doc.grand_total==218, "Grad Total correct"); + + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index 3d5d5f4d90..2f425248a1 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -435,11 +435,16 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }); this.serach_item.make_input(); - this.serach_item.$input.on("keyup", function () { - setTimeout(function () { - me.items = me.get_items(); - me.make_item_list(); - }, 1000); + + this.serach_item.$input.on("keypress", function (event) { + + clearTimeout(me.last_search_timeout); + me.last_search_timeout = setTimeout(() => { + if((me.serach_item.$input.val() != "") || (event.which == 13)) { + me.items = me.get_items(); + me.make_item_list(); + } + }, 400); }); this.search_item_group = this.wrapper.find('.search-item-group'); @@ -736,14 +741,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ input = input.toLowerCase(); item = this.get_item(item.value); - var searchtext = - Object.keys(item) - .filter(key => ['customer_name', 'customer_group', 'value', 'label', 'email_id', 'phone', 'mobile_no'].includes(key)) - .map(key => item[key]) - .join(" ") - .toLowerCase(); - - return searchtext.includes(input) + return item.searchtext.includes(input) }, item: function (item, input) { var d = this.get_item(item.value); @@ -817,7 +815,11 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ territory: c.territory, phone: contact ? contact["phone"] : '', mobile_no: contact ? contact["mobile_no"] : '', - email_id: contact ? contact["email_id"] : '' + email_id: contact ? contact["email_id"] : '', + searchtext: ['customer_name', 'customer_group', 'value', + 'label', 'email_id', 'phone', 'mobile_no'] + .map(key => c[key]).join(' ') + .toLowerCase() } }); diff --git a/erpnext/docs/assets/old_images/__init__.py b/erpnext/accounts/print_format/gst_pos_invoice/__init__.py similarity index 100% rename from erpnext/docs/assets/old_images/__init__.py rename to erpnext/accounts/print_format/gst_pos_invoice/__init__.py diff --git a/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json b/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json new file mode 100644 index 0000000000..051a1238d9 --- /dev/null +++ b/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json @@ -0,0 +1,22 @@ +{ + "align_labels_left": 0, + "creation": "2017-08-08 12:33:04.773099", + "custom_format": 1, + "disabled": 0, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype": "Print Format", + "font": "Default", + "html": "\n\n

\n\t{{ doc.company }}
\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"
\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t{{ _(\"GSTIN\") }}:{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"
GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t
\n\t{{ doc.select_print_heading or _(\"Invoice\") }}
\n

\n

\n\t{{ _(\"Receipt No\") }}: {{ doc.name }}
\n\t{{ _(\"Date\") }}: {{ doc.get_formatted(\"posting_date\") }}
\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"
\", \" \") %}\n\t\t{{ _(\"Customer\") }}:
\n\t\t{{ doc.customer_name }}
\n\t\t{{ customer_address }}\n\t{% endif %}\n

\n\n
\n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n\t\t{%- for item in doc.items -%}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{%- endfor -%}\n\t\n
{{ _(\"Item\") }}{{ _(\"Qty\") }}{{ _(\"Amount\") }}
\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t
{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t
{{ _(\"HSN/SAC\") }}: {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t
{{ _(\"Serial No\") }}: {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t
{{ item.qty }}
@ {{ item.rate }}
{{ item.get_formatted(\"amount\") }}
\n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{%- for row in doc.taxes -%}\n\t\t{%- if not row.included_in_print_rate -%}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{%- endif -%}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n
\n\t\t\t\t{{ _(\"Net Total\") }}\n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"net_total\") }}\n\t\t\t
\n\t\t\t\t{{ row.description }}\n\t\t\t\n\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t
\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t
\n\t\t\t\t{{ _(\"Grand Total\") }}\n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t
\n

Tax Breakup:

\n
\n\t{{ doc.other_charges_calculation }}\n
\n

{{ doc.terms or \"\" }}

\n

{{ _(\"Thank you, please visit again.\") }}

", + "idx": 0, + "line_breaks": 0, + "modified": "2017-08-29 15:54:19.467642", + "modified_by": "Administrator", + "module": "Accounts", + "name": "GST POS Invoice", + "owner": "Administrator", + "print_format_builder": 0, + "print_format_type": "Server", + "show_section_headings": 0, + "standard": "Yes" +} \ No newline at end of file diff --git a/erpnext/docs/assets/img/articles/$SGrab_253.png b/erpnext/docs/assets/img/articles/$SGrab_253.png deleted file mode 100644 index 69649253ed..0000000000 Binary files a/erpnext/docs/assets/img/articles/$SGrab_253.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/$SGrab_254.png b/erpnext/docs/assets/img/articles/$SGrab_254.png deleted file mode 100644 index 7b2ea780fe..0000000000 Binary files a/erpnext/docs/assets/img/articles/$SGrab_254.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/$SGrab_256.png b/erpnext/docs/assets/img/articles/$SGrab_256.png deleted file mode 100644 index 1fabda35fc..0000000000 Binary files a/erpnext/docs/assets/img/articles/$SGrab_256.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/$SGrab_306.png b/erpnext/docs/assets/img/articles/$SGrab_306.png deleted file mode 100644 index ebbb00764a..0000000000 Binary files a/erpnext/docs/assets/img/articles/$SGrab_306.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/$SGrab_307.png b/erpnext/docs/assets/img/articles/$SGrab_307.png deleted file mode 100644 index f3d1ee1e4a..0000000000 Binary files a/erpnext/docs/assets/img/articles/$SGrab_307.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/$SGrab_431.png b/erpnext/docs/assets/img/articles/$SGrab_431.png deleted file mode 100644 index ae79a3ef63..0000000000 Binary files a/erpnext/docs/assets/img/articles/$SGrab_431.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/$SGrab_432.png b/erpnext/docs/assets/img/articles/$SGrab_432.png deleted file mode 100644 index cc49d855d3..0000000000 Binary files a/erpnext/docs/assets/img/articles/$SGrab_432.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/SGrab_282.png b/erpnext/docs/assets/img/articles/SGrab_282.png deleted file mode 100644 index 3fb138a3c7..0000000000 Binary files a/erpnext/docs/assets/img/articles/SGrab_282.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/SGrab_283.png b/erpnext/docs/assets/img/articles/SGrab_283.png deleted file mode 100644 index d726339dff..0000000000 Binary files a/erpnext/docs/assets/img/articles/SGrab_283.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/Screen Shot 2015-02-19 at 5.28.57 pm.png b/erpnext/docs/assets/img/articles/Screen Shot 2015-02-19 at 5.28.57 pm.png deleted file mode 100644 index 8467e6dc54..0000000000 Binary files a/erpnext/docs/assets/img/articles/Screen Shot 2015-02-19 at 5.28.57 pm.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/Screen Shot 2015-04-02 at 3.26.51 pm.png b/erpnext/docs/assets/img/articles/Screen Shot 2015-04-02 at 3.26.51 pm.png deleted file mode 100644 index ac32083b43..0000000000 Binary files a/erpnext/docs/assets/img/articles/Screen Shot 2015-04-02 at 3.26.51 pm.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/Screen Shot 2015-04-09 at 1.37.38 pm.png b/erpnext/docs/assets/img/articles/Screen Shot 2015-04-09 at 1.37.38 pm.png deleted file mode 100644 index 46c2047114..0000000000 Binary files a/erpnext/docs/assets/img/articles/Screen Shot 2015-04-09 at 1.37.38 pm.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/brand-logo.gif b/erpnext/docs/assets/img/articles/brand-logo.gif new file mode 100644 index 0000000000..99a10d3b34 Binary files /dev/null and b/erpnext/docs/assets/img/articles/brand-logo.gif differ diff --git a/erpnext/docs/assets/img/articles/capacity-1.png b/erpnext/docs/assets/img/articles/capacity-1.png new file mode 100644 index 0000000000..b6879959c7 Binary files /dev/null and b/erpnext/docs/assets/img/articles/capacity-1.png differ diff --git a/erpnext/docs/assets/img/articles/capacity-2.png b/erpnext/docs/assets/img/articles/capacity-2.png new file mode 100644 index 0000000000..9995b6c60c Binary files /dev/null and b/erpnext/docs/assets/img/articles/capacity-2.png differ diff --git a/erpnext/docs/assets/img/articles/capacity-3.png b/erpnext/docs/assets/img/articles/capacity-3.png new file mode 100644 index 0000000000..d074eb015d Binary files /dev/null and b/erpnext/docs/assets/img/articles/capacity-3.png differ diff --git a/erpnext/docs/assets/img/articles/child-1.png b/erpnext/docs/assets/img/articles/child-1.png new file mode 100644 index 0000000000..fb19e26835 Binary files /dev/null and b/erpnext/docs/assets/img/articles/child-1.png differ diff --git a/erpnext/docs/assets/img/articles/child-2.png b/erpnext/docs/assets/img/articles/child-2.png new file mode 100644 index 0000000000..2141272e39 Binary files /dev/null and b/erpnext/docs/assets/img/articles/child-2.png differ diff --git a/erpnext/docs/assets/img/articles/child-3.png b/erpnext/docs/assets/img/articles/child-3.png new file mode 100644 index 0000000000..a3667aa727 Binary files /dev/null and b/erpnext/docs/assets/img/articles/child-3.png differ diff --git a/erpnext/docs/assets/img/articles/child-4.gif b/erpnext/docs/assets/img/articles/child-4.gif new file mode 100644 index 0000000000..fab4ba7e93 Binary files /dev/null and b/erpnext/docs/assets/img/articles/child-4.gif differ diff --git a/erpnext/docs/assets/img/articles/child-5.png b/erpnext/docs/assets/img/articles/child-5.png new file mode 100644 index 0000000000..6990021286 Binary files /dev/null and b/erpnext/docs/assets/img/articles/child-5.png differ diff --git a/erpnext/docs/assets/img/articles/child-6.png b/erpnext/docs/assets/img/articles/child-6.png new file mode 100644 index 0000000000..d65498691c Binary files /dev/null and b/erpnext/docs/assets/img/articles/child-6.png differ diff --git a/erpnext/docs/assets/img/articles/common-receivable.png b/erpnext/docs/assets/img/articles/common-receivable.png new file mode 100644 index 0000000000..33e92c1a76 Binary files /dev/null and b/erpnext/docs/assets/img/articles/common-receivable.png differ diff --git a/erpnext/docs/assets/img/articles/download-backup-1.png b/erpnext/docs/assets/img/articles/download-backup-1.png new file mode 100644 index 0000000000..93597f453f Binary files /dev/null and b/erpnext/docs/assets/img/articles/download-backup-1.png differ diff --git a/erpnext/docs/assets/img/articles/download-backup-2.gif b/erpnext/docs/assets/img/articles/download-backup-2.gif new file mode 100644 index 0000000000..4109dff018 Binary files /dev/null and b/erpnext/docs/assets/img/articles/download-backup-2.gif differ diff --git a/erpnext/docs/assets/img/articles/email-error.png b/erpnext/docs/assets/img/articles/email-error.png new file mode 100644 index 0000000000..e8c5d73dc3 Binary files /dev/null and b/erpnext/docs/assets/img/articles/email-error.png differ diff --git a/erpnext/docs/assets/img/articles/email-setup-error.png b/erpnext/docs/assets/img/articles/email-setup-error.png new file mode 100644 index 0000000000..e8c5d73dc3 Binary files /dev/null and b/erpnext/docs/assets/img/articles/email-setup-error.png differ diff --git a/erpnext/docs/assets/img/articles/fetching-1.png b/erpnext/docs/assets/img/articles/fetching-1.png new file mode 100644 index 0000000000..fcf3fcbac2 Binary files /dev/null and b/erpnext/docs/assets/img/articles/fetching-1.png differ diff --git a/erpnext/docs/assets/img/articles/fetching-2.png b/erpnext/docs/assets/img/articles/fetching-2.png new file mode 100644 index 0000000000..c5594d56f4 Binary files /dev/null and b/erpnext/docs/assets/img/articles/fetching-2.png differ diff --git a/erpnext/docs/assets/img/articles/fetching-3.gif b/erpnext/docs/assets/img/articles/fetching-3.gif new file mode 100644 index 0000000000..5deea3e5f8 Binary files /dev/null and b/erpnext/docs/assets/img/articles/fetching-3.gif differ diff --git a/erpnext/docs/assets/img/articles/hr-working-days.png b/erpnext/docs/assets/img/articles/hr-working-days.png new file mode 100644 index 0000000000..5857164615 Binary files /dev/null and b/erpnext/docs/assets/img/articles/hr-working-days.png differ diff --git a/erpnext/docs/assets/img/articles/item-valuation-1.png b/erpnext/docs/assets/img/articles/item-valuation-1.png new file mode 100644 index 0000000000..16bde1d120 Binary files /dev/null and b/erpnext/docs/assets/img/articles/item-valuation-1.png differ diff --git a/erpnext/docs/assets/img/articles/item-valuation-2.png b/erpnext/docs/assets/img/articles/item-valuation-2.png new file mode 100644 index 0000000000..cc8b8442f3 Binary files /dev/null and b/erpnext/docs/assets/img/articles/item-valuation-2.png differ diff --git a/erpnext/docs/assets/img/articles/purchase-invoice-account-type.png b/erpnext/docs/assets/img/articles/purchase-invoice-account-type.png new file mode 100644 index 0000000000..f268fd7a55 Binary files /dev/null and b/erpnext/docs/assets/img/articles/purchase-invoice-account-type.png differ diff --git a/erpnext/docs/assets/img/articles/purchase-return.gif b/erpnext/docs/assets/img/articles/purchase-return.gif new file mode 100644 index 0000000000..de5f18cf33 Binary files /dev/null and b/erpnext/docs/assets/img/articles/purchase-return.gif differ diff --git a/erpnext/docs/assets/img/articles/report-header-1.png b/erpnext/docs/assets/img/articles/report-header-1.png new file mode 100644 index 0000000000..848c3018bb Binary files /dev/null and b/erpnext/docs/assets/img/articles/report-header-1.png differ diff --git a/erpnext/docs/assets/img/articles/report-header-2.png b/erpnext/docs/assets/img/articles/report-header-2.png new file mode 100644 index 0000000000..47d86958be Binary files /dev/null and b/erpnext/docs/assets/img/articles/report-header-2.png differ diff --git a/erpnext/docs/assets/img/articles/report-permission-1.png b/erpnext/docs/assets/img/articles/report-permission-1.png new file mode 100644 index 0000000000..08c4f5a59b Binary files /dev/null and b/erpnext/docs/assets/img/articles/report-permission-1.png differ diff --git a/erpnext/docs/assets/img/articles/report-permission-2.png b/erpnext/docs/assets/img/articles/report-permission-2.png new file mode 100644 index 0000000000..5e5ef17cf7 Binary files /dev/null and b/erpnext/docs/assets/img/articles/report-permission-2.png differ diff --git a/erpnext/docs/assets/img/articles/role-deskperm.png b/erpnext/docs/assets/img/articles/role-deskperm.png new file mode 100644 index 0000000000..ef4a4d87f9 Binary files /dev/null and b/erpnext/docs/assets/img/articles/role-deskperm.png differ diff --git a/erpnext/docs/assets/img/articles/sections-1.png b/erpnext/docs/assets/img/articles/sections-1.png new file mode 100644 index 0000000000..1ac12adda2 Binary files /dev/null and b/erpnext/docs/assets/img/articles/sections-1.png differ diff --git a/erpnext/docs/assets/img/articles/sections-2.gif b/erpnext/docs/assets/img/articles/sections-2.gif new file mode 100644 index 0000000000..48edb795b0 Binary files /dev/null and b/erpnext/docs/assets/img/articles/sections-2.gif differ diff --git a/erpnext/docs/assets/img/articles/types-in-tax-masters.png b/erpnext/docs/assets/img/articles/types-in-tax-masters.png new file mode 100644 index 0000000000..221808ea7b Binary files /dev/null and b/erpnext/docs/assets/img/articles/types-in-tax-masters.png differ diff --git a/erpnext/docs/assets/img/project/timesheet/make_invoice_from_timesheet.gif b/erpnext/docs/assets/img/project/timesheet/make_invoice_from_timesheet.gif new file mode 100644 index 0000000000..90cc6d6e86 Binary files /dev/null and b/erpnext/docs/assets/img/project/timesheet/make_invoice_from_timesheet.gif differ diff --git a/erpnext/docs/assets/img/schools/admission/program-enrollment-tool.gif b/erpnext/docs/assets/img/schools/admission/program-enrollment-tool.gif new file mode 100644 index 0000000000..c25b179967 Binary files /dev/null and b/erpnext/docs/assets/img/schools/admission/program-enrollment-tool.gif differ diff --git a/erpnext/docs/assets/img/schools/admission/program-enrollment-tool01.gif b/erpnext/docs/assets/img/schools/admission/program-enrollment-tool01.gif new file mode 100644 index 0000000000..8b1f6314be Binary files /dev/null and b/erpnext/docs/assets/img/schools/admission/program-enrollment-tool01.gif differ diff --git a/erpnext/docs/assets/img/schools/admission/program-enrollment.gif b/erpnext/docs/assets/img/schools/admission/program-enrollment.gif new file mode 100644 index 0000000000..616ab17df9 Binary files /dev/null and b/erpnext/docs/assets/img/schools/admission/program-enrollment.gif differ diff --git a/erpnext/docs/assets/img/schools/admission/program-enrollment.png b/erpnext/docs/assets/img/schools/admission/program-enrollment.png deleted file mode 100644 index df96f3c320..0000000000 Binary files a/erpnext/docs/assets/img/schools/admission/program-enrollment.png and /dev/null differ diff --git a/erpnext/docs/assets/img/schools/admission/student-applicant-enroll.png b/erpnext/docs/assets/img/schools/admission/student-applicant-enroll.png index fb92a679df..7cf5e75be4 100644 Binary files a/erpnext/docs/assets/img/schools/admission/student-applicant-enroll.png and b/erpnext/docs/assets/img/schools/admission/student-applicant-enroll.png differ diff --git a/erpnext/docs/assets/img/schools/admission/student-application-actions.png b/erpnext/docs/assets/img/schools/admission/student-application-actions.png new file mode 100644 index 0000000000..e3a4c15ec1 Binary files /dev/null and b/erpnext/docs/assets/img/schools/admission/student-application-actions.png differ diff --git a/erpnext/docs/assets/img/schools/schedule/student-attendance.gif b/erpnext/docs/assets/img/schools/schedule/student-attendance.gif new file mode 100644 index 0000000000..82549d4692 Binary files /dev/null and b/erpnext/docs/assets/img/schools/schedule/student-attendance.gif differ diff --git a/erpnext/docs/assets/img/schools/schedule/student-leave-application.gif b/erpnext/docs/assets/img/schools/schedule/student-leave-application.gif new file mode 100644 index 0000000000..3b09fac27b Binary files /dev/null and b/erpnext/docs/assets/img/schools/schedule/student-leave-application.gif differ diff --git a/erpnext/docs/assets/img/schools/setup/Course-schedule-error.png b/erpnext/docs/assets/img/schools/setup/Course-schedule-error.png new file mode 100644 index 0000000000..d9913d857a Binary files /dev/null and b/erpnext/docs/assets/img/schools/setup/Course-schedule-error.png differ diff --git a/erpnext/docs/assets/img/schools/setup/Room-Assesment-plan.png b/erpnext/docs/assets/img/schools/setup/Room-Assesment-plan.png new file mode 100644 index 0000000000..4b23cd7ea3 Binary files /dev/null and b/erpnext/docs/assets/img/schools/setup/Room-Assesment-plan.png differ diff --git a/erpnext/docs/assets/img/schools/setup/course-fee-program.png b/erpnext/docs/assets/img/schools/setup/course-fee-program.png new file mode 100644 index 0000000000..c8527d04e0 Binary files /dev/null and b/erpnext/docs/assets/img/schools/setup/course-fee-program.png differ diff --git a/erpnext/docs/assets/img/schools/setup/setup-section.png b/erpnext/docs/assets/img/schools/setup/setup-section.png deleted file mode 100644 index c02bbc4733..0000000000 Binary files a/erpnext/docs/assets/img/schools/setup/setup-section.png and /dev/null differ diff --git a/erpnext/docs/assets/img/schools/setup/student-attendance-tool.gif b/erpnext/docs/assets/img/schools/setup/student-attendance-tool.gif new file mode 100644 index 0000000000..c8c1c05e80 Binary files /dev/null and b/erpnext/docs/assets/img/schools/setup/student-attendance-tool.gif differ diff --git a/erpnext/docs/assets/img/schools/setup/student-group-instructor.png b/erpnext/docs/assets/img/schools/setup/student-group-instructor.png new file mode 100644 index 0000000000..d9457a6d9c Binary files /dev/null and b/erpnext/docs/assets/img/schools/setup/student-group-instructor.png differ diff --git a/erpnext/docs/assets/img/schools/student/guardian.png b/erpnext/docs/assets/img/schools/student/guardian.png new file mode 100644 index 0000000000..01045be490 Binary files /dev/null and b/erpnext/docs/assets/img/schools/student/guardian.png differ diff --git a/erpnext/docs/assets/img/schools/student/schools-settings.png b/erpnext/docs/assets/img/schools/student/schools-settings.png new file mode 100644 index 0000000000..8a71ac92ed Binary files /dev/null and b/erpnext/docs/assets/img/schools/student/schools-settings.png differ diff --git a/erpnext/docs/assets/img/schools/student/student group.gif b/erpnext/docs/assets/img/schools/student/student group.gif new file mode 100644 index 0000000000..13b1cf4342 Binary files /dev/null and b/erpnext/docs/assets/img/schools/student/student group.gif differ diff --git a/erpnext/docs/assets/img/schools/student/student-admission.gif b/erpnext/docs/assets/img/schools/student/student-admission.gif new file mode 100644 index 0000000000..a9ce8dc9b5 Binary files /dev/null and b/erpnext/docs/assets/img/schools/student/student-admission.gif differ diff --git a/erpnext/docs/assets/img/schools/student/student-batch-validation.gif b/erpnext/docs/assets/img/schools/student/student-batch-validation.gif new file mode 100644 index 0000000000..dd9f0e821d Binary files /dev/null and b/erpnext/docs/assets/img/schools/student/student-batch-validation.gif differ diff --git a/erpnext/docs/assets/img/schools/student/student-batch.gif b/erpnext/docs/assets/img/schools/student/student-batch.gif new file mode 100644 index 0000000000..43bae7734d Binary files /dev/null and b/erpnext/docs/assets/img/schools/student/student-batch.gif differ diff --git a/erpnext/docs/assets/img/schools/student/student-batch.png b/erpnext/docs/assets/img/schools/student/student-batch.png deleted file mode 100644 index 75a33140cc..0000000000 Binary files a/erpnext/docs/assets/img/schools/student/student-batch.png and /dev/null differ diff --git a/erpnext/docs/assets/img/schools/student/student-course-validation.gif b/erpnext/docs/assets/img/schools/student/student-course-validation.gif new file mode 100644 index 0000000000..6ab9d00472 Binary files /dev/null and b/erpnext/docs/assets/img/schools/student/student-course-validation.gif differ diff --git a/erpnext/docs/assets/img/schools/student/student-group-attendance.gif b/erpnext/docs/assets/img/schools/student/student-group-attendance.gif new file mode 100644 index 0000000000..da9aa1ac26 Binary files /dev/null and b/erpnext/docs/assets/img/schools/student/student-group-attendance.gif differ diff --git a/erpnext/docs/assets/img/schools/student/student-group-creation-tool.gif b/erpnext/docs/assets/img/schools/student/student-group-creation-tool.gif new file mode 100644 index 0000000000..1fe1a6f020 Binary files /dev/null and b/erpnext/docs/assets/img/schools/student/student-group-creation-tool.gif differ diff --git a/erpnext/docs/assets/img/schools/student/student-group-creation-tool.png b/erpnext/docs/assets/img/schools/student/student-group-creation-tool.png deleted file mode 100644 index 32e6498f8b..0000000000 Binary files a/erpnext/docs/assets/img/schools/student/student-group-creation-tool.png and /dev/null differ diff --git a/erpnext/docs/assets/img/schools/student/student-group.png b/erpnext/docs/assets/img/schools/student/student-group.png deleted file mode 100644 index c562b00132..0000000000 Binary files a/erpnext/docs/assets/img/schools/student/student-group.png and /dev/null differ diff --git a/erpnext/docs/assets/img/setup/integrations/razorpay-api.gif b/erpnext/docs/assets/img/setup/integrations/razorpay-api.gif new file mode 100644 index 0000000000..1e79664e5f Binary files /dev/null and b/erpnext/docs/assets/img/setup/integrations/razorpay-api.gif differ diff --git a/erpnext/docs/user/manual/en/accounts/articles/c-form.md b/erpnext/docs/user/manual/en/accounts/articles/c-form.md deleted file mode 100644 index a02f7c6461..0000000000 --- a/erpnext/docs/user/manual/en/accounts/articles/c-form.md +++ /dev/null @@ -1,47 +0,0 @@ -#C-Form - -C-Form functionality is only applicable for Indian customers. - -**What is C-Form?** - -C-Form is issued by the Customer. If Customer Issues C-Form, supplier applies discounted CST (central sales tax) in the invoice. C-Form is only applicable on the inter-state transactions. - -C-Form functionality in ERPNext allows Supplier to update C-Form No. as received from Customer in the submitted Sales Invoice. Also you can create report on Sales Invoice and track invoices for which C-Form has not yet been received from Customer. - -Following are step to manage C-Form related sales in ERPNext. - -####Set C-Form Applicability - -While creating Sales invoice for the customer, set C-Form applicability in Sales Invoice. In More Info section of Sales Invoice, set field called **Is C-Form Applicable** as **Yes**. Bydefault, this field will have No for a value. - -![C-form](/docs/assets/img/articles/Selection_0028c9f9a.png) - -Updating this field as Yes will allow you to pull this Sales Invoice in the C-Form Tool, and update C-Form No. as received from the Customer. - -####Create C-Form Record - -After receiving C-Form from your Customer, you should update that C-Form no. in the Sales Invoice by creating C-Form record. - -Go to `Accounts > Setup > C-Form > New` - -Enter details like C-Form No, Received Date, State and Amount etc. Select Customer and pull related Sales Invoices under provided table. - -![New C-Form](/docs/assets/img/articles/Selection_020f01c1e.png) - -####Save & Submit C-Form - -After entering details, save and submit C-Form record. On save system will generate C-Form record and on submission update that C-Form No. in the Sales Invoice. - -![C-Form](/docs/assets/img/articles/Selection_02178f9d6.png) - -C-Form serial no will be updated in related invoice under the field 'C-Form No'. - -![C-Form No](/docs/assets/img/articles/Selection_022b7c6d5.png) - -####Tracking Pending Invoice for C-Form - -To track invoices for which C-Form has not yet been received from Customer, you can create custom report on Sales Invoice. In this report, you can filter invoices which doesn't have C-Form updated in them yet, and followup with the customer accordingly. - -![C-Form Report](/docs/assets/img/articles/Selection_026.png) - - diff --git a/erpnext/docs/user/manual/en/accounts/articles/common-receivable-account.md b/erpnext/docs/user/manual/en/accounts/articles/common-receivable-account.md new file mode 100644 index 0000000000..6f92232117 --- /dev/null +++ b/erpnext/docs/user/manual/en/accounts/articles/common-receivable-account.md @@ -0,0 +1,13 @@ +# Common Receivable Account + +As per the party model, a common receivable account called **Debtor** is auto-created. This is a default Receivable Account for all the Customers. + +Role Desk Permission + +If needed, you can also create a new receivable account and update in the Customer master. + +**Question:** Should I create separate Receivable Account Account for each Customer? + +**Answer:** You can, but it's not a recommend approach. If you want to create separate Receivable Account for each Customer for tracking receivable, then it not needed. You still view Account Receivable & General Ledger report for each Customer. + +Just like Debtors, for tracking payables, default account called Creditors is created under Account Payables. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/accounts/articles/freeze-account.md b/erpnext/docs/user/manual/en/accounts/articles/freeze-account.md new file mode 100644 index 0000000000..3582c28124 --- /dev/null +++ b/erpnext/docs/user/manual/en/accounts/articles/freeze-account.md @@ -0,0 +1,13 @@ +# Freeze an Account + +Once an Account is Frozen, you won't be able to use it any accounting transaction. Since this is a critical action, you need to explicitly define a Role who can set an Account as Frozen. You can define this Role in the Account Settings. + +`Accounts > Account Settings` + +To freeze an Account, go to Chart of Accounts, and edit an Account. + +Download Backup + +If User has Role define in the  Account Setting assigned, then he/she will be able to set an Account as Frozen. + +Download Backup \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/accounts/articles/index.txt b/erpnext/docs/user/manual/en/accounts/articles/index.txt index 77474bd159..af8572c233 100644 --- a/erpnext/docs/user/manual/en/accounts/articles/index.txt +++ b/erpnext/docs/user/manual/en/accounts/articles/index.txt @@ -6,10 +6,12 @@ freeze-accounting-entries how-to-freeze-accouting-ledger manage-foreign-exchange-difference managing-transactions-in-multiple-currency -fiscal-year-creation +fiscal-year-creation post-dated-cheque-entry update-stock-option-in-sales-invoice what-is-the-differences-of-total-and-valuation-in-tax-and-charges withdrawing-salary-from-owners-equity-account adjust-withhold-amount-payment-entry -c-form \ No newline at end of file +common-receivable-account.md +types-in-tax-template +freeze-account \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/accounts/articles/purchase-invoice-account-type-error.md b/erpnext/docs/user/manual/en/accounts/articles/purchase-invoice-account-type-error.md new file mode 100644 index 0000000000..e7a0772256 --- /dev/null +++ b/erpnext/docs/user/manual/en/accounts/articles/purchase-invoice-account-type-error.md @@ -0,0 +1,9 @@ +# Purchase Invoice - Account Type Error + +**Question:** On saving the Purchase Invoice, I am getting a validation message that Credit To Account must be a Balance Sheet account. + +Role Desk Permission + +**Answer: **On submission of a Purchase Invoice, payable is updated towards the Supplier. As per the accounting standards, Payable Account is aligned under Current Liability (credit side of Balance Sheet). + +The error message indicates that Account selected in the Credit To field doesn't belong to the Liability Group. Please ensure that Payable Account selected in the Purchase Invoice is located under Liability group. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/accounts/articles/types-in-tax-template.md b/erpnext/docs/user/manual/en/accounts/articles/types-in-tax-template.md new file mode 100644 index 0000000000..d8618bee56 --- /dev/null +++ b/erpnext/docs/user/manual/en/accounts/articles/types-in-tax-template.md @@ -0,0 +1,17 @@ +# Types in Sales and Purchase Tax Template + +In the Sales Taxes and Purchase Taxes master, you will find a column called Type. Following a brief on a meaning of each Type and how you can use it. + +Role Desk Permission + +**Actual:** This allows you to enter expense amount directly. For example, Rs. 500 incurred for Shipping. + +**On Net Total:** If you want to apply any tax or charges on Net Total, select this option. For example, 18% GST applied to all the item in the Sales Order. + +**On Previous Row Amount:** This option helps you want to calculate tax amount calculated based on another tax amount. + +Example: Education Cess is calculated based on the amount of GST tax. + +**On Previous Row Total:** For each Tax row, a cumulative tax is calculated in the Total column. For the first row, total tax is calculated as Net Total + Tax amount at first row. If you want to apply a tax on the Total Amount of another tax row, then use this option. + +If you select Type as Previous Row Amount or Previous Row Total, then you must also specify a Row No. whose Amount or Total should be considered for the calculation. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/customize-erpnext/articles/child-table-.md b/erpnext/docs/user/manual/en/customize-erpnext/articles/child-table-.md new file mode 100644 index 0000000000..bc31cf21d3 --- /dev/null +++ b/erpnext/docs/user/manual/en/customize-erpnext/articles/child-table-.md @@ -0,0 +1,33 @@ +# Customizing visibility of data in the child table + +**Question:** Currently, in the child table (like Item table in Quotation), we can view value in the four columns only. How can we have more values previewed in the child table? + +**Answer:** In the version 7, we introduced a feature, editable grid. This allowed the user to add values in the child table without opening dialog box/form for each row. + +This is how Quotation Item table renders value when Editable Grid is enabled. It will maximum list four columns in the table. + +Role Desk Permission + +As per the default setting, only four columns are listed in the child table. Following is how you can add more columns in the editable itself. + +For the field to be added as a column in the table, enter a value in the Column field. Also, ensure that "Is List View" property is checked for that field. + +Role Desk Permission + +Based on the value in the Column field, columns will be added in the child table. Ensure that sum total of value added in the Column field doesn't exceed 10. Based on the Column value, width for that column will be set. + +Role Desk Permission + +**Switch to Un-editable Grid** + +To have more values shown in the preview of Quotation Item table, you can disable Editable Grid for the Quotation Item Doctype. Steps below. + +Role Desk Permission + +Once Editable Grid is disabled for the Quotation Item, the following is how values will be rendered in a preview of the Quotation Item table. + +Role Desk Permission + +To have specific field's value shown in the preview, ensure that for that field, in the Customize Form tool, "In List View" property is checked. + +Role Desk Permission \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/customize-erpnext/articles/fetching-data-from-a-document.md b/erpnext/docs/user/manual/en/customize-erpnext/articles/fetching-data-from-a-document.md new file mode 100644 index 0000000000..04b20ac4b9 --- /dev/null +++ b/erpnext/docs/user/manual/en/customize-erpnext/articles/fetching-data-from-a-document.md @@ -0,0 +1,19 @@ +# Fetching Data from one Document to Another + +**Question:** We track Customer's PO No and PO Date field in the Sales Order. To have these values fetched into Sales Invoice as well, we have inserted Custom Field in the Sales Invoice. However, when we create Sales Invoice from the Sales Order, Customer's PO details are not being fetched. + +**Answer:** When data is fetched from one transaction to the another transaction, then the mapping of data is done based on the field names. If two transactions have fields with the exact same name, then it's values are mapped. + +For example, if you want Customer's PO No. and PO Date to be fetched from Sales Order to Sales Invoice, then you should ensure that Custom Fields added in the Sales Invoice has an exact same field name as in the Sales Order. + +Sales Order (standard fields) + +Standard fields in Sales Order + +Sales Invoice (custom fields) + +Custom Field in Sales Invoice + +Since names for the Customer's PO related fields are same in the Sales Order and Sales Invoice, when creating Sales Invoice from the Sales Order, values in these fields are auto-fetched. + +Values fetching from Sales Order to Sales Invoice \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/customize-erpnext/articles/index.txt b/erpnext/docs/user/manual/en/customize-erpnext/articles/index.txt index f8a81a4e51..56e7040b47 100644 --- a/erpnext/docs/user/manual/en/customize-erpnext/articles/index.txt +++ b/erpnext/docs/user/manual/en/customize-erpnext/articles/index.txt @@ -14,4 +14,6 @@ search-record-by-specific-field set-language set-precision user-restriction -maximum-numbers-of-fields-in-a-form \ No newline at end of file +maximum-numbers-of-fields-in-a-form +child-table +fetching-data-from-a-document \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/human-resources/articles/index.txt b/erpnext/docs/user/manual/en/human-resources/articles/index.txt index 3fbdc5bb51..3019af5de9 100644 --- a/erpnext/docs/user/manual/en/human-resources/articles/index.txt +++ b/erpnext/docs/user/manual/en/human-resources/articles/index.txt @@ -1,2 +1,3 @@ employees-loan-management -leave-calculation-in-salary-slip \ No newline at end of file +leave-calculation-in-salary-slip +working-days-in-salary-slip \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/human-resources/articles/working-days-in-salary-slip.md b/erpnext/docs/user/manual/en/human-resources/articles/working-days-in-salary-slip.md new file mode 100644 index 0000000000..289a24abb2 --- /dev/null +++ b/erpnext/docs/user/manual/en/human-resources/articles/working-days-in-salary-slip.md @@ -0,0 +1,11 @@ +# Working Days Calculation in the Salary Slip + +Working Days are shown in the In the Salary Slip. Based on your preference, it may include holidays of the month or it may not. You can define your preference for the Working Days calculation in HR Settings. + +`HR > Setup > HR Settings` + +If you want to include holidays in the count of Total Working days, then ensure that in the HR Settings, field **Include holidays in Total no. of Working Days** is checked and vice versa. + +Role Desk Permission + +To learn how to define holidays for your company, check [Holiday List](/user/manual/en/human-resources/holiday-list) feature in the HR module. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/human-resources/training.md b/erpnext/docs/user/manual/en/human-resources/training.md index 39b9790246..2aa06791f0 100644 --- a/erpnext/docs/user/manual/en/human-resources/training.md +++ b/erpnext/docs/user/manual/en/human-resources/training.md @@ -9,22 +9,23 @@ Schedule seminars, workshops, conferences etc using Training Event. You can also ### Inviting Employees for Event You can invite your employees to attend the event. You can do so by selecting the employees to be invited in the employee table. + By default the status of the employee will be 'Open'. -The system shall notify the employee with status 'Open' by sending a email to the office email address of the employee as mentioned in the employee master if you have selected 'Send Email' checkbox. -The status is changed to 'Invited' when an invitation email is sent to the employee by the system. -When an Employee confirms his/her presence for the event you can change the status to 'Confirmed'. 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. + ### Training Result -After compleation of the training Employee Wise training results can be stored based on the Feedback received from the Trainer. +After compleation of the training Employee-wise training results can be stored based on the Feedback received from the Trainer. Employee +When the Training Result is submitted, all the employees will receive an email notifying them that they must share their feedback via "Training Feedback". This is also managed via an Email Alert, so you can customize this alert too. -### Trainig Feedback +### Training Feedback -Collect feedback regarding the event from your Employees using Training Feedback. +Employees can then share their feedback via Training Feedback. Employee diff --git a/erpnext/docs/user/manual/en/manufacturing/articles/capacity-planning.md b/erpnext/docs/user/manual/en/manufacturing/articles/capacity-planning.md new file mode 100644 index 0000000000..4dd10b3eb7 --- /dev/null +++ b/erpnext/docs/user/manual/en/manufacturing/articles/capacity-planning.md @@ -0,0 +1,51 @@ +# Capacity Planning based on Production Order + +Capacity Planning functionality helps you in tracking production jobs allocated on each Workstation. + +Role Desk Permission + +Follow are the steps to use Capacity Planning Feature in your ERPNext account. + +1. Operations + + To add operations, go to: + + `Manufacturing > Bill of Materials > Operations` + +2. Workstation + + Add each Workstation in your ERPNext account from: + + `Manufacturing > Bill of Materials > Workstation` + + In the Workstation master, you can define which operations will be performed on it, what are the cost associated with it, and what are the working hours of that Workstation. + +3. Bill of Materials (BOM): + + In a BOM, with the list of raw material needed, for manufacturing, you can also list operation and workstations through which those raw materials will be processed. + +4. Production Order: + + On submission of Production Order, Timesheet for Operations. This helps you allocate production jobs on each Workstation, as well as you can update actual time taken for each Operation. + +### Error due to Capacity Planning + +**Question:** On Submission of Production Order, we are getting following error message. + +Role Desk Permission + +**Answer: **Please check if you have updated Working Hours in the Workstation master? If not, then please update it and then try to submit Production Order. + +On submission of Production Order, Operations (as added in the BOM) are allocated on the workstation. Each operation should start and end on the same day. If a system is not able to schedule that operation in a day, then system request you to divide that Project, so that system can allocate smaller operations in a day. + +If you have update working hours in the Workstation, but still getting this issue, that because one of your operation is taking too long, and cannot be completed in a day. Please divide that operation into smaller operations, so that it can be allocated on Workstation and completed on the same day. + +### Avoid Working Hours of Workstation + +If you want to ignore above validation and allow scheduling of production job beyond the working hours of the Workstation, enable +Overtime in the Manufacturing Settings. + +Role Desk Permission + +If you want to complete disable Capacity Planning feature, in the Manufacturing Settings, check field "Disable Capacity Planning and Time Tracking". + diff --git a/erpnext/docs/user/manual/en/manufacturing/articles/index.txt b/erpnext/docs/user/manual/en/manufacturing/articles/index.txt index bb78d39731..d0e429e993 100644 --- a/erpnext/docs/user/manual/en/manufacturing/articles/index.txt +++ b/erpnext/docs/user/manual/en/manufacturing/articles/index.txt @@ -1,3 +1,4 @@ nested-bom-structure production-planning-subassembly -valuation-based-on-field-in-bom \ No newline at end of file +valuation-based-on-field-in-bom +capacity-planning \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/projects/articles/project-costing.md b/erpnext/docs/user/manual/en/projects/articles/project-costing.md index dad849ea9d..2943ea6717 100644 --- a/erpnext/docs/user/manual/en/projects/articles/project-costing.md +++ b/erpnext/docs/user/manual/en/projects/articles/project-costing.md @@ -1,4 +1,4 @@ -

Project Costing

+# Project Costing Each project has multiple task associated with it. To track actual costing of a Project, primarily in terms of services, user has to create Time Log based on actual time spent on Project-Task. Following the steps on how you can track actual service cost against Project. @@ -12,17 +12,17 @@ Activity Type is a master of service offered by your personnel. You can add new Activity Cost is a master where you can track billing and costing rate for each Employee, and for each Activity Type. -![Activity Cost](/docs/assets/img/articles/Screen Shot 2015-06-11 at 4.57.01 pm.png) +Activity Cost #### Time Log Based on Actual Time spent on the Project-Task, Employee will create a time log. -![Time Log](/docs/assets/img/articles/Screen Shot 2015-06-11 at 4.59.49 pm.png) +Time Log On selection of Activity Type in the Time Log, Billing and Costing Rate will fetched for that Employee from respective Activity Cost master. -![Time Log Costing](/docs/assets/img/articles/Screen Shot 2015-06-11 at 5.00.06 pm.png) +[Time Log Costing Multiplying these rates with total no. of Hours in the Time Log gives Costing Amount and Billing Amount for the specific Time Log. @@ -30,10 +30,10 @@ Multiplying these rates with total no. of Hours in the Time Log gives Costing Am Based on total Time Logs created for a specific Task, its costing will be updated in the respective Task master. -![Costing in Task](/docs/assets/img/articles/Screen Shot 2015-06-11 at 5.02.54 pm.png) +Costing in Task Same way, Project master will have cost updated based on Time Log created against that Projects, and tasks associated with that Project. -![Costing in Project](/docs/assets/img/articles/Screen Shot 2015-06-11 at 5.02.29 pm.png) +Costing in Project \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/projects/timesheet/sales-invoice-from-timesheet.md b/erpnext/docs/user/manual/en/projects/timesheet/sales-invoice-from-timesheet.md index 9be2bad0e2..4dbdcbb6dc 100644 --- a/erpnext/docs/user/manual/en/projects/timesheet/sales-invoice-from-timesheet.md +++ b/erpnext/docs/user/manual/en/projects/timesheet/sales-invoice-from-timesheet.md @@ -48,6 +48,8 @@ In the Timesheet, if "Is Billable" is checked, you will find option to create Sa Sales Invoice +Sales Invoice timesheet + ####Sales Invoice Sales Invoice has dedicated table for the Timesheet table where Timesheet details will be updated. You can select more Timesheets in this table. diff --git a/erpnext/docs/user/manual/en/schools/Assessment/assessment_criteria_group.md b/erpnext/docs/user/manual/en/schools/Assessment/assessment_criteria_group.md new file mode 100644 index 0000000000..4287ca8617 --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/Assessment/assessment_criteria_group.md @@ -0,0 +1 @@ +# \ No newline at end of file diff --git a/erpnext/docs/assets/old_images/erpnext/__init__.py b/erpnext/docs/user/manual/en/schools/Attendance/__init__.py similarity index 100% rename from erpnext/docs/assets/old_images/erpnext/__init__.py rename to erpnext/docs/user/manual/en/schools/Attendance/__init__.py diff --git a/erpnext/docs/user/manual/en/schools/Attendance/index.md b/erpnext/docs/user/manual/en/schools/Attendance/index.md new file mode 100644 index 0000000000..3153a59022 --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/Attendance/index.md @@ -0,0 +1,6 @@ +#Attendance + + +### Topics + +{index} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/Attendance/index.txt b/erpnext/docs/user/manual/en/schools/Attendance/index.txt new file mode 100644 index 0000000000..8cd02627a2 --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/Attendance/index.txt @@ -0,0 +1,3 @@ +student-attendance +student-leave-application +student-attendance-tool \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/Attendance/student-attendance-tool.md b/erpnext/docs/user/manual/en/schools/Attendance/student-attendance-tool.md new file mode 100644 index 0000000000..5c4ce3072a --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/Attendance/student-attendance-tool.md @@ -0,0 +1,15 @@ +# Student Attendance Tool + +The Student Attendance tool allow you to bulk update the attendance for students based on **Student Group and Course Schedule**. + +To mark the **Attedance* based on Student Group select the group based on + +**1. Batch + 2. Course + 3. Activity ** + +Student detials will be autofetched and you can mark the attendance of the given date. + +Student Attendance + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/Attendance/student-attendance.md b/erpnext/docs/user/manual/en/schools/Attendance/student-attendance.md new file mode 100644 index 0000000000..1b917d0ae2 --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/Attendance/student-attendance.md @@ -0,0 +1,15 @@ +# Student Attendance + +Attendance doctype allows you to track and manage attendance of a student in all the days at any time. The Attendance module is designed to help teachers easily mark student attendance during class. + +Attendance Records can be created against Student on daily basis. + +To create Attendance record : + +Select the **Student, Course Schedule and Student Group** for which attendance is to be marked for the given date. Set the Status to Present/Absent and save. + +Student Attendance + +**Student Attendance tool** can be used for bulk updation of the attendance based on **Batch, Course or Activity**. + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/Attendance/student-leave-application.md b/erpnext/docs/user/manual/en/schools/Attendance/student-leave-application.md new file mode 100644 index 0000000000..5620bdadd7 --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/Attendance/student-leave-application.md @@ -0,0 +1,13 @@ +#Student Leave Application + +ERPNext allows you to record the leave application for a student. + +To create a Student Leave application record, enter the Student and the date for the leave is applied and save. + +Student Attendance + +Incase the student is not attending the school in order to participate or represent school in any event, he/she can be mark as present from the Leave Application itself. + +Once a Leave Application is recorded for a student it will not be recorded in the absent student report as he has applied for a leave. + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/admission/index.md b/erpnext/docs/user/manual/en/schools/admission/index.md index 87cdfe5c89..b602271bbb 100644 --- a/erpnext/docs/user/manual/en/schools/admission/index.md +++ b/erpnext/docs/user/manual/en/schools/admission/index.md @@ -1,6 +1,6 @@ # Admission -This section contains student admission related documents. +The Admission section allow you to create all records starting from Student application till the program enrollment. Below is the list of documents for Student addmission. ### Topics diff --git a/erpnext/docs/user/manual/en/schools/admission/index.txt b/erpnext/docs/user/manual/en/schools/admission/index.txt index ec9e768116..680d779089 100644 --- a/erpnext/docs/user/manual/en/schools/admission/index.txt +++ b/erpnext/docs/user/manual/en/schools/admission/index.txt @@ -1,2 +1,4 @@ +student-admission student-applicant -program-enrollment \ No newline at end of file +program-enrollment +program-enrollment-Tool diff --git a/erpnext/docs/user/manual/en/schools/admission/program-enrollment-tool.md b/erpnext/docs/user/manual/en/schools/admission/program-enrollment-tool.md new file mode 100644 index 0000000000..2a2fa1e58e --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/admission/program-enrollment-tool.md @@ -0,0 +1,16 @@ +# Program Enrollment Tool + +The Program Enrollment tool allows the bulk enrollment of the **Student Applicants** in a Program. + + +You can create the the Program Enrollment for : + +1. **Student Applicants** >> List of Student Applicants will be fetched for the selected **Program** and **Academic year**. + +Student Applicant Enrollment + +2. **Program Enrollment** >> You can bulk update the **Program** for the students from one academic year to another in the same **Program** or a new **Program**. + +Student Applicant Enrollment + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/admission/program-enrollment.md b/erpnext/docs/user/manual/en/schools/admission/program-enrollment.md index 2dcc6cb2ce..cc1308cf6c 100644 --- a/erpnext/docs/user/manual/en/schools/admission/program-enrollment.md +++ b/erpnext/docs/user/manual/en/schools/admission/program-enrollment.md @@ -1,7 +1,12 @@ # Program Enrollment -This form allows you to enroll a student to a program. A student can be enrolled to multiple programs. +Program Enrollment describes an educational model where students must complete a defined set of courses towards their academic objective in a specified sequence. Enrollment is a program driven process in which the student select the Program to enrol for in a Academic Year. -Student Applicant Enrollment +Once a student have applied for the **Program** and the application is approved, the program enrollment is done for that student. + +Student Applicant Enrollment + +- A student can be enrolled in multiple Course for a program in a given academeic year. +- Based on the Fee structure selected at the time of enrollment Fee detials are created of the student. {next} diff --git a/erpnext/docs/user/manual/en/schools/admission/student-applicant.md b/erpnext/docs/user/manual/en/schools/admission/student-applicant.md index e67c1dc79e..22d370939d 100644 --- a/erpnext/docs/user/manual/en/schools/admission/student-applicant.md +++ b/erpnext/docs/user/manual/en/schools/admission/student-applicant.md @@ -18,7 +18,9 @@ You can Approve or Reject a student applicant. By accepting a student applicant and will not allow you to change the application status unless the student record is deleted. ### Student Enrollment +Once the form is submitted you can either approve or reject the application form. +Student Applicant Enrollment Once you approve a Student Applicant you can enroll them to a program. When you click the 'Enroll' buttom, the system shall create a student against that applicant and redirect you to the [Program Enrollment form](/docs/user/manual/en/schools/student/program-enrollment.html). diff --git a/erpnext/docs/user/manual/en/schools/admission/student_admission.md b/erpnext/docs/user/manual/en/schools/admission/student_admission.md new file mode 100644 index 0000000000..eeaa977912 --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/admission/student_admission.md @@ -0,0 +1,13 @@ +# Student Admission + +The admission process begins with filling the admission form. The Student Admission record enables to intitate your admission process for a given **Academic year**. ERPNext admission module allow you to create an admission record which can be then published on the ERPNext generate website. + +To create a Student Admission record go to : + +**Schools** >> **Admissions** >> **Student Admission** >> + + +Student Applicant + + +Once a admission record is created it can be published on the website and the student can apply from the web portal itself. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/index.md b/erpnext/docs/user/manual/en/schools/index.md index 8c766d6db4..d317d39bfa 100644 --- a/erpnext/docs/user/manual/en/schools/index.md +++ b/erpnext/docs/user/manual/en/schools/index.md @@ -1,7 +1,7 @@ # Schools -The School Modules is designed to meet requirements of Schools, Colleges & Educational Institutes. +The School Modules in ERPNext is designed to meet requirements of Schools, Colleges & Educational Institutes. This is a centralized system, which maintains and updates all the activities related to an Institution. This will ease the process of each and every aspect of a School, be it Students, Admission, Examination and Fee. Fees Section diff --git a/erpnext/docs/user/manual/en/schools/index.txt b/erpnext/docs/user/manual/en/schools/index.txt index b485fdcfea..159089c6f3 100644 --- a/erpnext/docs/user/manual/en/schools/index.txt +++ b/erpnext/docs/user/manual/en/schools/index.txt @@ -1,6 +1,7 @@ student admission +Attendance schedule fees setup -assessment \ No newline at end of file +Assessment \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/schedule/student-attendance.md b/erpnext/docs/user/manual/en/schools/schedule/student-attendance.md deleted file mode 100644 index 84e1ea8669..0000000000 --- a/erpnext/docs/user/manual/en/schools/schedule/student-attendance.md +++ /dev/null @@ -1,7 +0,0 @@ -# Student Attendance - -Maintains attendance record of the student. Attendance Records can be created against Course Schedules. - -Student Attendance - -{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/academic-term.md b/erpnext/docs/user/manual/en/schools/setup/academic-term.md index 6306444b61..b52bea7108 100644 --- a/erpnext/docs/user/manual/en/schools/setup/academic-term.md +++ b/erpnext/docs/user/manual/en/schools/setup/academic-term.md @@ -1,5 +1,9 @@ # Academic Term +An academic term (or simply "term") is a portion of an academic year, the time during which an educational institution holds classes. The schedules adopted vary widely. The academic term can be a quater, trimester or a semester. + +The **Academic term** form in ERPNext enables you to create academic terms within in a year. Based on the term schedule enter the start and end date for the schedule and generate the term for a Academic year. + Academic Term diff --git a/erpnext/docs/user/manual/en/schools/setup/academic-year.md b/erpnext/docs/user/manual/en/schools/setup/academic-year.md index 3913eb634b..4fc5f929a5 100644 --- a/erpnext/docs/user/manual/en/schools/setup/academic-year.md +++ b/erpnext/docs/user/manual/en/schools/setup/academic-year.md @@ -1,5 +1,11 @@ # Academic Year +An academic year is a period of time which schools, colleges and universities use to measure a quantity of study. + +The **Academic year** form have the Start and End date for the Academic year. + Academic Year -{next} \ No newline at end of file +**Student group** link is given to view or add the respective groups to the Academic year. + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/course.md b/erpnext/docs/user/manual/en/schools/setup/course.md index 140131dccd..dc10ed54b1 100644 --- a/erpnext/docs/user/manual/en/schools/setup/course.md +++ b/erpnext/docs/user/manual/en/schools/setup/course.md @@ -1,5 +1,15 @@ # Course + A course is a unit of teaching that typically lasts one academic term, is led by one or more instructors (teachers or professors), and has a fixed number of students. Students may receive a grade and academic credit after completion of the course. + +To create a **Course** enter the Course name and Code. Code for the course should be unique for every course. You can also link the department under which the course is conducted. + Course +Once a **Course** is created, a course schedule can defined for the same. + +Course + +The Course form is further linked to **Program, Student Group and Assessment Plan** doctypes. The links allow to view/create the related documents for a **Course**. + {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/index.md b/erpnext/docs/user/manual/en/schools/setup/index.md index 9de753614c..4e0915277b 100644 --- a/erpnext/docs/user/manual/en/schools/setup/index.md +++ b/erpnext/docs/user/manual/en/schools/setup/index.md @@ -1,5 +1,7 @@ # Setup +The Setup section of Schools module provides facility to make some basic configuration. Below are doctypes for basic configuration. + Setup Section ### Topics diff --git a/erpnext/docs/user/manual/en/schools/setup/index.txt b/erpnext/docs/user/manual/en/schools/setup/index.txt index fb9ba05d09..8fb9bb2def 100644 --- a/erpnext/docs/user/manual/en/schools/setup/index.txt +++ b/erpnext/docs/user/manual/en/schools/setup/index.txt @@ -2,5 +2,8 @@ course program instructor room +student-category +student-batch-name academic-term -academic-year \ No newline at end of file +academic-year +school-settings \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/instructor.md b/erpnext/docs/user/manual/en/schools/setup/instructor.md index 1a4d35161c..6150f025fe 100644 --- a/erpnext/docs/user/manual/en/schools/setup/instructor.md +++ b/erpnext/docs/user/manual/en/schools/setup/instructor.md @@ -1,5 +1,18 @@ # Instructor +An instructoe is a teacher, or professor, of a specialised subject that involves skill. + +You can create an Instructor and link it to the Employee master and a Departmemt. + Instructor +An **Instructor** is further linked to a **Course Schedule**, where you can define the schedule for a **Course** for a give date and **Room no**. + +Instructor +It is also linked to **Student group** where an **Instructor** is assigned to the Student group. + +Instructor + +An **Instructor** is also linked to an **Assesment Plan** for a Student group. The Instructor can be an Examiner or the supervisor for the assesment. + {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/program.md b/erpnext/docs/user/manual/en/schools/setup/program.md index 64513e20b0..be10166e7b 100644 --- a/erpnext/docs/user/manual/en/schools/setup/program.md +++ b/erpnext/docs/user/manual/en/schools/setup/program.md @@ -1,5 +1,19 @@ # Program +An educational program is a program written by the institutions which determines the learning progress of each subject in all the stages of formal education. + +To create a Program go to : + +###Schools >> Setup >> Program >> New Program + +Enter a unique code for every **Program**. You can also link the **Program** to the department under which it is conducted. + Program +Add the relevant Course and the Fee details for a program. + +Program + +The Program Doctype is further linked to the **Student applicant**, **Program enrollment, Student group, Fee structre and Fee**. The links allow to view or create the related document for a Program. + {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/room.md b/erpnext/docs/user/manual/en/schools/setup/room.md index bb265e3ea2..43ddde9224 100644 --- a/erpnext/docs/user/manual/en/schools/setup/room.md +++ b/erpnext/docs/user/manual/en/schools/setup/room.md @@ -1,6 +1,17 @@ # Room +A classroom is a space (room or lab) where you want to schedule courses or examinations. A room in an educational institute can be a Class room, a laboratory or a Examination hall. + +The Room doctype allows you to record the room number and the seating capacity for a classroom. Once a room is created Course schedule link is provided in the Room doctype to view or add the course schedule for the classroom. Room +The course schedule validate the availability of the Room number and an alert message is shown if there is an overlap for the Room number for a given time slot. + +Room + +The Room number is further linked to the Assesment plan. It validates the availability of examination room for the assessment to be held for a given date and time. + +Room + {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/school-settings.md b/erpnext/docs/user/manual/en/schools/setup/school-settings.md new file mode 100644 index 0000000000..ce9e9144b7 --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/setup/school-settings.md @@ -0,0 +1,15 @@ +#School Settings + +The Schools settings page allow you to setup basic settings like **Academic Year and Term** for the Schools setup. + +Student + +The checkbox to Validate Batch for Students in Student Group enables the Student Batch validation for every Student from the Program Enrollment for the **Batch** based on **Student Group** + +Student + +You can enable the validation of Course for every Student from the enrolled Courses in Program Enrollment,for Course based Student Group by checking the settings for **Validate Enrolled Course for Students in Student Group** + +Student + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/student-batch-name.md b/erpnext/docs/user/manual/en/schools/setup/student-batch-name.md new file mode 100644 index 0000000000..056f910863 --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/setup/student-batch-name.md @@ -0,0 +1,10 @@ +# Student Batch + +Student batch is a collection of students from Student Groups. **Student batch** allows you to create **Student Group** based on a batch. When a student is enrolled for a **Program**, the Student batch is selected to enroll the student for the given Program and batch + +Student + +You can also get a **Student Batch-Wise Attendance** report to view the number of student present from the Batch. + + +{next} diff --git a/erpnext/docs/user/manual/en/schools/setup/student-category.md b/erpnext/docs/user/manual/en/schools/setup/student-category.md new file mode 100644 index 0000000000..0d76927972 --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/setup/student-category.md @@ -0,0 +1,12 @@ +# Student Category + +Student Category doctype allow you to classify student based various categories. In Institutions, there may be fee concession for some categories such as Handicapped students, foreign, nationals, reserved category by the government etc. + +To create Student category go to Setup >> Student Category >> New. + +We can create new student category by adding a name and save it + +Student + + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/student/guardian.md b/erpnext/docs/user/manual/en/schools/student/guardian.md new file mode 100644 index 0000000000..7bbdbc22c5 --- /dev/null +++ b/erpnext/docs/user/manual/en/schools/student/guardian.md @@ -0,0 +1,9 @@ +#Guardian + +The Guardian doctype allows you to record the guardian details for a **Student**. + +Student + +The email id added in the **Guardian** detail can be linked to a email group for sending newsletter or announcements. + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/student/index.txt b/erpnext/docs/user/manual/en/schools/student/index.txt index 9b31be4dc9..89704b1fc7 100644 --- a/erpnext/docs/user/manual/en/schools/student/index.txt +++ b/erpnext/docs/user/manual/en/schools/student/index.txt @@ -1,5 +1,6 @@ student +guardian student-log student-batch student-group -student-group-creation-tool +student-group-creation-tool \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/student/student-batch.md b/erpnext/docs/user/manual/en/schools/student/student-batch.md index 4987c0313f..056f910863 100644 --- a/erpnext/docs/user/manual/en/schools/student/student-batch.md +++ b/erpnext/docs/user/manual/en/schools/student/student-batch.md @@ -1,7 +1,10 @@ # Student Batch -Student batch is a collection of students from Student Groups. +Student batch is a collection of students from Student Groups. **Student batch** allows you to create **Student Group** based on a batch. When a student is enrolled for a **Program**, the Student batch is selected to enroll the student for the given Program and batch + +Student + +You can also get a **Student Batch-Wise Attendance** report to view the number of student present from the Batch. -Student {next} diff --git a/erpnext/docs/user/manual/en/schools/student/student-group-creation-tool.md b/erpnext/docs/user/manual/en/schools/student/student-group-creation-tool.md index 130c94491e..1cd9b1e796 100644 --- a/erpnext/docs/user/manual/en/schools/student/student-group-creation-tool.md +++ b/erpnext/docs/user/manual/en/schools/student/student-group-creation-tool.md @@ -1,8 +1,17 @@ # Student Group Creation Tool -This tool allows you to create student groups in bulk. You can specify multiple parameters to create them. +The Student group creation tool allows you to create student groups in bulk. +To create Student group using this tool go to -Student Group Creation Tool +##Schools >>Student >> Student Group creation tool + +Select the **Academic Term** and the **Program** for which a student group is to be created. + +Student Group Creation Tool + +By default the student group is created based on the **Course** only. The check box for "Separate course based Group for every Batch" allows you to create batchwise Student groups for a course. + +You can leave it unchecked if you don't want to consider batch while making course based groups. {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/student/student-group.md b/erpnext/docs/user/manual/en/schools/student/student-group.md index 191e917a8b..cf3f82c5a2 100644 --- a/erpnext/docs/user/manual/en/schools/student/student-group.md +++ b/erpnext/docs/user/manual/en/schools/student/student-group.md @@ -1,8 +1,22 @@ # Student Group -A student group is a collection of students taking a same course. You can create Course Schedules and Examinations against a Student Group. -A student group needs to be created for every course in a particular academic term and academic year. +A student group is a collection of students taking same course. You can create Course Schedules and Examinations against a Student Group. + +A Student Group needs to be created for every course for **Academic Term** and **Academic Year**. The student group can be create based on **Batch, Course and Activity**. + +To create a Student Group go to: + +Schools >> Student >> New Student Group + +Student Group + +To create a Student group based on **Batch**, select the **Progam** and **Batch**, where as to create a Student group based on **Course**, you will only have to select the Course Code. Creating a student group based on activity allows you to group of student for events and activities happening in the institute. + +Once a student group is created you can mark attendance for the group. + +Student Group + +You can also update the **Email Group** for the Student Group. Click on Update Email Group to add all the email ids of the gaurdians in the respective email group and **Newsletter** can be created and sent to the Email group. -Student Group {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/student/student-log.md b/erpnext/docs/user/manual/en/schools/student/student-log.md index a037a231ac..160e39fcdc 100644 --- a/erpnext/docs/user/manual/en/schools/student/student-log.md +++ b/erpnext/docs/user/manual/en/schools/student/student-log.md @@ -1,6 +1,7 @@ # Student Log -You can make a note of student activities using student log. +The Student log Doctype enables you to add and edit addtional information for a student. +You can make a note of student activities using Student log. Logs can be categorised as 'General', 'Academic', 'Medical' or 'Achievement' Student diff --git a/erpnext/docs/user/manual/en/schools/student/student.md b/erpnext/docs/user/manual/en/schools/student/student.md index dd99a80d2f..09e44714e6 100644 --- a/erpnext/docs/user/manual/en/schools/student/student.md +++ b/erpnext/docs/user/manual/en/schools/student/student.md @@ -1,10 +1,12 @@ # Student A Student is a person who has enrolled at your institute and you have accepted their application. -The student doctype maintains personal details of the student. - -You can view everything related to a particular student on this page. Eg : Fees, Student Group, etc +The Student doctype maintains detials like personal information, date of birth, address etc. It also records the **Guardian** and sibling details. Student +The student is enrolled in a **Program** when the application is approved. Once the enrollement is done the **Student Applicant** status is update to Admitted. -{next} +You can view every doctype created for a particular student. Eg : Fees, Student Group, etc + + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/articles/difference-between-system-user-and-website-user.md b/erpnext/docs/user/manual/en/setting-up/articles/difference-between-system-user-and-website-user.md new file mode 100644 index 0000000000..a11aa212ff --- /dev/null +++ b/erpnext/docs/user/manual/en/setting-up/articles/difference-between-system-user-and-website-user.md @@ -0,0 +1,19 @@ +# Difference Between System User and Website User + +**Question:** I have added my Employee as a User and have assigned them Roles as well. Still, they are not able to view Dashboard on the login. + +**Answer:** + +There are two type of Users in ERPNext. + +* **System User**: They are Employees of your company. Example of Roles assigned to System Users are Account User, Sales Manager, Purchase User, Support Team etc. + +* **Website User**: They are to parties (like Customer and Suppliers) of your Company. + +Example Website User Roles are Customer and Suppliers. + +How to check if Role is for System User or Website User? + +In the Role master, if field "Desk Access" is checked, that Role is for System User. If Desk Access field is unchecked, then that Role is for Website User. + +Role Desk Permission \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/articles/email-error.md b/erpnext/docs/user/manual/en/setting-up/articles/email-error.md new file mode 100644 index 0000000000..9d5abd021e --- /dev/null +++ b/erpnext/docs/user/manual/en/setting-up/articles/email-error.md @@ -0,0 +1,9 @@ +# Email Error in Sending or Receiving + +In ERPNext, you can customize the Incoming and Outgoing Email Gateway. On saving an Email Account, ERPNext tries establishing a connection with your email gateway. If your ERPNext account is able to connect fine, then Email Account is saved successfully. If not, then you might receive an error as below. + +Email Error + +This indicates that using login credentials and other email gateway details provided in the Email Account, ERPNext is not able to connect to your email server. Please ensure that you have entered valid email credentials for your Email Gateway. Once you have configured Email Account successfully, you should be able to send and receive emails from your ERPNext account fine. + +Note: Your ERPNext account is connected with an ERPNext email server by default. If you don't want to use your own email server, you can continue sending emails using ERPNext email server, without any configuration required in the Email Account. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/articles/index.txt b/erpnext/docs/user/manual/en/setting-up/articles/index.txt index acf15318f8..259229ec8d 100644 --- a/erpnext/docs/user/manual/en/setting-up/articles/index.txt +++ b/erpnext/docs/user/manual/en/setting-up/articles/index.txt @@ -11,4 +11,8 @@ naming-series-current-value overwriting-data-from-data-import-tool rename-user using-custom-domain-on-erpnext -setup-two-factor-authentication \ No newline at end of file +setup-two-factor-authentication +difference-between-system-user-and-website-user +outgoing-email-gateway +print-format-sections +email-error \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/articles/managing-multiple-companies.md b/erpnext/docs/user/manual/en/setting-up/articles/managing-multiple-companies.md index 9971610ab0..e4362fb337 100644 --- a/erpnext/docs/user/manual/en/setting-up/articles/managing-multiple-companies.md +++ b/erpnext/docs/user/manual/en/setting-up/articles/managing-multiple-companies.md @@ -36,5 +36,4 @@ A separate Chart of Account master will be set for each company in the ERPNext. New Company - \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/articles/outgoing-email-gateway.md b/erpnext/docs/user/manual/en/setting-up/articles/outgoing-email-gateway.md new file mode 100644 index 0000000000..9694da12d3 --- /dev/null +++ b/erpnext/docs/user/manual/en/setting-up/articles/outgoing-email-gateway.md @@ -0,0 +1,9 @@ +#Outgoing Email Gateway + +In the ERPNext, you can customize incoming and Outgoing Email Gateway. On saving an Email Account, ERPNext tries establishing a connection with your email gateway. If your ERPNext account is able to connect fine, then Email Account master is saved. If not, then you might receive an error as indicated below. + +Email Setup Error + +This indicates that using login credentials and other email gateway details provided, ERPNext is not able to connect to your email server. Please ensure that you have entered valid email credentials for your Email Gateway. Once you have configured Email Account successfully, you should be able to send and receive emails from your ERPNext account fine. + +Note: Your ERPNext account is connected with ERPNext email server by default. If you don't want to use your own email server, you can continue sending emails using an ERPNext email server. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/articles/print-format-sections.md b/erpnext/docs/user/manual/en/setting-up/articles/print-format-sections.md new file mode 100644 index 0000000000..93542e6261 --- /dev/null +++ b/erpnext/docs/user/manual/en/setting-up/articles/print-format-sections.md @@ -0,0 +1,11 @@ +#Print Format Sections + +**Question:** In the Print Format, I am getting link breaks for each section. How can I disable it? + +Email Setup Error + +**Answer:** To disable line breaks for the section breaks, you should uncheck field "Show Line Breaks after Sections" in its Print Format. + +Print Format Builder > Select Print Format > Edit Settings > Uncheck field "Show Line Breaks after Sections" + +Email Setup Error \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/articles/report-permission-error.md b/erpnext/docs/user/manual/en/setting-up/articles/report-permission-error.md new file mode 100644 index 0000000000..c345d0a7ef --- /dev/null +++ b/erpnext/docs/user/manual/en/setting-up/articles/report-permission-error.md @@ -0,0 +1,17 @@ +**Question:** User has roles like Account User and Account Manager assigned. Still, when accessing  Account Receivable report, User is getting an error message of no permission the territory master. + +Report Permission Error + +**Answer:** + +As per the permission system in ERPNext, for the User to be able to access a form or a report, s(he) should have at-least read permission on all the link field in that form/report. Since Territory is a link field in Account Receivable report, please add a permission rule to let Account User/Manager have at-least Read permission on the Territory master. Please follow below-given steps to resolve this issue. + +1. Roles assigned to User are Account User and Account Manager. + +2. As indicates in the Error message, the user didn't have permission on the territory master. As per the default permission, none of the above role assigned to that User has any permission on the Territory master. + +3. To resolve this issue, I have assigned Account User permission to Read Territory master. + + Permission Manager + +As per this permission update, User should be able to access Account Receivable report fine. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/data/download-backup.md b/erpnext/docs/user/manual/en/setting-up/data/download-backup.md new file mode 100644 index 0000000000..6c98cf34f8 --- /dev/null +++ b/erpnext/docs/user/manual/en/setting-up/data/download-backup.md @@ -0,0 +1,13 @@ +# Download Backup + +In the ERPNext, you can manually download database backup. To get the latest database backup, go to: + +`Setup > Data > Download Backup` + +Backup available for the download is updated in every eight hours. Click on the link to download the backups at a given time. + +Download Backup + +By default three latest backups will be available for the download. If you want to customize no. of backups, then click on "Set Number of Backups". In the System Settings, you can set Number of Backups available for the download at a time. + +Download Backup \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/data/index.txt b/erpnext/docs/user/manual/en/setting-up/data/index.txt index 998b5a2164..d15f9175bb 100644 --- a/erpnext/docs/user/manual/en/setting-up/data/index.txt +++ b/erpnext/docs/user/manual/en/setting-up/data/index.txt @@ -1,2 +1,3 @@ data-import-tool bulk-rename +download-backup diff --git a/erpnext/docs/user/manual/en/setting-up/integrations/razorpay-integration.md b/erpnext/docs/user/manual/en/setting-up/integrations/razorpay-integration.md index 01f29751c8..d41283ce40 100644 --- a/erpnext/docs/user/manual/en/setting-up/integrations/razorpay-integration.md +++ b/erpnext/docs/user/manual/en/setting-up/integrations/razorpay-integration.md @@ -1,26 +1,31 @@ -#Setting up Razorpay +#RazorPay Integration -A payment gateway is an e-commerce application service provider service that authorizes credit card payments for e-businesses, online retailers, bricks and clicks, or traditional brick and mortar. +A payment gateway is an e-commerce application service provider service that authorises credit card payments for e-businesses, online retailers, bricks and clicks, or traditional brick and mortar. A payment gateway facilitates the transfer of information between a payment portal (such as a website, mobile phone or interactive voice response service) and the Front End Processor or acquiring bank. -To setup Razorpay, -`Explore > Integrations > Razorpay Settings` +To setup RazorPay, -#### Setup Razorpay +`Explore > Integrations > RazorPay Settings` + +Razorpay Settings + +#### Setup RazorPay + +To enable RazorPay payment service, you need to configure parameters like API Key, API Secret -To enable Razorpay payment service, you need to configure parameters like API Key, API Secret Razorpay Settings -On enabling service, the system will create Payment Gateway record and Account head in chart of account with account type as Bank. +On enabling service, the system will create Payment Gateway record and Account head in the Chart of Account with account type as Bank. Razorpay COA -Also it will create Payment Gateway Account entry. Payment Gateway Account is configuration hub from this you can set account head from existing COA, default Payment Request email body template. +Also, it will create Payment Gateway Account entry. Payment Gateway Account is configuration hub from this you can set account head from existing COA, default Payment Request email body template. Payment Gateway Account After enabling service and configuring Payment Gateway Account your system is able to accept online payments. ####Supporting transaction currencies -INR + +RazorPay will only work for the company having `INR (Indian Rupee)` as a Currency. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/setup-wizard/index.md b/erpnext/docs/user/manual/en/setting-up/setup-wizard/index.md index 244d893c7b..c05c4af5b6 100644 --- a/erpnext/docs/user/manual/en/setting-up/setup-wizard/index.md +++ b/erpnext/docs/user/manual/en/setting-up/setup-wizard/index.md @@ -1,6 +1,6 @@ # Setup Wizard -The Setup Wizard helps you quickly setup your ERPnext by helping you create your company, Items, Customer, Suppliers and will also setup a basic website with this data. +The Setup Wizard helps you quickly setup ERPnext as per your locale and sets up your organisation. Here is a quick overview of the steps: diff --git a/erpnext/docs/user/manual/en/setting-up/setup-wizard/index.txt b/erpnext/docs/user/manual/en/setting-up/setup-wizard/index.txt index eb7655826e..b2f680a388 100644 --- a/erpnext/docs/user/manual/en/setting-up/setup-wizard/index.txt +++ b/erpnext/docs/user/manual/en/setting-up/setup-wizard/index.txt @@ -1,10 +1,5 @@ step-1-language step-2-currency-and-timezone step-3-user-details +step-4-two-factor-authentication step-5-company-details -step-6-letterhead-and-logo -step-7-add-users -step-8-tax-details -step-9-customer-names -step-10-suppliers -step-11-item diff --git a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-10-suppliers.md b/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-10-suppliers.md deleted file mode 100644 index 364b4d6982..0000000000 --- a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-10-suppliers.md +++ /dev/null @@ -1,12 +0,0 @@ -# Step 10: Suppliers - -Enter a few of your Suppliers' names. - -Suppliers - ---- - -To understand Suppliers in detail visit [Supplier Master](/docs/user/manual/en/buying/supplier.html) - -{next} diff --git a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-11-item.md b/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-11-item.md deleted file mode 100644 index 42d7e3d26d..0000000000 --- a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-11-item.md +++ /dev/null @@ -1,16 +0,0 @@ -# Step 11: Item Names - -In this final step, please enter the names of the Items you buy or sell. - -Add Items - -Please set the group of the item (Product / Service) and unit of measure. Don't worry you will be able to edit all of this later. - ---- - -## Thats it! - -Once you are done with the setup wizard you will see the familiar desktop page. - -{next} diff --git a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-6-letterhead-and-logo.md b/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-6-letterhead-and-logo.md deleted file mode 100644 index 0286a3ee23..0000000000 --- a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-6-letterhead-and-logo.md +++ /dev/null @@ -1,23 +0,0 @@ -# Step 6: Letterhead and Logo - -Attach Company Letterhead and Company Logo. - -Company Logo and Letterhead - ---- - -### Letterhead - -A letterhead is the heading at the top of a sheet of letter paper (stationery). That heading usually consists of a name and an address, and a logo or corporate design. - -Click on the box ‘Attach Letterhead’ . Select the image file from the place it is stored and click enter. - -You may choose to skip this step if your letterhead is not ready. - -To select letterhead later through the setup module, read [Letter-head](/docs/user/manual/en/setting-up/print/letter-head.html) - -#### To "attach as web-link" - -For any attachments in ERPNext, you can also attach as a web-link. If you are using other tools like Dropbox or Google Docs to manage your files, you can set its public link. - -{next} diff --git a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-7-add-users.md b/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-7-add-users.md deleted file mode 100644 index c92721c91b..0000000000 --- a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-7-add-users.md +++ /dev/null @@ -1,7 +0,0 @@ -# Step 7: Add Users - -Add other users and assign them roles based on their job responsibilities. - -Users - -{next} diff --git a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-8-tax-details.md b/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-8-tax-details.md deleted file mode 100644 index dae88e4432..0000000000 --- a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-8-tax-details.md +++ /dev/null @@ -1,21 +0,0 @@ -# Step 8: Tax Details - -Enter any three types of taxes which you regularly pay. This wizard will create a tax master which will calculate the taxes as per the tax-type. - -Tax Details - -Just set the tax name and the standard percentage levied. - ---- - -Some examples of tax types are given below. - -#### VAT - -A value added tax (VAT) is a form of consumption tax. From the perspective of the buyer, it is a tax on the purchase price. From that of the seller, it is a tax only on the value added to a product, material, or a service. From an accounting point of view, by the stage of its manufacture or distribution. The manufacturer remits to the government the difference between these two amounts, and retains the rest for themselves to offset the taxes they had previously paid on the inputs. - -The purpose of VAT is to generate tax revenues to the government similar to the corporate income tax or the personal income tax. For Example: When you shop at a departmental store and avail discount on the products, the store charges you 5% extra on the total bill as the VAT. - -To setup VAT in the setup wizard , simply enter the percentage amount levied by your government. To setup VAT at a later stage read [setting-up-taxes](/docs/user/manual/en/setting-up/setting-up-taxes.html) - -{next} diff --git a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-9-customer-names.md b/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-9-customer-names.md deleted file mode 100644 index e3489433fc..0000000000 --- a/erpnext/docs/user/manual/en/setting-up/setup-wizard/step-9-customer-names.md +++ /dev/null @@ -1,22 +0,0 @@ -# Step 9: Customers - -Enter your Customer names and the contact person from that organisation. - - -Customers - ---- - -#### Difference between a customer name and a contact name - -A customer name is the name of the organisation and a contact name is the name of the person from that organisation. - -For Example: If American Power Mills is an organisation name and their founder Shiv Agarwal has installed ERPNext on his system. Then, - -Customer Name: American Power Mills - -Contact Name: Shiv Agarwal - -To understand Customer in detail visit [Customer Details](/docs/user/manual/en/CRM/customer.html) - -{next} diff --git a/erpnext/docs/user/manual/en/setting-up/users-and-permissions/admin-user.md b/erpnext/docs/user/manual/en/setting-up/users-and-permissions/admin-user.md new file mode 100644 index 0000000000..3a87e02afe --- /dev/null +++ b/erpnext/docs/user/manual/en/setting-up/users-and-permissions/admin-user.md @@ -0,0 +1,7 @@ +# Administrator User + +If your ERPNext account is hosted with us (Frappe Technologies Pvt. Ltd.), then you won't be able to access your ERPNext account as an Administrator. For the hosted account, access via Administrator User us reserved with us. + +1. For the hosted account, upgrades are managed from the backend. We reserve admin login credential with us so that we can upgrade all the hosted customer's ERPNext accounts from the backend. + +2. Since on a single server, we host have many customer's ERPNext accounts, as a security measure, we cannot share the credentials for administrator account with any hosted user. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/users-and-permissions/index.txt b/erpnext/docs/user/manual/en/setting-up/users-and-permissions/index.txt index 74243df520..2477fca4ea 100644 --- a/erpnext/docs/user/manual/en/setting-up/users-and-permissions/index.txt +++ b/erpnext/docs/user/manual/en/setting-up/users-and-permissions/index.txt @@ -3,3 +3,4 @@ role-based-permissions user-permissions role-permisison-for-page-and-report sharing +admin-user \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/stock/articles/delivery-note-stock-error.md b/erpnext/docs/user/manual/en/stock/articles/delivery-note-stock-error.md new file mode 100644 index 0000000000..afb6de92d8 --- /dev/null +++ b/erpnext/docs/user/manual/en/stock/articles/delivery-note-stock-error.md @@ -0,0 +1,7 @@ +# Delivery Note Negative Stock Error + +**Question**: When submitting a Delivery Note, receiving a message says that item's stock is insufficient, but we have item's stock available in the Warehouse. + +**Answer**: On submission of Delivery Note, stock level is checked as on Posting Date and Posting Time of a Delivery Note. It's possible that you have stock of an Item available in the Warehouse. But if you are creating back-dated Delivery Note, and if item was not available in the warehouse on the Posting Date and Posting Time of Delivery Note, you are likely to receive an error message on the negative stock. You can refer to the Stock Ledger report to confirm the same. + +If this is the case, you should edit the Posting Date and Time of a Delivery Note, and ensure that it is after the Posting Date and Time of item's receipt entry. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/stock/articles/index.txt b/erpnext/docs/user/manual/en/stock/articles/index.txt index df779de628..acf1375214 100644 --- a/erpnext/docs/user/manual/en/stock/articles/index.txt +++ b/erpnext/docs/user/manual/en/stock/articles/index.txt @@ -10,4 +10,8 @@ repack-entry serial-no-naming stock-entry-purpose stock-level-report -track-items-using-barcode \ No newline at end of file +track-items-using-barcode +stock-received-but-not-billed +return-rejected-item +item-valuation-transactions +delivery-note-stock-error \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/stock/articles/item-valuation-transactions.md b/erpnext/docs/user/manual/en/stock/articles/item-valuation-transactions.md new file mode 100644 index 0000000000..5cc6529d89 --- /dev/null +++ b/erpnext/docs/user/manual/en/stock/articles/item-valuation-transactions.md @@ -0,0 +1,17 @@ +# Item Valuation Methods and Transactions + +In ERPNext, Item's stock valuation is updated on the creation of one of the following transaction. + +1. Purchase Receipt +2. Stock Entry of type Material Receipt +3. Stock Reconciliation made for updating stock opening balance + +You can select valuation method based on which item's value will be calculated. Valuation Method can be set globally for all the items from the Stock Settings. + +Download Backup + +You can also set Valuation Method in the item master, especially when a valuation method for an item is different from the default Method. + +Download Backup + +[Click here to learn about the valuation methods available in the ERPNext, and how it works.](https://frappe.io/blog/erpnext-features/inventory-valuation-method-fifo-vs-moving-average) diff --git a/erpnext/docs/user/manual/en/stock/articles/return-rejected-item.md b/erpnext/docs/user/manual/en/stock/articles/return-rejected-item.md new file mode 100644 index 0000000000..aaaec2dea0 --- /dev/null +++ b/erpnext/docs/user/manual/en/stock/articles/return-rejected-item.md @@ -0,0 +1,13 @@ +# Return Rejected Items + +In the Purchase Receipt, you can receive the Items in the Accepted or the Rejected Warehouse. + +If you are creating Purchase Return for the items received in the Rejected Warehouse, then create return entry following these steps. + +1. In the Purchase Receipt Item table, for the item to be returned, in the Received Qty field, enter return entry in negative. +2. In the Accepted Warehouse field, set value as zero. +3. In the Rejected Warehouse field, set the quantity to be returned in negative. + +For detailed steps on how to create Purchase Return Entry for the Rejected Item, refer to the below example. + +Returning Rejected Items \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/stock/articles/stock-received-but-not-billed.md b/erpnext/docs/user/manual/en/stock/articles/stock-received-but-not-billed.md new file mode 100644 index 0000000000..25ef3b8aa6 --- /dev/null +++ b/erpnext/docs/user/manual/en/stock/articles/stock-received-but-not-billed.md @@ -0,0 +1,9 @@ +# Purpose of Stock Received but not Billed + +When purchased items are received, an accounts posting is done based on the value of the purchased items in the Stock-in-hand / fixed-assets account. When you sell and deliver those items, an expense (cost-of-goods-sold) is booked, equal to the buying cost of the items. + +As stock balance increases through Purchase Receipt, Warehouse account is debited and an adjustment account called **Stock Received But Not Billed** account is credited. At the same time, the negative expense is booked in account **Expense included in Valuation** for the amount added for valuation purpose, to avoid double expense booking. + +On receiving Bill from the supplier, you will make Purchase Invoice against a Purchase Receipt. Here **Stock Received But Not Billed** account is debited, hence nullifies the balance in the Stock Received but not Billed Account. + +The balance in the Stock Received but not Billed account indicates the value of items for which Purchase Receipt has been made, but billing is pending. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/using-erpnext/articles/index.txt b/erpnext/docs/user/manual/en/using-erpnext/articles/index.txt index 4ca21aa969..9dc7df3f31 100644 --- a/erpnext/docs/user/manual/en/using-erpnext/articles/index.txt +++ b/erpnext/docs/user/manual/en/using-erpnext/articles/index.txt @@ -8,4 +8,5 @@ bulk-rename renaming-documents search-filter tree-master-renaming -pos-view \ No newline at end of file +pos-view +letter-head-in-the-report \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/using-erpnext/articles/letter-head-in-the-report.md b/erpnext/docs/user/manual/en/using-erpnext/articles/letter-head-in-the-report.md new file mode 100644 index 0000000000..4f8b2e9ea3 --- /dev/null +++ b/erpnext/docs/user/manual/en/using-erpnext/articles/letter-head-in-the-report.md @@ -0,0 +1,15 @@ +# Letter Head in the Report's Print Format + +In the reports, Letter Head is fetched from the Company master. To have company's Letter Head fetched correctly in the report, please ensure that you have updated default Letter Head in the Company master. + +`Explore > Accounts > Company` + +Company Letter + +In a Company master, if no Letter Head is set as default, then in the reports, Letter Head having Default field checked will be fetched. + +Default Letter Head + +If you are managing multiple companies in a single ERPNext account, then ensure that for each Company, default Letter Head is set in the Company master. + +After updating Letter Head in the Company master, refresh your ERPNext account, and then check the print format of a report. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/website/articles/website-banner.md b/erpnext/docs/user/manual/en/website/articles/website-banner.md new file mode 100644 index 0000000000..514e23e58d --- /dev/null +++ b/erpnext/docs/user/manual/en/website/articles/website-banner.md @@ -0,0 +1,9 @@ +# Website Banner Resizing + +Each ERPNext account website automatically generated from it. On a website, logo is set based on logo image selected in the Setup Wizard. You can change or edit property for your company's logo from the Website Settings. + +`Explore > Website > Website Settings` + +For the exact steps on how to upload a Website Banner and resize it, please refer to the help given below. + +Website Banner image \ No newline at end of file diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 7e65fc9262..e5d9ef9e4f 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -27,6 +27,8 @@ doctype_js = { # setup wizard setup_wizard_requires = "assets/erpnext/js/setup_wizard.js" setup_wizard_complete = "erpnext.setup.setup_wizard.setup_wizard.setup_complete" +setup_wizard_success = "erpnext.setup.setup_wizard.setup_wizard.setup_success" +setup_wizard_test = "erpnext.setup.setup_wizard.test_setup_wizard.run_setup_wizard_test" before_install = "erpnext.setup.install.check_setup_wizard_not_completed" after_install = "erpnext.setup.install.after_install" @@ -34,6 +36,8 @@ after_install = "erpnext.setup.install.after_install" boot_session = "erpnext.startup.boot.boot_session" notification_config = "erpnext.startup.notifications.get_notification_config" get_help_messages = "erpnext.utilities.activation.get_help_messages" +get_user_progress_slides = "erpnext.utilities.user_progress.get_user_progress_slides" +update_and_get_user_progress = "erpnext.utilities.user_progress_utils.update_default_domain_actions_and_get_state" on_session_creation = "erpnext.shopping_cart.utils.set_cart_count" on_logout = "erpnext.shopping_cart.utils.clear_cart_count" diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index a078ef2033..03626cdc5c 100755 --- a/erpnext/hr/doctype/employee/employee.py +++ b/erpnext/hr/doctype/employee/employee.py @@ -289,3 +289,15 @@ def create_user(employee, user = None): }) user.insert() return user.name + +def get_employee_emails(employee_list): + '''Returns list of employee emails either based on user_id or company_email''' + employee_emails = [] + for employee in employee_list: + if not employee: + continue + user, email = frappe.db.get_value('Employee', employee, ['user_id', 'company_email']) + if user or email: + employee_emails.append(user or email) + + return employee_emails \ No newline at end of file diff --git a/erpnext/hr/doctype/process_payroll/process_payroll.py b/erpnext/hr/doctype/process_payroll/process_payroll.py index 7575ee45b4..55c0cce59f 100644 --- a/erpnext/hr/doctype/process_payroll/process_payroll.py +++ b/erpnext/hr/doctype/process_payroll/process_payroll.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe from dateutil.relativedelta import relativedelta -from frappe.utils import cint, nowdate, add_days, getdate, fmt_money, add_to_date, DATE_FORMAT +from frappe.utils import cint, flt, nowdate, add_days, getdate, fmt_money, add_to_date, DATE_FORMAT from frappe import _ from erpnext.accounts.utils import get_fiscal_year @@ -260,85 +260,97 @@ class ProcessPayroll(Document): loan_amounts = self.get_total_salary_and_loan_amounts() loan_accounts = self.get_loan_accounts() jv_name = "" + precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency") if earnings or deductions: journal_entry = frappe.new_doc('Journal Entry') journal_entry.voucher_type = 'Journal Entry' - journal_entry.user_remark = _('Accural Journal Entry for salaries from {0} to {1}').format(self.start_date, - self.end_date) + journal_entry.user_remark = _('Accural Journal Entry for salaries from {0} to {1}')\ + .format(self.start_date, self.end_date) journal_entry.company = self.company journal_entry.posting_date = nowdate() - account_amt_list = [] - adjustment_amt = 0 - for acc, amt in earnings.items(): - adjustment_amt = adjustment_amt+amt - account_amt_list.append({ + accounts = [] + payable_amount = 0 + + # Earnings + for acc, amount in earnings.items(): + payable_amount += flt(amount, precision) + accounts.append({ "account": acc, - "debit_in_account_currency": amt, + "debit_in_account_currency": flt(amount, precision), "cost_center": self.cost_center, "project": self.project }) + + # Deductions for acc, amt in deductions.items(): - adjustment_amt = adjustment_amt-amt - account_amt_list.append({ + payable_amount -= flt(amount, precision) + accounts.append({ "account": acc, - "credit_in_account_currency": amt, + "credit_in_account_currency": flt(amount, precision), "cost_center": self.cost_center, "project": self.project }) - #employee loan + + # Employee loan if loan_amounts.total_loan_repayment: - account_amt_list.append({ + accounts.append({ "account": loan_accounts.employee_loan_account, "credit_in_account_currency": loan_amounts.total_principal_amount }) - account_amt_list.append({ + accounts.append({ "account": loan_accounts.interest_income_account, "credit_in_account_currency": loan_amounts.total_interest_amount, "cost_center": self.cost_center, "project": self.project }) - adjustment_amt = adjustment_amt-(loan_amounts.total_loan_repayment) - - account_amt_list.append({ - "account": default_payroll_payable_account, - "credit_in_account_currency": adjustment_amt - }) - journal_entry.set("accounts", account_amt_list) + payable_amount -= flt(loan_amounts.total_loan_repayment, precision) + + # Payable amount + accounts.append({ + "account": default_payroll_payable_account, + "credit_in_account_currency": flt(payable_amount, precision) + }) + + journal_entry.set("accounts", accounts) journal_entry.save() + try: journal_entry.submit() jv_name = journal_entry.name self.update_salary_slip_status(jv_name = jv_name) except Exception as e: frappe.msgprint(e) + return jv_name def make_payment_entry(self): self.check_permission('write') total_salary_amount = self.get_total_salary_and_loan_amounts() default_payroll_payable_account = self.get_default_payroll_payable_account() + precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency") if total_salary_amount.rounded_total: journal_entry = frappe.new_doc('Journal Entry') journal_entry.voucher_type = 'Bank Entry' - journal_entry.user_remark = _('Payment of salary from {0} to {1}').format(self.start_date, - self.end_date) + journal_entry.user_remark = _('Payment of salary from {0} to {1}')\ + .format(self.start_date, self.end_date) journal_entry.company = self.company journal_entry.posting_date = nowdate() - account_amt_list = [] - - account_amt_list.append({ + payment_amount = flt(total_salary_amount.rounded_total, precision) + + journal_entry.set("accounts", [ + { "account": self.payment_account, - "credit_in_account_currency": total_salary_amount.rounded_total - }) - account_amt_list.append({ + "credit_in_account_currency": payment_amount + }, + { "account": default_payroll_payable_account, - "debit_in_account_currency": total_salary_amount.rounded_total - }) - journal_entry.set("accounts", account_amt_list) + "debit_in_account_currency": payment_amount + } + ]) return journal_entry.as_dict() else: frappe.msgprint( diff --git a/erpnext/hr/doctype/process_payroll/test_process_payroll.py b/erpnext/hr/doctype/process_payroll/test_process_payroll.py index 1f9ba26748..cac43c4d47 100644 --- a/erpnext/hr/doctype/process_payroll/test_process_payroll.py +++ b/erpnext/hr/doctype/process_payroll/test_process_payroll.py @@ -16,10 +16,13 @@ class TestProcessPayroll(unittest.TestCase): fiscal_year = "_Test Fiscal Year 2016" for data in frappe.get_all('Salary Component', fields = ["name"]): - if not frappe.db.get_value('Salary Component Account', {'parent': data.name, 'company': erpnext.get_default_company()}, 'name'): + if not frappe.db.get_value('Salary Component Account', + {'parent': data.name, 'company': erpnext.get_default_company()}, 'name'): get_salary_component_account(data.name) - payment_account = frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name") + payment_account = frappe.get_value('Account', + {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name") + if not frappe.db.get_value("Salary Slip", {"start_date": "2016-11-01", "end_date": "2016-11-30"}): process_payroll = frappe.get_doc("Process Payroll", "Process Payroll") process_payroll.company = erpnext.get_default_company() diff --git a/erpnext/hr/doctype/training_event/test_training_event.js b/erpnext/hr/doctype/training_event/tests/test_training_event.js similarity index 100% rename from erpnext/hr/doctype/training_event/test_training_event.js rename to erpnext/hr/doctype/training_event/tests/test_training_event.js diff --git a/erpnext/hr/doctype/training_event/tests/test_training_event_attandance.js b/erpnext/hr/doctype/training_event/tests/test_training_event_attandance.js new file mode 100644 index 0000000000..6364308f73 --- /dev/null +++ b/erpnext/hr/doctype/training_event/tests/test_training_event_attandance.js @@ -0,0 +1,40 @@ +QUnit.module('hr'); + +QUnit.test("test: Training Event", function (assert) { + // number of asserts + assert.expect(1); + let done = assert.async(); + + frappe.run_serially([ + // insert a new Training Event + () => frappe.set_route("List", "Training Event", "List"), + () => frappe.new_doc("Training Event"), + () => frappe.timeout(1), + () => frappe.click_link('Edit in full page'), + () => cur_frm.set_value("event_name", "Test Event " + frappe.utils.get_random(10)), + () => cur_frm.set_value("start_time", "2017-07-26, 2:00 pm PDT"), + () => cur_frm.set_value("end_time", "2017-07-26, 2:30 pm PDT"), + () => cur_frm.set_value("introduction", "This is a test report"), + () => cur_frm.set_value("location", "Fake office"), + () => frappe.click_button('Add Row'), + () => frappe.db.get_value('Employee', {'employee_name':'Test Employee 1'}, 'name'), + (r) => { + console.log(r); + return cur_frm.fields_dict.employees.grid.grid_rows[0].doc.employee = r.message.name; + }, + () => { + return cur_frm.fields_dict.employees.grid.grid_rows[0].doc.attendance = "Optional"; + }, + () => frappe.click_button('Save'), + () => frappe.timeout(2), + () => frappe.click_button('Submit'), + () => frappe.timeout(2), + () => frappe.click_button('Yes'), + () => frappe.timeout(1), + () => { + assert.equal(cur_frm.doc.docstatus, 1); + }, + () => done() + ]); + +}); \ No newline at end of file diff --git a/erpnext/hr/doctype/training_event/training_event.js b/erpnext/hr/doctype/training_event/training_event.js index ebe0c7907c..6a6e8fe0a6 100644 --- a/erpnext/hr/doctype/training_event/training_event.js +++ b/erpnext/hr/doctype/training_event/training_event.js @@ -18,4 +18,4 @@ frappe.ui.form.on('Training Event', { }); } } -}); +}); \ 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 03b58b4802..7be9d974fe 100644 --- a/erpnext/hr/doctype/training_event/training_event.json +++ b/erpnext/hr/doctype/training_event/training_event.json @@ -25,7 +25,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 0, "label": "Event Name", "length": 0, @@ -55,7 +55,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 1, "label": "Event Status", "length": 0, @@ -115,12 +115,12 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 1, "label": "Type", "length": 0, "no_copy": 0, - "options": "Seminar\nTheory\nWorkshop\nConference\nExam\nInternet", + "options": "Seminar\nTheory\nWorkshop\nConference\nExam\nInternet\nSelf-Study", "permlevel": 0, "precision": "", "print_hide": 0, @@ -386,7 +386,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 1, "label": "Location", "length": 0, @@ -581,37 +581,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Will send an email about the event to employees with status 'Open'", - "fieldname": "send_email", - "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": "Send 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": 1, @@ -672,6 +641,37 @@ "search_index": 0, "set_only_once": 0, "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "employee_emails", + "fieldtype": "Small Text", + "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": "Employee Emails", + "length": 0, + "no_copy": 0, + "options": "Email", + "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 } ], "has_web_view": 0, @@ -684,7 +684,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-05-29 06:13:38.411039", + "modified": "2017-08-11 03:11:25.768563", "modified_by": "Administrator", "module": "HR", "name": "Training Event", diff --git a/erpnext/hr/doctype/training_event/training_event.py b/erpnext/hr/doctype/training_event/training_event.py index 27ae8cf549..cc568414a0 100644 --- a/erpnext/hr/doctype/training_event/training_event.py +++ b/erpnext/hr/doctype/training_event/training_event.py @@ -3,24 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -from frappe import _ from frappe.model.document import Document +from erpnext.hr.doctype.employee.employee import get_employee_emails class TrainingEvent(Document): - def on_update(self): - self.invite_employee() - - def on_update_after_submit(self): - self.invite_employee() - - def invite_employee(self): - if self.event_status == "Scheduled" and self.send_email: - subject = _("""You are invited for to attend {0} - {1} scheduled from {2} to {3} at {4}."""\ - .format(self.type, self.event_name, self.start_time, self.end_time, self.location)) - - for emp in self.employees: - if emp.status== "Open": - frappe.sendmail(frappe.db.get_value("Employee", emp.employee, "company_email"), \ - subject=subject, content= self.introduction) - emp.status= "Invited" \ No newline at end of file + def validate(self): + self.employee_emails = ', '.join(get_employee_emails([d.employee + for d in self.employees])) diff --git a/erpnext/hr/doctype/training_event_employee/training_event_employee.json b/erpnext/hr/doctype/training_event_employee/training_event_employee.json index 575d0e7582..a8a72b1a70 100644 --- a/erpnext/hr/doctype/training_event_employee/training_event_employee.json +++ b/erpnext/hr/doctype/training_event_employee/training_event_employee.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -11,6 +12,7 @@ "editable_grid": 1, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -21,6 +23,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Employee", @@ -40,6 +43,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -50,6 +54,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Employee Name", @@ -69,6 +74,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -79,6 +85,7 @@ "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, @@ -96,6 +103,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -107,12 +115,44 @@ "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": 1, - "options": "Open\nInvited\nConfirmed\nAttended\nWithdrawn", + "options": "Open\nInvited\nCompleted\nFeedback Submitted", + "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": "attendance", + "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": "Attendance", + "length": 0, + "no_copy": 0, + "options": "Mandatory\nOptional", "permlevel": 0, "precision": "", "print_hide": 0, @@ -126,17 +166,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 0, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-12-14 11:43:40.996578", + "modified": "2017-08-11 03:36:22.738253", "modified_by": "Administrator", "module": "HR", "name": "Training Event Employee", @@ -146,7 +186,9 @@ "quick_entry": 1, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", + "track_changes": 0, "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/hr/doctype/training_feedback/training_feedback.py b/erpnext/hr/doctype/training_feedback/training_feedback.py index 2a0403bd53..20a3bc5652 100644 --- a/erpnext/hr/doctype/training_feedback/training_feedback.py +++ b/erpnext/hr/doctype/training_feedback/training_feedback.py @@ -5,6 +5,19 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document +from frappe import _ class TrainingFeedback(Document): - pass + def validate(self): + training_event = frappe.get_doc("Training Event", self.training_event) + if training_event.docstatus != 1: + frappe.throw(_('{0} must be submitted').format(_('Training Event'))) + + def on_submit(self): + training_event = frappe.get_doc("Training Event", self.training_event) + for e in training_event.employees: + if e.employee == self.employee: + training_event.status = 'Feedback Submitted' + break + + training_event.update_after_submit() diff --git a/erpnext/hr/doctype/training_result/test_training_result.js b/erpnext/hr/doctype/training_result/test_training_result.js new file mode 100644 index 0000000000..cb1d7fb27a --- /dev/null +++ b/erpnext/hr/doctype/training_result/test_training_result.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Training Result", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Training Result + () => frappe.tests.make('Training Result', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/hr/doctype/training_result/training_result.json b/erpnext/hr/doctype/training_result/training_result.json index e5fbb5fd42..41142b59e6 100644 --- a/erpnext/hr/doctype/training_result/training_result.json +++ b/erpnext/hr/doctype/training_result/training_result.json @@ -26,7 +26,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 0, "label": "Training Event", "length": 0, @@ -133,6 +133,37 @@ "search_index": 0, "set_only_once": 0, "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "employee_emails", + "fieldtype": "Small Text", + "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": "Employee Emails", + "length": 0, + "no_copy": 0, + "options": "Email", + "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 } ], "has_web_view": 0, @@ -145,7 +176,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-06-15 08:16:01.566531", + "modified": "2017-08-11 03:53:21.283968", "modified_by": "Administrator", "module": "HR", "name": "Training Result", diff --git a/erpnext/hr/doctype/training_result/training_result.py b/erpnext/hr/doctype/training_result/training_result.py index 36c3cb93bc..7cdc51f801 100644 --- a/erpnext/hr/doctype/training_result/training_result.py +++ b/erpnext/hr/doctype/training_result/training_result.py @@ -6,19 +6,27 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document +from erpnext.hr.doctype.employee.employee import get_employee_emails class TrainingResult(Document): + def validate(self): + training_event = frappe.get_doc("Training Event", self.training_event) + if training_event.docstatus != 1: + frappe.throw(_('{0} must be submitted').format(_('Training Event'))) + + self.employee_emails = ', '.join(get_employee_emails([d.employee + for d in self.employees])) + def on_submit(self): - self.send_result() - - def send_result(self): - for emp in self.employees: - message = "Thank You for attending {0}.".format(self.training_event) - if emp.grade: - message = message + "Your grade: {0}".format(emp.grade) - frappe.sendmail(frappe.db.get_value("Employee", emp.employee, "company_email"), \ - subject=_("{0} Results".format(self.training_event)), \ - content=message) + training_event = frappe.get_doc("Training Event", self.training_event) + training_event.status = 'Completed' + for e in self.employees: + for e1 in training_event.employees: + if e1.employee == e.employee: + e1.status = 'Completed' + break + + training_event.save() @frappe.whitelist() def get_employees(training_event): diff --git a/erpnext/docs/user/manual/en/setting-up/setup-wizard/__init__.py b/erpnext/hr/email_alert/__init__.py similarity index 100% rename from erpnext/docs/user/manual/en/setting-up/setup-wizard/__init__.py rename to erpnext/hr/email_alert/__init__.py diff --git a/erpnext/hr/email_alert/training_feedback/__init__.py b/erpnext/hr/email_alert/training_feedback/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/hr/email_alert/training_feedback/training_feedback.html b/erpnext/hr/email_alert/training_feedback/training_feedback.html new file mode 100644 index 0000000000..fd8fef9e82 --- /dev/null +++ b/erpnext/hr/email_alert/training_feedback/training_feedback.html @@ -0,0 +1,6 @@ +

{{ _("Hello") }},

+ +

You attended training {{ frappe.utils.get_link_to_form( + "Training Event", doc.training_event) }}

+ +

{{ _("Please share your feedback to the training by clicking on 'Training Feedback' and then 'New'") }}

\ No newline at end of file diff --git a/erpnext/hr/email_alert/training_feedback/training_feedback.json b/erpnext/hr/email_alert/training_feedback/training_feedback.json new file mode 100644 index 0000000000..51f6cedfec --- /dev/null +++ b/erpnext/hr/email_alert/training_feedback/training_feedback.json @@ -0,0 +1,24 @@ +{ + "attach_print": 0, + "creation": "2017-08-11 03:17:11.769210", + "days_in_advance": 0, + "docstatus": 0, + "doctype": "Email Alert", + "document_type": "Training Result", + "enabled": 1, + "event": "Submit", + "idx": 0, + "is_standard": 1, + "message": "

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

\n

{{ message }}

\n\n

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

\n{{_(\"Event Name\")}}: {{ name }}\n
{{_(\"Event Location\")}}: {{ location }}\n
{{_(\"Start Time\")}}: {{ start_time }}\n
{{_(\"End Time\")}}: {{ end_time }}\n
{{_(\"Attendance\")}}: {{ attendance }}\n", + "modified": "2017-08-11 04:26:58.194793", + "modified_by": "Administrator", + "module": "HR", + "name": "Training Feedback", + "owner": "Administrator", + "recipients": [ + { + "email_by_document_field": "employee_emails" + } + ], + "subject": "Please Share your Feedback For {{ doc.training_event }}" +} \ No newline at end of file diff --git a/erpnext/hr/email_alert/training_feedback/training_feedback.md b/erpnext/hr/email_alert/training_feedback/training_feedback.md new file mode 100644 index 0000000000..bcadf7df59 --- /dev/null +++ b/erpnext/hr/email_alert/training_feedback/training_feedback.md @@ -0,0 +1,9 @@ +

{{_("Training Event")}}

+

{{ message }}

+ +

{{_("Details")}}

+{{_("Event Name")}}: {{ name }} +
{{_("Event Location")}}: {{ location }} +
{{_("Start Time")}}: {{ start_time }} +
{{_("End Time")}}: {{ end_time }} +
{{_("Attendance")}}: {{ attendance }} diff --git a/erpnext/hr/email_alert/training_feedback/training_feedback.py b/erpnext/hr/email_alert/training_feedback/training_feedback.py new file mode 100644 index 0000000000..2334f8b26d --- /dev/null +++ b/erpnext/hr/email_alert/training_feedback/training_feedback.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +import frappe + +def get_context(context): + # do your magic here + pass diff --git a/erpnext/hr/email_alert/training_scheduled/__init__.py b/erpnext/hr/email_alert/training_scheduled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/hr/email_alert/training_scheduled/training_scheduled.html b/erpnext/hr/email_alert/training_scheduled/training_scheduled.html new file mode 100644 index 0000000000..b1aeb2c873 --- /dev/null +++ b/erpnext/hr/email_alert/training_scheduled/training_scheduled.html @@ -0,0 +1,9 @@ +

{{_("Training Event")}}

+ +

{{ doc.introduction }}

+ +

{{_("Details")}}

+{{_("Event Name")}}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }} +
{{_("Event Location")}}: {{ doc.location }} +
{{_("Start Time")}}: {{ doc.start_time }} +
{{_("End Time")}}: {{ doc.end_time }} diff --git a/erpnext/hr/email_alert/training_scheduled/training_scheduled.json b/erpnext/hr/email_alert/training_scheduled/training_scheduled.json new file mode 100644 index 0000000000..e1631f8683 --- /dev/null +++ b/erpnext/hr/email_alert/training_scheduled/training_scheduled.json @@ -0,0 +1,24 @@ +{ + "attach_print": 0, + "creation": "2017-08-11 03:13:40.519614", + "days_in_advance": 0, + "docstatus": 0, + "doctype": "Email Alert", + "document_type": "Training Event", + "enabled": 1, + "event": "Submit", + "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", + "module": "HR", + "name": "Training Scheduled", + "owner": "Administrator", + "recipients": [ + { + "email_by_document_field": "employee_emails" + } + ], + "subject": "Training Scheduled: {{ doc.name }}" +} \ No newline at end of file diff --git a/erpnext/hr/email_alert/training_scheduled/training_scheduled.md b/erpnext/hr/email_alert/training_scheduled/training_scheduled.md new file mode 100644 index 0000000000..bcadf7df59 --- /dev/null +++ b/erpnext/hr/email_alert/training_scheduled/training_scheduled.md @@ -0,0 +1,9 @@ +

{{_("Training Event")}}

+

{{ message }}

+ +

{{_("Details")}}

+{{_("Event Name")}}: {{ name }} +
{{_("Event Location")}}: {{ location }} +
{{_("Start Time")}}: {{ start_time }} +
{{_("End Time")}}: {{ end_time }} +
{{_("Attendance")}}: {{ attendance }} diff --git a/erpnext/hr/email_alert/training_scheduled/training_scheduled.py b/erpnext/hr/email_alert/training_scheduled/training_scheduled.py new file mode 100644 index 0000000000..2334f8b26d --- /dev/null +++ b/erpnext/hr/email_alert/training_scheduled/training_scheduled.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +import frappe + +def get_context(context): + # do your magic here + pass diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index c58c89cd5d..32c357f25c 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -5,7 +5,10 @@ frappe.provide("erpnext.bom"); frappe.ui.form.on("BOM", { setup: function(frm) { - frm.add_fetch('buying_price_list', 'currency', 'currency'); + frm.add_fetch("item", "description", "description"); + frm.add_fetch("item", "image", "image"); + frm.add_fetch("item", "item_name", "item_name"); + frm.add_fetch("item", "stock_uom", "uom"); frm.set_query("bom_no", "items", function() { return { @@ -23,6 +26,38 @@ frappe.ui.form.on("BOM", { } }; }); + + frm.set_query("item", function() { + return { + query: "erpnext.controllers.queries.item_query" + }; + }); + + frm.set_query("project", function() { + return{ + filters:[ + ['Project', 'status', 'not in', 'Completed, Cancelled'] + ] + }; + }); + + frm.set_query("item_code", "items", function() { + return { + query: "erpnext.controllers.queries.item_query", + filters: [["Item", "name", "!=", cur_frm.doc.item]] + }; + }); + + frm.set_query("bom_no", "items", function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + return { + filters: { + 'item': d.item_code, + 'is_active': 1, + 'docstatus': 1 + } + }; + }); }, onload_post_render: function(frm) { @@ -69,14 +104,14 @@ frappe.ui.form.on("BOM", { }); erpnext.bom.BomController = erpnext.TransactionController.extend({ - conversion_rate: function(doc, cdt, cdn) { + conversion_rate: function(doc) { if(this.frm.doc.currency === this.get_company_currency()) { this.frm.set_value("conversion_rate", 1.0); } else { erpnext.bom.update_cost(doc); } }, - + item_code: function(doc, cdt, cdn){ var scrap_items = false; var child = locals[cdt][cdn]; @@ -90,39 +125,34 @@ erpnext.bom.BomController = erpnext.TransactionController.extend({ get_bom_material_detail(doc, cdt, cdn, scrap_items); }, - conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) { + conversion_factor: function(doc, cdt, cdn) { if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) { var item = frappe.get_doc(cdt, cdn); frappe.model.round_floats_in(item, ["qty", "conversion_factor"]); item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item)); refresh_field("stock_qty", item.name, item.parentfield); this.toggle_conversion_factor(item); + this.frm.events.update_cost(this.frm); } }, -}) +}); $.extend(cur_frm.cscript, new erpnext.bom.BomController({frm: cur_frm})); -cur_frm.add_fetch("item", "description", "description"); -cur_frm.add_fetch("item", "image", "image"); -cur_frm.add_fetch("item", "item_name", "item_name"); -cur_frm.add_fetch("item", "stock_uom", "uom"); - - -cur_frm.cscript.hour_rate = function(doc, dt, dn) { +cur_frm.cscript.hour_rate = function(doc) { erpnext.bom.calculate_op_cost(doc); erpnext.bom.calculate_total(doc); -} +}; cur_frm.cscript.time_in_mins = cur_frm.cscript.hour_rate; cur_frm.cscript.bom_no = function(doc, cdt, cdn) { get_bom_material_detail(doc, cdt, cdn, false); -} +}; cur_frm.cscript.is_default = function(doc) { if (doc.is_default) cur_frm.set_value("is_active", 1); -} +}; var get_bom_material_detail= function(doc, cdt, cdn, scrap_items) { var d = locals[cdt][cdn]; @@ -141,6 +171,7 @@ var get_bom_material_detail= function(doc, cdt, cdn, scrap_items) { $.extend(d, r.message); refresh_field("items"); refresh_field("scrap_items"); + doc = locals[doc.doctype][doc.name]; erpnext.bom.calculate_rm_cost(doc); erpnext.bom.calculate_scrap_materials_cost(doc); @@ -149,13 +180,13 @@ var get_bom_material_detail= function(doc, cdt, cdn, scrap_items) { freeze: true }); } -} +}; -cur_frm.cscript.qty = function(doc, cdt, cdn) { +cur_frm.cscript.qty = function(doc) { erpnext.bom.calculate_rm_cost(doc); erpnext.bom.calculate_scrap_materials_cost(doc); erpnext.bom.calculate_total(doc); -} +}; cur_frm.cscript.rate = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; @@ -173,14 +204,14 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) { erpnext.bom.calculate_scrap_materials_cost(doc); erpnext.bom.calculate_total(doc); } -} +}; erpnext.bom.update_cost = function(doc) { erpnext.bom.calculate_op_cost(doc); erpnext.bom.calculate_rm_cost(doc); erpnext.bom.calculate_scrap_materials_cost(doc); erpnext.bom.calculate_total(doc); -} +}; erpnext.bom.calculate_op_cost = function(doc) { var op = doc.operations || []; @@ -189,7 +220,7 @@ erpnext.bom.calculate_op_cost = function(doc) { for(var i=0;i { + var args = dialog.get_values(); + if(!args) return; + dialog.hide(); + return frappe.call({ + type: "GET", + method: "erpnext.projects.doctype.timesheet.timesheet.make_sales_invoice", + args: { + "source_name": frm.doc.name, + "item_code": args.item_code, + "customer": args.customer + }, + freeze: true, + callback: function(r) { + if(!r.exc) { + frappe.model.sync(r.message); + frappe.set_route("Form", r.message.doctype, r.message.name); + } + } + }) + }) + + dialog.show(); }, make_salary_slip: function(frm) { diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 16abd2499c..ad566d5ac1 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -323,17 +323,32 @@ def get_timesheet_data(name, project): } @frappe.whitelist() -def make_sales_invoice(source_name, target=None): +def make_sales_invoice(source_name, item_code=None, customer=None): target = frappe.new_doc("Sales Invoice") timesheet = frappe.get_doc('Timesheet', source_name) + hours = flt(timesheet.total_billable_hours) - flt(timesheet.total_billed_hours) + billing_amount = flt(timesheet.total_billable_amount) - flt(timesheet.total_billed_amount) + billing_rate = billing_amount / hours + + if customer: + target.customer = customer + + if item_code: + target.append('items', { + 'item_code': item_code, + 'qty': hours, + 'rate': billing_rate + }) + target.append('timesheets', { 'time_sheet': timesheet.name, - 'billing_hours': flt(timesheet.total_billable_hours) - flt(timesheet.total_billed_hours), - 'billing_amount': flt(timesheet.total_billable_amount) - flt(timesheet.total_billed_amount) + 'billing_hours': hours, + 'billing_amount': billing_amount }) target.run_method("calculate_billing_amount_for_timesheet") + target.run_method("set_missing_values") return target diff --git a/erpnext/public/images/illustrations/shop.jpg b/erpnext/public/images/illustrations/shop.jpg new file mode 100644 index 0000000000..f92f7dbd4e Binary files /dev/null and b/erpnext/public/images/illustrations/shop.jpg differ diff --git a/erpnext/public/images/illustrations/shop2.jpg b/erpnext/public/images/illustrations/shop2.jpg new file mode 100644 index 0000000000..62e464956b Binary files /dev/null and b/erpnext/public/images/illustrations/shop2.jpg differ diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index f2c3d6057c..f5bcf1ce41 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -531,12 +531,23 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ if(this.frm.doc.ignore_pricing_rule) { this.calculate_taxes_and_totals(); } else if (!this.in_apply_price_list){ + this.set_actual_charges_based_on_currency(); this.apply_price_list(); } } }, + set_actual_charges_based_on_currency: function() { + var me = this; + $.each(this.frm.doc.taxes || [], function(i, d) { + if(d.charge_type == "Actual") { + frappe.model.set_value(d.doctype, d.name, "tax_amount", + flt(d.tax_amount) / flt(me.frm.doc.conversion_rate)); + } + }); + }, + get_exchange_rate: function(transaction_date, from_currency, to_currency, callback) { if (!transaction_date || !from_currency || !to_currency) return; return frappe.call({ diff --git a/erpnext/public/js/setup_wizard.js b/erpnext/public/js/setup_wizard.js index d551885700..320d871849 100644 --- a/erpnext/public/js/setup_wizard.js +++ b/erpnext/public/js/setup_wizard.js @@ -7,7 +7,11 @@ frappe.pages['setup-wizard'].on_page_load = function(wrapper) { } }; -var erpnext_slides = [ +frappe.setup.on("before_load", function () { + erpnext.setup.slides_settings.map(frappe.setup.add_slide); +}); + +erpnext.setup.slides_settings = [ { // Domain name: 'domain', @@ -18,14 +22,14 @@ var erpnext_slides = [ fieldname: 'domain', label: __('Domain'), fieldtype: 'Select', options: [ { "label": __("Distribution"), "value": "Distribution" }, - { "label": __("Education"), "value": "Education" }, { "label": __("Manufacturing"), "value": "Manufacturing" }, { "label": __("Retail"), "value": "Retail" }, - { "label": __("Services"), "value": "Services" } + { "label": __("Services"), "value": "Services" }, + { "label": __("Education"), "value": "Education" } ], reqd: 1 }, ], - help: __('Select the nature of your business.'), + // help: __('Select the nature of your business.'), onload: function (slide) { slide.get_input("domain").on("change", function () { frappe.setup.domain = $(this).val(); @@ -40,7 +44,7 @@ var erpnext_slides = [ domains: ["all"], icon: "fa fa-bookmark", title: __("The Brand"), - help: __('Upload your letter head and logo. (you can edit them later).'), + // help: __('Upload your letter head and logo. (you can edit them later).'), fields: [ { fieldtype: "Attach Image", fieldname: "attach_logo", @@ -79,6 +83,12 @@ var erpnext_slides = [ slide.get_field("company_abbr").set_value(""); } }); + }, + validate: function() { + if (!this.values.company_abbr) { + return false; + } + return true; } }, { @@ -87,9 +97,9 @@ var erpnext_slides = [ domains: ["all"], title: __("Your Organization"), icon: "fa fa-building", - help: (frappe.setup.domain === 'Education' ? - __('The name of the institute for which you are setting up this system.') : - __('The name of your company for which you are setting up this system.')), + // help: (frappe.setup.domain === 'Education' ? + // __('The name of the institute for which you are setting up this system.') : + // __('The name of your company for which you are setting up this system.')), fields: [ { fieldname: 'company_tagline', @@ -189,213 +199,6 @@ var erpnext_slides = [ slide.form.fields_dict.fy_end_date.set_value(year_end_date); }); } - }, - - { - // Users - name: 'users', - domains: ["all"], - title: __("Add Users"), - help: __("Add users to your organization, other than yourself"), - add_more: 1, - max_count: 3, - fields: [ - {fieldtype:"Section Break"}, - {fieldtype:"Data", fieldname:"user_fullname", - label:__("Full Name"), static: 1}, - {fieldtype:"Data", fieldname:"user_email", label:__("Email ID"), - placeholder:__("user@example.com"), options: "Email", static: 1}, - {fieldtype:"Column Break"}, - {fieldtype: "Check", fieldname: "user_sales", - label:__("Sales"), "default": 1, static: 1, - hidden: frappe.setup.domain==='Education' ? 1 : 0}, - {fieldtype: "Check", fieldname: "user_purchaser", - label:__("Purchaser"), "default": 1, static: 1, - hidden: frappe.setup.domain==='Education' ? 1 : 0}, - {fieldtype: "Check", fieldname: "user_accountant", - label:__("Accountant"), "default": 1, static: 1, - hidden: frappe.setup.domain==='Education' ? 1 : 0}, - ] - }, - - { - // Sales Target - name: 'Goals', - domains: ['manufacturing', 'services', 'retail', 'distribution'], - title: __("Set your Target"), - help: __("Set a sales target you'd like to achieve."), - fields: [ - {fieldtype:"Currency", fieldname:"sales_target", label:__("Monthly Sales Target")}, - ] - }, - - { - // Taxes - name: 'taxes', - domains: ['manufacturing', 'services', 'retail', 'distribution'], - icon: "fa fa-money", - title: __("Add Taxes"), - help: __("List your tax heads (e.g. VAT, Customs etc; they should have unique names) and their standard rates. This will create a standard template, which you can edit and add more later."), - add_more: 1, - max_count: 3, - mandatory_entry: 0, - fields: [ - {fieldtype:"Section Break"}, - {fieldtype:"Data", fieldname:"tax", label:__("Tax"), - placeholder:__("e.g. VAT")}, - {fieldtype:"Column Break"}, - {fieldtype:"Float", fieldname:"tax_rate", label:__("Rate (%)"), placeholder:__("e.g. 5")} - ] - }, - - { - // Customers - name: 'customers', - domains: ['manufacturing', 'services', 'retail', 'distribution'], - icon: "fa fa-group", - title: __("Add Customers"), - help: __("List a few of your customers. They could be organizations or individuals."), - add_more: 1, - max_count: 5, - mandatory_entry: 1, - fields: [ - {fieldtype:"Section Break"}, - {fieldtype:"Data", fieldname:"customer", label:__("Customer"), - placeholder:__("Customer Name")}, - {fieldtype:"Column Break"}, - {fieldtype:"Data", fieldname:"customer_contact", - label:__("Contact Name"), placeholder:__("Contact Name")} - ], - }, - - { - // Suppliers - name: 'suppliers', - domains: ['manufacturing', 'services', 'retail', 'distribution'], - icon: "fa fa-group", - title: __("Your Suppliers"), - help: __("List a few of your suppliers. They could be organizations or individuals."), - add_more: 1, - max_count: 5, - mandatory_entry: 1, - fields: [ - {fieldtype:"Section Break"}, - {fieldtype:"Data", fieldname:"supplier", label:__("Supplier"), - placeholder:__("Supplier Name")}, - {fieldtype:"Column Break"}, - {fieldtype:"Data", fieldname:"supplier_contact", - label:__("Contact Name"), placeholder:__("Contact Name")}, - ] - }, - - { - // Products - name: 'products', - domains: ['manufacturing', 'services', 'retail', 'distribution'], - icon: "fa fa-barcode", - title: __("Your Products or Services"), - help: __("List your products or services that you buy or sell. Make sure to check the Item Group, Unit of Measure and other properties when you start."), - add_more: 1, - max_count: 5, - mandatory_entry: 1, - fields: [ - {fieldtype:"Section Break", show_section_border: true}, - {fieldtype:"Data", fieldname:"item", label:__("Item"), - placeholder:__("A Product or Service")}, - {fieldtype:"Select", label:__("Group"), fieldname:"item_group", - options:[__("Products"), __("Services"), - __("Raw Material"), __("Consumable"), __("Sub Assemblies")], - "default": __("Products"), static: 1}, - {fieldtype:"Select", fieldname:"item_uom", label:__("UOM"), - options:[__("Unit"), __("Nos"), __("Box"), __("Pair"), __("Kg"), __("Set"), - __("Hour"), __("Minute"), __("Litre"), __("Meter"), __("Gram")], - "default": __("Unit"), static: 1}, - {fieldtype: "Check", fieldname: "is_sales_item", - label:__("We sell this Item"), default: 1, static: 1}, - {fieldtype: "Check", fieldname: "is_purchase_item", - label:__("We buy this Item"), default: 1, static: 1}, - {fieldtype:"Column Break"}, - {fieldtype:"Currency", fieldname:"item_price", label:__("Rate"), static: 1}, - {fieldtype:"Attach Image", fieldname:"item_img", label:__("Attach Image"), is_private: 0, static: 1}, - ], - get_item_count: function() { - return this.item_count; - } - }, - - { - // Program - name: 'program', - domains: ["education"], - title: __("Program"), - help: __("Example: Masters in Computer Science"), - add_more: 1, - max_count: 5, - mandatory_entry: 1, - fields: [ - {fieldtype:"Section Break", show_section_border: true}, - {fieldtype:"Data", fieldname:"program", label:__("Program"), placeholder: __("Program Name")}, - ], - }, - - { - // Course - name: 'course', - domains: ["education"], - title: __("Course"), - help: __("Example: Basic Mathematics"), - add_more: 1, - max_count: 5, - mandatory_entry: 1, - fields: [ - {fieldtype:"Section Break", show_section_border: true}, - {fieldtype:"Data", fieldname:"course", label:__("Course"), placeholder: __("Course Name")}, - ] - }, - - { - // Instructor - name: 'instructor', - domains: ["education"], - title: __("Instructor"), - help: __("People who teach at your organisation"), - add_more: 1, - max_count: 5, - mandatory_entry: 1, - fields: [ - {fieldtype:"Section Break", show_section_border: true}, - {fieldtype:"Data", fieldname:"instructor", label:__("Instructor"), placeholder: __("Instructor Name")}, - ] - }, - - { - // Room - name: 'room', - domains: ["education"], - title: __("Room"), - help: __("Classrooms/ Laboratories etc where lectures can be scheduled."), - add_more: 1, - max_count: 3, - mandatory_entry: 1, - fields: [ - {fieldtype:"Section Break", show_section_border: true}, - {fieldtype:"Data", fieldname:"room", label:__("Room")}, - {fieldtype:"Column Break"}, - {fieldtype:"Int", fieldname:"room_capacity", label:__("Room") + " Capacity", static: 1}, - ] - }, - - { - // last slide: Sample Data - name: 'bootstrap', - domains: ["all"], - title: __("Sample Data"), - fields: [{fieldtype: "Section Break"}, - {fieldtype: "Check", fieldname: "add_sample_data", - label: __("Add a few sample records"), "default": 1}, - {fieldtype: "Check", fieldname: "setup_website", - label: __("Setup a simple website for my organization"), "default": 1} - ] } ]; @@ -422,23 +225,19 @@ erpnext.setup.fiscal_years = { "United Kingdom": ["04-01", "03-31"], }; -frappe.setup.on("before_load", function () { - erpnext_slides.map(frappe.setup.add_slide); -}); - -var test_values_edu = { - "language": "english", - "domain": "Education", - "country": "India", - "timezone": "Asia/Kolkata", - "currency": "INR", - "first_name": "Tester", - "email": "test@example.com", - "password": "test", - "company_name": "Hogwarts", - "company_abbr": "HS", - "company_tagline": "School for magicians", - "bank_account": "Gringotts Wizarding Bank", - "fy_start_date": "2016-04-01", - "fy_end_date": "2017-03-31" -} +// var test_values_edu = { +// "language": "english", +// "domain": "Education", +// "country": "India", +// "timezone": "Asia/Kolkata", +// "currency": "INR", +// "first_name": "Tester", +// "email": "test@example.com", +// "password": "test", +// "company_name": "Hogwarts", +// "company_abbr": "HS", +// "company_tagline": "School for magicians", +// "bank_account": "Gringotts Wizarding Bank", +// "fy_start_date": "2016-04-01", +// "fy_end_date": "2017-03-31" +// } diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index eaf064b26c..a333ca82d6 100644 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -125,7 +125,33 @@ $.extend(erpnext.utils, { } }); } - } + }, + + /** + * Checks if the first row of a given child table is empty + * @param child_table - Child table Doctype + * @return {Boolean} + **/ + first_row_is_empty: function(child_table){ + if($.isArray(child_table) && child_table.length > 0) { + return !child_table[0].item_code; + } + return false; + }, + + /** + * Removes the first row of a child table if it is empty + * @param {_Frm} frm - The current form + * @param {String} child_table_name - The child table field name + * @return {Boolean} + **/ + remove_empty_first_row: function(frm, child_table_name){ + const rows = frm['doc'][child_table_name]; + if (this.first_row_is_empty(rows)){ + frm['doc'][child_table_name] = rows.splice(1); + } + return rows; + }, }); erpnext.utils.map_current_doc = function(opts) { diff --git a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json index 23cf082362..7b3a8d6b72 100644 --- a/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json +++ b/erpnext/regional/doctype/gst_hsn_code/gst_hsn_code.json @@ -84,13 +84,34 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-06-30 20:12:57.903983", - "modified_by": "Administrator", + "modified": "2017-08-31 14:38:52.220743", + "modified_by": "ewdszx@ed.ews", "module": "Regional", "name": "GST HSN Code", "name_case": "", "owner": "Administrator", - "permissions": [], + "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": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], "quick_entry": 1, "read_only": 0, "read_only_onload": 0, diff --git a/erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.js b/erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.js new file mode 100644 index 0000000000..24c5fd355f --- /dev/null +++ b/erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: GST HSN Code", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new GST HSN Code + () => frappe.tests.make('GST HSN Code', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/regional/doctype/gst_settings/gst_settings.json b/erpnext/regional/doctype/gst_settings/gst_settings.json index 61af138e44..04065e29df 100644 --- a/erpnext/regional/doctype/gst_settings/gst_settings.json +++ b/erpnext/regional/doctype/gst_settings/gst_settings.json @@ -83,13 +83,34 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2017-06-28 16:20:21.206397", - "modified_by": "Administrator", + "modified": "2017-08-31 14:39:15.625952", + "modified_by": "ewdszx@ed.ews", "module": "Regional", "name": "GST Settings", "name_case": "", "owner": "Administrator", - "permissions": [], + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 0, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], "quick_entry": 1, "read_only": 0, "read_only_onload": 0, diff --git a/erpnext/regional/doctype/gst_settings/test_gst_settings.js b/erpnext/regional/doctype/gst_settings/test_gst_settings.js new file mode 100644 index 0000000000..00fcca6f32 --- /dev/null +++ b/erpnext/regional/doctype/gst_settings/test_gst_settings.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: GST Settings", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new GST Settings + () => frappe.tests.make('GST Settings', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index 0c59ba003a..46afeece1b 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -39,12 +39,12 @@ def add_hsn_sac_codes(): hsn_codes = json.loads(f.read()) create_hsn_codes(hsn_codes, code_field="hsn_code") - + # SAC Codes with open(os.path.join(os.path.dirname(__file__), 'sac_code_data.json'), 'r') as f: sac_codes = json.loads(f.read()) create_hsn_codes(sac_codes, code_field="sac_code") - + def create_hsn_codes(data, code_field): for d in data: if not frappe.db.exists("GST HSN Code", d[code_field]): @@ -54,8 +54,6 @@ def create_hsn_codes(data, code_field): hsn_code.name = d[code_field] hsn_code.db_insert() - frappe.db.commit() - def add_custom_roles_for_reports(): for report_name in ('GST Sales Register', 'GST Purchase Register', 'GST Itemised Sales Register', 'GST Itemised Purchase Register'): @@ -101,7 +99,7 @@ def make_custom_fields(): dict(fieldname='ecommerce_gstin', label='E-commerce GSTIN', fieldtype='Data', insert_after='export_type', print_hide=1) ] - + purchase_invoice_gst_fields = [ dict(fieldname='supplier_gstin', label='Supplier GSTIN', fieldtype='Data', insert_after='supplier_address', @@ -110,7 +108,7 @@ def make_custom_fields(): fieldtype='Data', insert_after='shipping_address', options='shipping_address.gstin', print_hide=1) ] - + sales_invoice_gst_fields = [ dict(fieldname='customer_gstin', label='Customer GSTIN', fieldtype='Data', insert_after='shipping_address', @@ -122,7 +120,7 @@ def make_custom_fields(): fieldtype='Data', insert_after='company_address', options='company_address.gstin', print_hide=1) ] - + custom_fields = { 'Address': [ dict(fieldname='gstin', label='Party GSTIN', fieldtype='Data', diff --git a/erpnext/regional/print_format/gst_tax_invoice/gst_tax_invoice.json b/erpnext/regional/print_format/gst_tax_invoice/gst_tax_invoice.json index 38508475e1..cb99fd0f38 100644 --- a/erpnext/regional/print_format/gst_tax_invoice/gst_tax_invoice.json +++ b/erpnext/regional/print_format/gst_tax_invoice/gst_tax_invoice.json @@ -7,10 +7,10 @@ "docstatus": 0, "doctype": "Print Format", "font": "Default", - "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"
\\n\\t

\\n\\t\\tTAX INVOICE
\\n\\t\\t{{ doc.name }}\\n\\t

\\n
\\n

\\n\\t{% if doc.invoice_copy -%}\\n\\t\\t{{ doc.invoice_copy }}\\n\\t{% endif -%}\\n

\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"company\", \"label\": \"Company\"}, {\"print_hide\": 0, \"fieldname\": \"company_address_display\", \"label\": \"Company Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"posting_date\", \"label\": \"Date\"}, {\"print_hide\": 0, \"fieldname\": \"due_date\", \"label\": \"Payment Due Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"options\": \"
\", \"fieldname\": \"_custom_html\", \"fieldtype\": \"HTML\", \"label\": \"Custom HTML\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"customer_name\", \"label\": \"Customer Name\"}, {\"print_hide\": 0, \"fieldname\": \"address_display\", \"label\": \"Address\"}, {\"print_hide\": 0, \"fieldname\": \"contact_display\", \"label\": \"Contact\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"shipping_address\", \"label\": \"Shipping Address\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"200px\"}, {\"print_hide\": 0, \"fieldname\": \"gst_hsn_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"items\", \"label\": \"Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"label\": \"Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}], \"print_hide\": 0, \"fieldname\": \"taxes\", \"label\": \"Sales Taxes and Charges\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"grand_total\", \"label\": \"Grand Total\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\", \"label\": \"Rounded Total\"}, {\"print_hide\": 0, \"fieldname\": \"in_words\", \"label\": \"In Words\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"other_charges_calculation\", \"align\": \"left\", \"label\": \"Tax Breakup\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Terms\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"terms\", \"label\": \"Terms and Conditions Details\"}]", + "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"
\\n\\t

\\n\\t\\tTAX INVOICE
\\n\\t\\t{{ doc.name }}\\n\\t

\\n
\\n

\\n\\t{% if doc.invoice_copy -%}\\n\\t\\t{{ doc.invoice_copy }}\\n\\t{% endif -%}\\n

\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"company\", \"label\": \"Company\"}, {\"print_hide\": 0, \"fieldname\": \"company_address_display\", \"label\": \"Company Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"posting_date\", \"label\": \"Date\"}, {\"print_hide\": 0, \"fieldname\": \"due_date\", \"label\": \"Payment Due Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"options\": \"
\", \"fieldname\": \"_custom_html\", \"fieldtype\": \"HTML\", \"label\": \"Custom HTML\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"customer_name\", \"label\": \"Customer Name\"}, {\"print_hide\": 0, \"fieldname\": \"address_display\", \"label\": \"Address\"}, {\"print_hide\": 0, \"fieldname\": \"contact_display\", \"label\": \"Contact\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"shipping_address\", \"label\": \"Shipping Address\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"200px\"}, {\"print_hide\": 0, \"fieldname\": \"gst_hsn_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"serial_no\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"items\", \"label\": \"Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"label\": \"Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}], \"print_hide\": 0, \"fieldname\": \"taxes\", \"label\": \"Sales Taxes and Charges\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"grand_total\", \"label\": \"Grand Total\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\", \"label\": \"Rounded Total\"}, {\"print_hide\": 0, \"fieldname\": \"in_words\", \"label\": \"In Words\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"other_charges_calculation\", \"align\": \"left\", \"label\": \"Tax Breakup\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Terms\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"terms\", \"label\": \"Terms and Conditions Details\"}]", "idx": 0, "line_breaks": 0, - "modified": "2017-07-07 13:06:20.042807", + "modified": "2017-08-29 13:58:58.503343", "modified_by": "Administrator", "module": "Regional", "name": "GST Tax Invoice", diff --git a/erpnext/schools/doctype/assessment_plan/assessment_plan.js b/erpnext/schools/doctype/assessment_plan/assessment_plan.js index be628b83c3..e83c4d3c70 100644 --- a/erpnext/schools/doctype/assessment_plan/assessment_plan.js +++ b/erpnext/schools/doctype/assessment_plan/assessment_plan.js @@ -27,6 +27,14 @@ frappe.ui.form.on("Assessment Plan", { frappe.set_route("Form", "Assessment Result Tool"); }); } + + frm.set_query('grading_scale', function(){ + return { + filters: { + docstatus: 1 + } + } + }); }, course: function(frm) { diff --git a/erpnext/schools/doctype/course/course.js b/erpnext/schools/doctype/course/course.js index c667eca2b7..e31ba72686 100644 --- a/erpnext/schools/doctype/course/course.js +++ b/erpnext/schools/doctype/course/course.js @@ -28,4 +28,12 @@ frappe.ui.form.on("Course", "refresh", function(frm) { frappe.set_route("List", "Assessment Plan"); }); } + + frm.set_query('default_grading_scale', function(){ + return { + filters: { + docstatus: 1 + } + } + }); }); \ No newline at end of file diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index c12cd449b8..52dcb73c03 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -90,6 +90,9 @@ class Customer(TransactionBase): lead = frappe.db.get_value("Lead", self.lead_name, ["lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True) + if not lead.lead_name: + frappe.throw(_("Please mention the Lead Name in Lead {0}").format(self.lead_name)) + lead.lead_name = lead.lead_name.split(" ") lead.first_name = lead.lead_name[0] lead.last_name = " ".join(lead.lead_name[1:]) diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index 3e5e52fe2a..5b137c3bad 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -161,7 +161,7 @@ cur_frm.cscript['Make Sales Order'] = function() { cur_frm.cscript['Declare Order Lost'] = function(){ var dialog = new frappe.ui.Dialog({ - title: "Set as Lost", + title: __('Set as Lost'), fields: [ {"fieldtype": "Text", "label": __("Reason for losing"), "fieldname": "reason", "reqd": 1 }, diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 8c814e3de8..c15d737a31 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -8,6 +8,16 @@ frappe.ui.form.on("Company", { erpnext.company.setup_queries(frm); }, + company_name: function(frm) { + if(frm.doc.__islocal) { + let parts = frm.doc.company_name.split(); + let abbr = $.map(parts, function (p) { + return p? p.substr(0, 1) : null; + }).join(""); + frm.set_value("abbr", abbr); + } + }, + refresh: function(frm) { if(frm.doc.abbr && !frm.doc.__islocal) { frm.set_df_property("abbr", "read_only", 1); diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index c338a81a8e..15e6b4b5b9 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -195,6 +195,157 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "sales_settings", + "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": "Sales", + "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": "sales_monthly_history", + "fieldtype": "Small Text", + "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": "Sales Monthly History", + "length": 0, + "no_copy": 1, + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "monthly_sales_target", + "fieldtype": "Currency", + "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": "Monthly Sales Target", + "length": 0, + "no_copy": 0, + "options": "default_currency", + "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_goals", + "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": "total_monthly_sales", + "fieldtype": "Currency", + "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": "Total Monthly Sales", + "length": 0, + "no_copy": 1, + "options": "default_currency", + "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, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -500,157 +651,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sales_settings", - "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": "Sales", - "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": "sales_monthly_history", - "fieldtype": "Small Text", - "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": "Sales Monthly History", - "length": 0, - "no_copy": 1, - "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, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sales_target", - "fieldtype": "Currency", - "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": "Sales Target", - "length": 0, - "no_copy": 1, - "options": "default_currency", - "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_goals", - "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": "total_monthly_sales", - "fieldtype": "Currency", - "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": "Total Monthly Sales", - "length": 0, - "no_copy": 1, - "options": "default_currency", - "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, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1991,7 +1991,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-08-03 16:17:31.206886", + "modified": "2017-08-31 11:48:56.278568", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index b945ee4104..d3503cc1fa 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -76,7 +76,10 @@ class Company(Document): self.create_default_accounts() self.create_default_warehouses() - self.install_country_fixtures() + if cint(frappe.db.get_single_value('System Settings', 'setup_complete')): + # In the case of setup, fixtures should be installed after setup_success + # This also prevents db commits before setup is successful + install_country_fixtures(self.name) if not frappe.db.get_value("Cost Center", {"is_group": 0, "company": self.name}): self.create_default_cost_center() @@ -95,12 +98,6 @@ class Company(Document): frappe.clear_cache() - def install_country_fixtures(self): - path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(self.country)) - if os.path.exists(path.encode("utf-8")): - frappe.get_attr("erpnext.regional.{0}.setup.setup" - .format(self.country.lower()))(self) - def create_default_warehouses(self): for wh_detail in [ {"warehouse_name": _("All Warehouses"), "is_group": 1}, @@ -311,6 +308,13 @@ def get_name_with_abbr(name, company): return " - ".join(parts) +def install_country_fixtures(company): + company_doc = frappe.get_doc("Company", company) + path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(company_doc.country)) + if os.path.exists(path.encode("utf-8")): + frappe.get_attr("erpnext.regional.{0}.setup.setup" + .format(company_doc.country.lower()))(company_doc) + def update_company_current_month_sales(company): current_month_year = formatdate(today(), "MM-yyyy") diff --git a/erpnext/setup/doctype/company/company_dashboard.py b/erpnext/setup/doctype/company/company_dashboard.py index da7f2b582a..7526dd6c54 100644 --- a/erpnext/setup/doctype/company/company_dashboard.py +++ b/erpnext/setup/doctype/company/company_dashboard.py @@ -8,8 +8,8 @@ def get_data(): 'graph': True, 'graph_method': "frappe.utils.goal.get_monthly_goal_graph_data", 'graph_method_args': { - 'title': 'Sales', - 'goal_value_field': 'sales_target', + 'title': _('Sales'), + 'goal_value_field': 'monthly_sales_target', 'goal_total_field': 'total_monthly_sales', 'goal_history_field': 'sales_monthly_history', 'goal_doctype': 'Sales Invoice', diff --git a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py index d4c9df380f..a477379ded 100644 --- a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py +++ b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py @@ -44,4 +44,5 @@ class TestCurrencyExchange(unittest.TestCase): # Exchange rate as on 15th Dec, 2015, should be fetched from fixer.io exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15") - self.assertFalse(exchange_rate==60) \ No newline at end of file + self.assertFalse(exchange_rate == 60) + self.assertEqual(exchange_rate, 66.894) \ No newline at end of file diff --git a/erpnext/setup/doctype/setup_progress/__init__.py b/erpnext/setup/doctype/setup_progress/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/setup/doctype/setup_progress/setup_progress.js b/erpnext/setup/doctype/setup_progress/setup_progress.js new file mode 100644 index 0000000000..5c78bd5075 --- /dev/null +++ b/erpnext/setup/doctype/setup_progress/setup_progress.js @@ -0,0 +1,8 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Setup Progress', { + refresh: function() { + + } +}); diff --git a/erpnext/setup/doctype/setup_progress/setup_progress.json b/erpnext/setup/doctype/setup_progress/setup_progress.json new file mode 100644 index 0000000000..2f886afe3b --- /dev/null +++ b/erpnext/setup/doctype/setup_progress/setup_progress.json @@ -0,0 +1,123 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2017-08-27 21:01:42.032109", + "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": "actions_sb", + "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": "Actions", + "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": "actions", + "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": "Actions", + "length": 0, + "no_copy": 0, + "options": "Setup Progress Action", + "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 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 1, + "is_submittable": 0, + "issingle": 1, + "istable": 0, + "max_attachments": 0, + "modified": "2017-08-28 17:44:43.100932", + "modified_by": "Administrator", + "module": "Setup", + "name": "Setup Progress", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 0, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "quick_entry": 1, + "read_only": 1, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/setup/doctype/setup_progress/setup_progress.py b/erpnext/setup/doctype/setup_progress/setup_progress.py new file mode 100644 index 0000000000..26eecd9634 --- /dev/null +++ b/erpnext/setup/doctype/setup_progress/setup_progress.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe, json +from frappe.model.document import Document + +class SetupProgress(Document): + pass + +def get_setup_progress(): + if not getattr(frappe.local, "setup_progress", None): + frappe.local.setup_progress = frappe.get_doc("Setup Progress", "Setup Progress") + + return frappe.local.setup_progress + +def get_action_completed_state(action_name): + return [d.is_completed for d in get_setup_progress().actions + if d.action_name == action_name][0] + +def update_action_completed_state(action_name): + action_table_doc = [d for d in get_setup_progress().actions + if d.action_name == action_name][0] + update_action(action_table_doc) + +def update_action(action_table_doc): + if not action_table_doc.is_completed and frappe.db.count(action_table_doc.action_doctype) >= action_table_doc.min_doc_count: + action_table_doc.is_completed = 1 + action_table_doc.save() + +def update_domain_actions(domain): + for d in get_setup_progress().actions: + domains = json.loads(d.domains) + if domains == [] or domain in domains: + update_action(d) + +def get_domain_actions_state(domain): + state = {} + for d in get_setup_progress().actions: + domains = json.loads(d.domains) + if domains == [] or domain in domains: + state[d.action_name] = d.is_completed + return state + +@frappe.whitelist() +def set_action_completed_state(action_name): + action_table_doc = [d for d in get_setup_progress().actions + if d.action_name == action_name][0] + action_table_doc.is_completed = 1 + action_table_doc.save() diff --git a/erpnext/setup/doctype/setup_progress/test_setup_progress.js b/erpnext/setup/doctype/setup_progress/test_setup_progress.js new file mode 100644 index 0000000000..9e84e0cb15 --- /dev/null +++ b/erpnext/setup/doctype/setup_progress/test_setup_progress.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Setup Progress", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Setup Progress + () => frappe.tests.make('Setup Progress', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/setup/doctype/setup_progress_action/__init__.py b/erpnext/setup/doctype/setup_progress_action/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/setup/doctype/setup_progress_action/setup_progress_action.json b/erpnext/setup/doctype/setup_progress_action/setup_progress_action.json new file mode 100644 index 0000000000..030fd99a33 --- /dev/null +++ b/erpnext/setup/doctype/setup_progress_action/setup_progress_action.json @@ -0,0 +1,192 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2017-08-27 21:00:40.715360", + "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": "action_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": "Action 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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "action_doctype", + "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": "Action Doctype", + "length": 0, + "no_copy": 0, + "options": "DocType", + "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": "min_doc_count", + "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": "Min Doc Count", + "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": "domains", + "fieldtype": "Code", + "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": "Domains", + "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": "is_completed", + "fieldtype": "Check", + "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": "Is Completed", + "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 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 1, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2017-08-28 17:44:58.008526", + "modified_by": "Administrator", + "module": "Setup", + "name": "Setup Progress Action", + "name_case": "", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "read_only": 1, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/setup/doctype/setup_progress_action/setup_progress_action.py b/erpnext/setup/doctype/setup_progress_action/setup_progress_action.py new file mode 100644 index 0000000000..24af94347e --- /dev/null +++ b/erpnext/setup/doctype/setup_progress_action/setup_progress_action.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 SetupProgressAction(Document): + pass diff --git a/erpnext/setup/setup_wizard/install_fixtures.py b/erpnext/setup/setup_wizard/install_fixtures.py index ea6da04641..53e58a15af 100644 --- a/erpnext/setup/setup_wizard/install_fixtures.py +++ b/erpnext/setup/setup_wizard/install_fixtures.py @@ -20,6 +20,28 @@ def install(country=None): { 'doctype': 'Domain', 'domain': _('Services')}, { 'doctype': 'Domain', 'domain': _('Education')}, + # Setup Progress + {'doctype': "Setup Progress", "actions": [ + {"action_name": _("Add Company"), "action_doctype": "Company", "min_doc_count": 1, "is_completed": 1, + "domains": '[]' }, + {"action_name": _("Add Customers"), "action_doctype": "Customer", "min_doc_count": 1, "is_completed": 0, + "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, + {"action_name": _("Add Suppliers"), "action_doctype": "Supplier", "min_doc_count": 1, "is_completed": 0, + "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, + {"action_name": _("Add Products"), "action_doctype": "Item", "min_doc_count": 1, "is_completed": 0, + "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' }, + {"action_name": _("Add Programs"), "action_doctype": "Program", "min_doc_count": 1, "is_completed": 0, + "domains": '["Education"]' }, + {"action_name": _("Add Instructors"), "action_doctype": "Instructor", "min_doc_count": 1, "is_completed": 0, + "domains": '["Education"]' }, + {"action_name": _("Add Courses"), "action_doctype": "Course", "min_doc_count": 1, "is_completed": 0, + "domains": '["Education"]' }, + {"action_name": _("Add Rooms"), "action_doctype": "Room", "min_doc_count": 1, "is_completed": 0, + "domains": '["Education"]' }, + {"action_name": _("Add Users"), "action_doctype": "User", "min_doc_count": 4, "is_completed": 0, + "domains": '[]' } + ]}, + # address template {'doctype':"Address Template", "country": country}, diff --git a/erpnext/setup/setup_wizard/sample_data.py b/erpnext/setup/setup_wizard/sample_data.py index cfc6726d1c..bc26e09677 100644 --- a/erpnext/setup/setup_wizard/sample_data.py +++ b/erpnext/setup/setup_wizard/sample_data.py @@ -10,26 +10,27 @@ import random, os, json from frappe import _ from markdown2 import markdown -def make_sample_data(args): +def make_sample_data(domain, make_dependent = False): """Create a few opportunities, quotes, material requests, issues, todos, projects to help the user get started""" - items = frappe.get_all("Item", {'is_sales_item': 1}) - customers = frappe.get_all("Customer") - warehouses = frappe.get_all("Warehouse") + if make_dependent: + items = frappe.get_all("Item", {'is_sales_item': 1}) + customers = frappe.get_all("Customer") + warehouses = frappe.get_all("Warehouse") - if items and customers: - for i in range(3): - customer = random.choice(customers).name - make_opportunity(items, customer) - make_quote(items, customer) + if items and customers: + for i in range(3): + customer = random.choice(customers).name + make_opportunity(items, customer) + make_quote(items, customer) - make_projects(args.get('domain')) + if items and warehouses: + make_material_request(frappe.get_all("Item")) + + make_projects(domain) import_email_alert() - if items and warehouses: - make_material_request(frappe.get_all("Item")) - frappe.db.commit() def make_opportunity(items, customer): diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py index 4dec3d75f7..40d11e5bdc 100644 --- a/erpnext/setup/setup_wizard/setup_wizard.py +++ b/erpnext/setup/setup_wizard/setup_wizard.py @@ -15,6 +15,7 @@ from .sample_data import make_sample_data from erpnext.accounts.doctype.account.account import RootNotEditable from frappe.core.doctype.communication.comment import add_info_comment from erpnext.setup.setup_wizard.domainify import setup_domain +from erpnext.setup.doctype.company.company import install_country_fixtures def setup_complete(args=None): if frappe.db.sql("select name from tabCompany"): @@ -25,24 +26,16 @@ def setup_complete(args=None): create_price_lists(args) create_fiscal_year_and_company(args) create_sales_tax(args) - create_users(args) + create_employee_for_self(args) set_defaults(args) create_territories() create_feed_and_todo() create_email_digest() create_letter_head(args) - create_taxes(args) - create_items(args) - create_customers(args) - create_suppliers(args) if args.get('domain').lower() == 'education': create_academic_year() create_academic_term() - create_program(args) - create_course(args) - create_instructor(args) - create_room(args) if args.get('setup_website'): website_maker(args) @@ -58,16 +51,19 @@ def setup_complete(args=None): frappe.db.commit() frappe.clear_cache() - if args.get("add_sample_data"): - try: - make_sample_data(args) - frappe.clear_cache() - except: - # clear message - if frappe.message_log: - frappe.message_log.pop() + try: + make_sample_data(args.get('domain')) + frappe.clear_cache() + except: + # clear message + if frappe.message_log: + frappe.message_log.pop() - pass + pass + +def setup_success(args=None): + company = frappe.db.sql("select name from tabCompany", as_dict=True)[0]["name"] + install_country_fixtures(company) def create_fiscal_year_and_company(args): if (args.get('fy_start_date')): @@ -91,8 +87,7 @@ def create_fiscal_year_and_company(args): 'country': args.get('country'), 'create_chart_of_accounts_based_on': 'Standard Template', 'chart_of_accounts': args.get('chart_of_accounts'), - 'domain': args.get('domain'), - 'sales_target': args.get('sales_target') + 'domain': args.get('domain') }).insert() #Enable shopping cart @@ -259,22 +254,7 @@ def create_sales_tax(args): tax_data.get('account_name'), tax_data.get('tax_rate'), sales_tax) -def get_country_wise_tax(country): - data = {} - with open (os.path.join(os.path.dirname(__file__), "data", "country_wise_tax.json")) as countrywise_tax: - data = json.load(countrywise_tax).get(country) - - return data - -def create_taxes(args): - for i in xrange(1,6): - if args.get("tax_" + str(i)): - # replace % in case someone also enters the % symbol - tax_rate = cstr(args.get("tax_rate_" + str(i)) or "").replace("%", "") - account_name = args.get("tax_" + str(i)) - - make_tax_account_and_template(args.get("company_name") , account_name, tax_rate) - +# Tax utils start def make_tax_account_and_template(company, account_name, tax_rate, template_name=None): try: if not isinstance(account_name, (list, tuple)): @@ -292,15 +272,6 @@ def make_tax_account_and_template(company, account_name, tax_rate, template_name except RootNotEditable: pass -def get_tax_account_group(company): - tax_group = frappe.db.get_value("Account", - {"account_name": "Duties and Taxes", "is_group": 1, "company": company}) - if not tax_group: - tax_group = frappe.db.get_value("Account", {"is_group": 1, "root_type": "Liability", - "account_type": "Tax", "company": company}) - - return tax_group - def make_tax_account(company, account_name, tax_rate): tax_group = get_tax_account_group(company) if tax_group: @@ -345,115 +316,23 @@ def make_sales_and_purchase_tax_templates(accounts, template_name=None): doc = frappe.get_doc(purchase_tax_template) doc.insert(ignore_permissions=True) -def create_items(args): - for i in xrange(1,6): - item = args.get("item_" + str(i)) - if item: - item_group = _(args.get("item_group_" + str(i))) - is_sales_item = args.get("is_sales_item_" + str(i)) - is_purchase_item = args.get("is_purchase_item_" + str(i)) - is_stock_item = item_group!=_("Services") - default_warehouse = "" - if is_stock_item: - default_warehouse = frappe.db.get_value("Warehouse", filters={ - "warehouse_name": _("Finished Goods") if is_sales_item else _("Stores"), - "company": args.get("company_name") - }) +def get_tax_account_group(company): + tax_group = frappe.db.get_value("Account", + {"account_name": "Duties and Taxes", "is_group": 1, "company": company}) + if not tax_group: + tax_group = frappe.db.get_value("Account", {"is_group": 1, "root_type": "Liability", + "account_type": "Tax", "company": company}) - try: - frappe.get_doc({ - "doctype":"Item", - "item_code": item, - "item_name": item, - "description": item, - "show_in_website": 1, - "is_sales_item": is_sales_item, - "is_purchase_item": is_purchase_item, - "is_stock_item": is_stock_item and 1 or 0, - "item_group": item_group, - "stock_uom": _(args.get("item_uom_" + str(i))), - "default_warehouse": default_warehouse - }).insert() + return tax_group - if args.get("item_img_" + str(i)): - item_image = args.get("item_img_" + str(i)).split(",") - if len(item_image)==3: - filename, filetype, content = item_image - fileurl = save_file(filename, content, "Item", item, decode=True).file_url - frappe.db.set_value("Item", item, "image", fileurl) +# Tax utils end - if args.get("item_price_" + str(i)): - item_price = flt(args.get("item_price_" + str(i))) +def get_country_wise_tax(country): + data = {} + with open (os.path.join(os.path.dirname(__file__), "data", "country_wise_tax.json")) as countrywise_tax: + data = json.load(countrywise_tax).get(country) - if is_sales_item: - price_list_name = frappe.db.get_value("Price List", {"selling": 1}) - make_item_price(item, price_list_name, item_price) - - if is_purchase_item: - price_list_name = frappe.db.get_value("Price List", {"buying": 1}) - make_item_price(item, price_list_name, item_price) - - except frappe.NameError: - pass - -def make_item_price(item, price_list_name, item_price): - frappe.get_doc({ - "doctype": "Item Price", - "price_list": price_list_name, - "item_code": item, - "price_list_rate": item_price - }).insert() - - -def create_customers(args): - for i in xrange(1,6): - customer = args.get("customer_" + str(i)) - if customer: - try: - doc = frappe.get_doc({ - "doctype":"Customer", - "customer_name": customer, - "customer_type": "Company", - "customer_group": _("Commercial"), - "territory": args.get("country"), - "company": args.get("company_name") - }).insert() - - if args.get("customer_contact_" + str(i)): - create_contact(args.get("customer_contact_" + str(i)), - "Customer", doc.name) - except frappe.NameError: - pass - -def create_suppliers(args): - for i in xrange(1,6): - supplier = args.get("supplier_" + str(i)) - if supplier: - try: - doc = frappe.get_doc({ - "doctype":"Supplier", - "supplier_name": supplier, - "supplier_type": _("Local"), - "company": args.get("company_name") - }).insert() - - if args.get("supplier_contact_" + str(i)): - create_contact(args.get("supplier_contact_" + str(i)), - "Supplier", doc.name) - except frappe.NameError: - pass - -def create_contact(contact, party_type, party): - """Create contact based on given contact name""" - contact = contact .split(" ") - - contact = frappe.get_doc({ - "doctype":"Contact", - "first_name":contact[0], - "last_name": len(contact) > 1 and contact[1] or "" - }) - contact.append('links', dict(link_doctype=party_type, link_name=party)) - contact.insert() + return data def create_letter_head(args): if args.get("attach_letterhead"): @@ -497,7 +376,7 @@ def login_as_first_user(args): if args.get("email") and hasattr(frappe.local, "login_manager"): frappe.local.login_manager.login_as(args.get("email")) -def create_users(args): +def create_employee_for_self(args): if frappe.session.user == 'Administrator': return @@ -512,50 +391,7 @@ def create_users(args): emp.flags.ignore_mandatory = True emp.insert(ignore_permissions = True) - for i in xrange(1,5): - email = args.get("user_email_" + str(i)) - fullname = args.get("user_fullname_" + str(i)) - if email: - if not fullname: - fullname = email.split("@")[0] - - parts = fullname.split(" ", 1) - - user = frappe.get_doc({ - "doctype": "User", - "email": email, - "first_name": parts[0], - "last_name": parts[1] if len(parts) > 1 else "", - "enabled": 1, - "user_type": "System User" - }) - - # default roles - user.append_roles("Projects User", "Stock User", "Support Team") - - if args.get("user_sales_" + str(i)): - user.append_roles("Sales User", "Sales Manager", "Accounts User") - if args.get("user_purchaser_" + str(i)): - user.append_roles("Purchase User", "Purchase Manager", "Accounts User") - if args.get("user_accountant_" + str(i)): - user.append_roles("Accounts Manager", "Accounts User") - - user.flags.delay_emails = True - - if not frappe.db.get_value("User", email): - user.insert(ignore_permissions=True) - - # create employee - emp = frappe.get_doc({ - "doctype": "Employee", - "employee_name": fullname, - "user_id": email, - "status": "Active", - "company": args.get("company_name") - }) - emp.flags.ignore_mandatory = True - emp.insert(ignore_permissions = True) - +# Schools def create_academic_term(): at = ["Semester 1", "Semester 2", "Semester 3"] ay = ["2013-14", "2014-15", "2015-16", "2016-17", "2017-18"] @@ -578,46 +414,3 @@ def create_academic_year(): academic_year.save() except frappe.DuplicateEntryError: pass - -def create_program(args): - for i in xrange(1,6): - if args.get("program_" + str(i)): - program = frappe.new_doc("Program") - program.program_code = args.get("program_" + str(i)) - program.program_name = args.get("program_" + str(i)) - try: - program.save() - except frappe.DuplicateEntryError: - pass - -def create_course(args): - for i in xrange(1,6): - if args.get("course_" + str(i)): - course = frappe.new_doc("Course") - course.course_code = args.get("course_" + str(i)) - course.course_name = args.get("course_" + str(i)) - try: - course.save() - except frappe.DuplicateEntryError: - pass - -def create_instructor(args): - for i in xrange(1,6): - if args.get("instructor_" + str(i)): - instructor = frappe.new_doc("Instructor") - instructor.instructor_name = args.get("instructor_" + str(i)) - try: - instructor.save() - except frappe.DuplicateEntryError: - pass - -def create_room(args): - for i in xrange(1,6): - if args.get("room_" + str(i)): - room = frappe.new_doc("Room") - room.room_name = args.get("room_" + str(i)) - room.seating_capacity = args.get("room_capacity_" + str(i)) - try: - room.save() - except frappe.DuplicateEntryError: - pass diff --git a/erpnext/setup/setup_wizard/test_setup_wizard.py b/erpnext/setup/setup_wizard/test_setup_wizard.py new file mode 100644 index 0000000000..aed6698bb4 --- /dev/null +++ b/erpnext/setup/setup_wizard/test_setup_wizard.py @@ -0,0 +1,57 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals + +import frappe, time +from frappe.utils.selenium_testdriver import TestDriver + +def run_setup_wizard_test(): + driver = TestDriver() + frappe.db.set_default('in_selenium', '1') + + driver.login('#page-setup-wizard') + print('Running Setup Wizard Test...') + + # Language slide + driver.set_select("language", "English (United Kingdom)") + driver.wait_for_ajax(True) + driver.wait_till_clickable(".next-btn").click() + + # Region slide + driver.wait_for_ajax(True) + driver.set_select("country", "India") + driver.wait_for_ajax(True) + driver.wait_till_clickable(".next-btn").click() + + # Profile slide + driver.set_field("full_name", "Joe Davis") + driver.set_field("email", "joe@example.com") + driver.set_field("password", "somethingrandom") + driver.wait_till_clickable(".next-btn").click() + + # Brand slide + driver.set_select("domain", "Manufacturing") + driver.wait_till_clickable(".next-btn").click() + + # Org slide + driver.set_field("company_name", "Acme Corp") + driver.wait_till_clickable(".next-btn").click() + driver.set_field("company_tagline", "Build Tools for Builders") + driver.set_field("bank_account", "BNL") + driver.wait_till_clickable(".complete-btn").click() + + # Wait for desk (Lock wait timeout error) + # driver.wait_for('#page-desktop', timeout=200) + + console = driver.get_console() + if frappe.flags.tests_verbose: + for line in console: + print(line) + print('-' * 40) + time.sleep(1) + + frappe.db.set_default('in_selenium', None) + driver.close() + + return True \ No newline at end of file diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py index 888099fc4f..bdbf3f4ec2 100644 --- a/erpnext/setup/utils.py +++ b/erpnext/setup/utils.py @@ -83,7 +83,8 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None): if not value: import requests - response = requests.get("http://api.fixer.io/latest", params={ + api_url = "http://api.fixer.io/{0}".format(transaction_date) + response = requests.get(api_url, params={ "base": from_currency, "symbols": to_currency }) diff --git a/erpnext/startup/notifications.py b/erpnext/startup/notifications.py index 5b0ce391a1..b32f41e0c0 100644 --- a/erpnext/startup/notifications.py +++ b/erpnext/startup/notifications.py @@ -60,8 +60,8 @@ def get_notification_config(): "targets": { "Company": { - "filters" : { "sales_target": ( ">", 0 ) }, - "target_field" : "sales_target", + "filters" : { "monthly_sales_target": ( ">", 0 ) }, + "target_field" : "monthly_sales_target", "value_field" : "total_monthly_sales" } } diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index fc0b9b2106..7043fb7ba8 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -153,9 +153,11 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten if(!r.message) { frappe.throw(__("BOM does not contain any stock item")) } else { + erpnext.utils.remove_empty_first_row(cur_frm, "items"); $.each(r.message, function(i, item) { var d = frappe.model.add_child(cur_frm.doc, "Material Request Item", "items"); d.item_code = item.item_code; + d.item_name = item.item_name; d.description = item.description; d.warehouse = values.warehouse; d.uom = item.stock_uom; diff --git a/erpnext/stock/doctype/material_request/tests/test_material_request_from_bom.js b/erpnext/stock/doctype/material_request/tests/test_material_request_from_bom.js new file mode 100644 index 0000000000..d8b39fe5aa --- /dev/null +++ b/erpnext/stock/doctype/material_request/tests/test_material_request_from_bom.js @@ -0,0 +1,28 @@ +QUnit.module('manufacturing'); + +QUnit.test("test material request get items from BOM", function(assert) { + assert.expect(4); + let done = assert.async(); + frappe.run_serially([ + () => frappe.set_route('Form', 'BOM'), + () => frappe.timeout(3), + () => frappe.click_button('Get Items from BOM'), + () => frappe.timeout(3), + () => { + assert.ok(cur_dialog, 'dialog appeared'); + }, + () => cur_dialog.set_value('bom', 'Laptop'), + () => cur_dialog.set_value('warehouse', 'Laptop Scrap Warehouse'), + () => frappe.click_button('Get Items from BOM'), + () => frappe.timeout(3), + () => { + assert.ok(cur_frm.doc.items[0].item_code, "First row is not empty"); + assert.ok(cur_frm.doc.items[0].item_name, "Item name is not empty"); + assert.equal(cur_frm.doc.items[0].item_name, "Laptop", cur_frm.doc.items[0].item_name); + }, + () => cur_frm.doc.items[0].schedule_date = '2017-12-12', + () => cur_frm.save(), + () => done() + ]); +}); + diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue_with_serialize_item.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue_with_serialize_item.js new file mode 100644 index 0000000000..aac09c30cd --- /dev/null +++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue_with_serialize_item.js @@ -0,0 +1,35 @@ +QUnit.module('Stock'); + +QUnit.test("test material issue", function(assert) { + assert.expect(2); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Stock Entry', [ + {from_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, + {items: [ + [ + {'item_code': 'Test Product 4'}, + {'qty': 1}, + {'batch_no':'TEST-BATCH-001'}, + {'serial_no':'Test-Product-003'}, + {'basic_rate':100}, + ] + ]}, + ]); + }, + () => cur_frm.save(), + () => frappe.click_button('Close'), + () => frappe.click_button('Update Rate and Availability'), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct"); + assert.ok(cur_frm.doc.total_outgoing_value==100, " Outgoing Value correct"); + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_repack.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_repack.js new file mode 100644 index 0000000000..699634df6d --- /dev/null +++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_repack.js @@ -0,0 +1,42 @@ +QUnit.module('Stock'); + +QUnit.test("test repack", function(assert) { + assert.expect(2); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Stock Entry', [ + {purpose:'Repack'}, + {items: [ + [ + {'item_code': 'Test Product 1'}, + {'qty': 1}, + {'s_warehouse':'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, + ], + [ + {'item_code': 'Test Product 2'}, + {'qty': 1}, + {'s_warehouse':'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, + ], + [ + {'item_code': 'Test Product 3'}, + {'qty': 1}, + {'t_warehouse':'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, + ], + ]}, + ]); + }, + () => cur_frm.save(), + () => frappe.click_button('Update Rate and Availability'), + () => { + // get_item_details + assert.ok(cur_frm.doc.total_outgoing_value==250, " Outgoing Value correct"); + assert.ok(cur_frm.doc.total_incoming_value==250, " Incoming Value correct"); + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/templates/emails/training_event.html b/erpnext/templates/emails/training_event.html new file mode 100644 index 0000000000..51c232d8e8 --- /dev/null +++ b/erpnext/templates/emails/training_event.html @@ -0,0 +1,21 @@ +

{{_("Training Event")}}

+

{{ message }}

+ +

{{_("Details")}}

+{{_("Event Name")}}: {{ name }} +
{{_("Event Location")}}: {{ location }} +
{{_("Start Time")}}: {{ start_time }} +
{{_("End Time")}}: {{ end_time }} +
{{_("Attendance")}}: {{ attendance }} + +

{{_("Update Response")}}

+{% if not self_study %} +

{{_("Please update your status for this training event")}}:

+
+
+{% else %} +

{{_("Please confirm once you have completed your training")}}:

+
+{% endif %} +

{{_("Thank you")}},
+{{ user_fullname }}

diff --git a/erpnext/templates/includes/itemised_tax_breakup.html b/erpnext/templates/includes/itemised_tax_breakup.html index 75212d5a1a..2fda0f8aac 100644 --- a/erpnext/templates/includes/itemised_tax_breakup.html +++ b/erpnext/templates/includes/itemised_tax_breakup.html @@ -4,9 +4,9 @@ {% for key in headers %} {% if loop.first %} - {{ key }} + {{ key }} {% else %} - {{ key }} + {{ key }} {% endif %} {% endfor%} @@ -23,7 +23,7 @@ {% if tax_details %} {% if tax_details.tax_rate or not tax_details.tax_amount %} - ({{ tax_details.tax_rate }}) + ({{ tax_details.tax_rate }}%)
{% endif %} {{ frappe.utils.fmt_money(tax_details.tax_amount, None, company_currency) }} diff --git a/erpnext/templates/pages/demo.html b/erpnext/templates/pages/demo.html index f94a7c4591..10743b8231 100644 --- a/erpnext/templates/pages/demo.html +++ b/erpnext/templates/pages/demo.html @@ -60,7 +60,7 @@ $(document).ready(function() { -

Sign up for a Free ERPNext.com account here +

Start a free 30-day trial