Merge branch 'staging'
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 70ae35a..da3786b 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -4,7 +4,7 @@
import frappe
from erpnext.hooks import regional_overrides
-__version__ = '8.10.2'
+__version__ = '8.11.0'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py b/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py
index cb95bd1..9e3388b 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py
@@ -4,7 +4,7 @@
"""
Import chart of accounts from OpenERP sources
"""
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import os, json
import ast
@@ -229,7 +229,7 @@
filename = src["id"][5:] + "_" + chart_id
- print "building " + filename
+ print("building " + filename)
chart = {}
chart["name"] = src["name"]
chart["country_code"] = src["id"][5:]
diff --git a/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.js b/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.js
new file mode 100644
index 0000000..f52f6fb
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.js
@@ -0,0 +1,22 @@
+QUnit.module('Account');
+
+QUnit.test("test Bank Reconciliation", function(assert) {
+ assert.expect(0);
+ let done = assert.async();
+ frappe.run_serially([
+ () => frappe.set_route('Form', 'Bank Reconciliation'),
+ () => cur_frm.set_value('bank_account','Cash - FT'),
+ () => frappe.click_button('Get Payment Entries'),
+ () => {
+ for(var i=0;i<=cur_frm.doc.payment_entries.length-1;i++){
+ cur_frm.doc.payment_entries[i].clearance_date = frappe.datetime.add_days(frappe.datetime.now_date(), 2);
+ }
+ },
+ () => {cur_frm.refresh_fields('payment_entries');},
+ () => frappe.click_button('Update Clearance Date'),
+ () => frappe.timeout(0.5),
+ () => frappe.click_button('Close'),
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.js b/erpnext/accounts/doctype/journal_entry/test_journal_entry.js
new file mode 100644
index 0000000..28ccd95
--- /dev/null
+++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.js
@@ -0,0 +1,39 @@
+QUnit.module('Journal Entry');
+
+QUnit.test("test journal entry", function(assert) {
+ assert.expect(2);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Journal Entry', [
+ {posting_date:frappe.datetime.add_days(frappe.datetime.nowdate(), 0)},
+ {accounts: [
+ [
+ {'account':'Debtors - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
+ {'party_type':'Customer'},
+ {'party':'Test Customer 1'},
+ {'credit_in_account_currency':1000},
+ {'is_advance':'Yes'},
+ ],
+ [
+ {'account':'HDFC - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
+ {'debit_in_account_currency':1000},
+ ]
+ ]},
+ {cheque_no:1234},
+ {cheque_date: frappe.datetime.add_days(frappe.datetime.nowdate(), -1)},
+ {user_remark: 'Test'},
+ ]);
+ },
+ () => cur_frm.save(),
+ () => {
+ // get_item_details
+ assert.ok(cur_frm.doc.total_debit==1000, "total debit correct");
+ assert.ok(cur_frm.doc.total_credit==1000, "total credit correct");
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 7bb9a52..9832c05 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -393,7 +393,7 @@
if self.payment_type=="Receive":
against_account = self.paid_to
else:
- against_account = self.paid_from
+ against_account = self.paid_from
party_gl_dict = self.get_gl_dict({
diff --git a/erpnext/accounts/doctype/payment_entry/tests/test_payment_entry.js b/erpnext/accounts/doctype/payment_entry/tests/test_payment_entry.js
new file mode 100644
index 0000000..a4ef0ca
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_entry/tests/test_payment_entry.js
@@ -0,0 +1,29 @@
+QUnit.module('Accounts');
+
+QUnit.test("test payment entry", function(assert) {
+ assert.expect(1);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Payment Entry', [
+ {payment_type:'Receive'},
+ {mode_of_payment:'Cash'},
+ {party_type:'Customer'},
+ {party:'Test Customer 3'},
+ {paid_amount:675},
+ {reference_no:123},
+ {reference_date: frappe.datetime.add_days(frappe.datetime.nowdate(), 0)},
+ ]);
+ },
+ () => cur_frm.save(),
+ () => {
+ // get_item_details
+ assert.ok(cur_frm.doc.total_allocated_amount==675, "Allocated AmountCorrect");
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 96d617e..780edd8 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -109,7 +109,7 @@
if not self.recurring_id:
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
- self.company, self.base_grand_total, self)
+ self.company, self.base_grand_total, self)
self.check_prev_docstatus()
diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment_request.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment_request.js
new file mode 100644
index 0000000..7abfb41
--- /dev/null
+++ b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment_request.js
@@ -0,0 +1,52 @@
+QUnit.module('Sales Invoice');
+
+QUnit.test("test sales Invoice with payment request", function(assert) {
+ assert.expect(4);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Sales Invoice', [
+ {customer: 'Test Customer 1'},
+ {items: [
+ [
+ {'qty': 5},
+ {'item_code': 'Test Product 1'},
+ ]
+ ]},
+ {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 1', "Item name correct");
+ // get tax details
+ assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
+ // grand_total Calculated
+ assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
+
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(2),
+ () => frappe.tests.click_button('Close'),
+ () => frappe.tests.click_button('Make'),
+ () => frappe.tests.click_link('Payment Request'),
+ () => frappe.timeout(0.2),
+ () => { cur_frm.set_value('print_format','GST Tax Invoice');},
+ () => { cur_frm.set_value('email_to','test@gmail.com');},
+ () => cur_frm.save(),
+ () => {
+ // get payment details
+ assert.ok(cur_frm.doc.grand_total==590, "grand total Correct");
+ },
+ () => done()
+ ]);
+});
+
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 0000000..6005984
--- /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/doctype/shipping_rule/shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
index 7faaf11..a47df2d 100644
--- a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
+++ b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
@@ -54,13 +54,15 @@
d.idx = i + 1
def validate_overlapping_shipping_rule_conditions(self):
- def overlap_exists_between((x1, x2), (y1, y2)):
+ def overlap_exists_between(num_range1, num_range2):
"""
- (x1, x2) and (y1, y2) are two ranges
- if condition x = 100 to 300
- then condition y can only be like 50 to 99 or 301 to 400
+ num_range1 and num_range2 are two ranges
+ ranges are represented as a tuple e.g. range 100 to 300 is represented as (100, 300)
+ if condition num_range1 = 100 to 300
+ then condition num_range2 can only be like 50 to 99 or 301 to 400
hence, non-overlapping condition = (x1 <= x2 < y1 <= y2) or (y1 <= y2 < x1 <= x2)
"""
+ (x1, x2), (y1, y2) = num_range1, num_range2
separate = (x1 <= x2 <= y1 <= y2) or (y1 <= y2 <= x1 <= x2)
return (not separate)
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 0000000..051a123
--- /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": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t<b>{{ _(\"GSTIN\") }}:</b>{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"<br>GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t<br>\n\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t<b>{{ _(\"Customer\") }}:</b><br>\n\t\t{{ doc.customer_name }}<br>\n\t\t{{ customer_address }}\n\t{% endif %}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\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<br>{{ 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<br><b>{{ _(\"HSN/SAC\") }}:</b> {{ 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<br><b>{{ _(\"Serial No\") }}:</b> {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.rate }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"net_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t{%- if not row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n<p><b>Tax Breakup:</b></p>\n<div style=\"font-size: 8px\">\n\t{{ doc.other_charges_calculation }}\n</div>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
+ "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/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
index 853b805..8fafce6 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
@@ -10,15 +10,15 @@
<thead>
<tr>
{% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
- <th style="width: 15%">{%= __("Date") %}</th>
- <th style="width: 15%">{%= __("Ref") %}</th>
- <th style="width: 40%">{%= __("Party") %}</th>
- <th style="width: 15%">{%= __("Invoiced Amount") %}</th>
- <th style="width: 15%">{%= __("Paid Amount") %}</th>
- <th style="width: 15%">{%= report.report_name === "Accounts Receivable" ? __('Credit Note') : __('Debit Note') %}</th>
- <th style="width: 15%">{%= __("Outstanding Amount") %}</th>
+ <th style="width: 14%">{%= __("Date") %}</th>
+ <th style="width: 16%">{%= __("Ref") %}</th>
+ <th style="width: 30%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
+ <th style="width: 10%">{%= __("Invoiced Amount") %}</th>
+ <th style="width: 10%">{%= __("Paid Amount") %}</th>
+ <th style="width: 10%">{%= report.report_name === "Accounts Receivable" ? __('Credit Note') : __('Debit Note') %}</th>
+ <th style="width: 10%">{%= __("Outstanding Amount") %}</th>
{% } else { %}
- <th style="width: 40%">{%= __("Party") %}</th>
+ <th style="width: 40%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
<th style="width: 15%">{%= __("Total Invoiced Amount") %}</th>
<th style="width: 15%">{%= __("Total Paid Amount") %}</th>
<th style="width: 15%">{%= report.report_name === "Accounts Receivable Summary" ? __('Credit Note Amount') : __('Debit Note Amount') %}</th>
@@ -34,8 +34,12 @@
<td>{%= dateutil.str_to_user(data[i][__("Posting Date")]) %}</td>
<td>{%= data[i][__("Voucher Type")] %}
<br>{%= data[i][__("Voucher No")] %}</td>
- <td>{%= data[i][__("Customer Name")] || data[i][__("Customer")] || data[i][__("Supplier Name")] || data[i][__("Supplier")] %}
- <br>{%= __("Remarks") %}: {%= data[i][__("Remarks")] %}</td>
+ <td>
+ {% if(!(filters.customer || filters.supplier)) { %}
+ {%= data[i][__("Customer Name")] || data[i][__("Customer")] || data[i][__("Supplier Name")] || data[i][__("Supplier")] %}<br>{%= __("Remarks") %}:
+ {% } %}
+ {%= data[i][__("Remarks")] %}
+ </td>
<td style="text-align: right">
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">
@@ -59,8 +63,13 @@
{% } else { %}
{% if(data[i][__("Customer")] || data[i][__("Supplier")]|| " ") { %}
{% if((data[i][__("Customer")] || data[i][__("Supplier")]) != __("'Total'")) { %}
- <td>{%= data[i][__("Customer")] || data[i][__("Supplier")] %}
- <br>{%= __("Remarks") %}: {%= data[i][__("Remarks")] %}</td>
+ <td>
+ {% if(!(filters.customer || filters.supplier)) { %}
+ {%= data[i][__("Customer")] || data[i][__("Supplier")] %}
+ <br>{%= __("Remarks") %}:
+ {% } %}
+ {%= data[i][__("Remarks")] %}
+ </td>
{% } else { %}
<td><b>{%= __("Total") %}</b></td>
{% } %}
diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py
index 73badc2..65360ec 100644
--- a/erpnext/controllers/website_list_for_contact.py
+++ b/erpnext/controllers/website_list_for_contact.py
@@ -68,8 +68,8 @@
if txt:
if meta.get_field('items'):
if meta.get_field('items').options:
- child_doctype = meta.get_field('items').options
- for item in frappe.get_all(child_doctype, {"item_name": ['like', "%" + txt + "%"]}):
+ child_doctype = meta.get_field('items').options
+ for item in frappe.get_all(child_doctype, {"item_name": ['like', "%" + txt + "%"]}):
child = frappe.get_doc(child_doctype, item.name)
or_filters.append([doctype, "name", "=", child.parent])
diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json
index e7c2d33..c9d04ac 100644
--- a/erpnext/crm/doctype/lead/lead.json
+++ b/erpnext/crm/doctype/lead/lead.json
@@ -80,36 +80,6 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "salutation",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Salutation",
- "length": 0,
- "no_copy": 0,
- "options": "Salutation",
- "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_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "lead_name",
"fieldtype": "Data",
"hidden": 0,
@@ -141,21 +111,21 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "gender",
- "fieldtype": "Link",
+ "fieldname": "company_name",
+ "fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"in_standard_filter": 0,
- "label": "Gender",
+ "label": "Organization Name",
"length": 0,
"no_copy": 0,
- "options": "Gender",
+ "oldfieldname": "company_name",
+ "oldfieldtype": "Data",
"permlevel": 0,
- "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -266,6 +236,37 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "gender",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Gender",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Gender",
+ "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,
"depends_on": "",
"fieldname": "source",
"fieldtype": "Link",
@@ -299,36 +300,6 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "company_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": "Organization Name",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "company_name",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "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_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "eval:doc.source == 'Existing Customer'",
"fieldname": "customer",
"fieldtype": "Link",
@@ -435,6 +406,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
+ "label": "Follow Up",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -514,11 +486,12 @@
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
- "bold": 0,
+ "bold": 1,
"collapsible": 0,
"columns": 0,
- "fieldname": "contact_by",
- "fieldtype": "Link",
+ "description": "",
+ "fieldname": "contact_date",
+ "fieldtype": "Datetime",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -526,12 +499,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Next Contact By",
+ "label": "Next Contact Date",
"length": 0,
- "no_copy": 0,
- "oldfieldname": "contact_by",
- "oldfieldtype": "Link",
- "options": "User",
+ "no_copy": 1,
+ "oldfieldname": "contact_date",
+ "oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -550,9 +522,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "description": "Add to calendar on this date",
- "fieldname": "contact_date",
- "fieldtype": "Datetime",
+ "fieldname": "contact_by",
+ "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -560,11 +531,12 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Next Contact Date",
+ "label": "Next Contact By",
"length": 0,
- "no_copy": 1,
- "oldfieldname": "contact_date",
- "oldfieldtype": "Date",
+ "no_copy": 0,
+ "oldfieldname": "contact_by",
+ "oldfieldtype": "Link",
+ "options": "User",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -732,6 +704,37 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "salutation",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Salutation",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Salutation",
+ "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": "mobile_no",
"fieldtype": "Data",
"hidden": 0,
@@ -1144,7 +1147,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-06-22 14:29:12.700000",
+ "modified": "2017-08-21 02:28:21.581948",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lead",
diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json
index dc8b3e7..89eb191 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -423,6 +423,164 @@
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
+ "collapsible": 1,
+ "collapsible_depends_on": "contact_by",
+ "columns": 0,
+ "fieldname": "next_contact",
+ "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": "Follow Up",
+ "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,
+ "description": "",
+ "fieldname": "contact_by",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 1,
+ "label": "Next Contact By",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "contact_by",
+ "oldfieldtype": "Link",
+ "options": "User",
+ "permlevel": 0,
+ "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,
+ "width": "75px"
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "description": "",
+ "fieldname": "contact_date",
+ "fieldtype": "Datetime",
+ "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": "Next Contact Date",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "contact_date",
+ "oldfieldtype": "Date",
+ "permlevel": 0,
+ "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_break2",
+ "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,
+ "oldfieldtype": "Column Break",
+ "permlevel": 0,
+ "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,
+ "width": "50%"
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "to_discuss",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "To Discuss",
+ "length": 0,
+ "no_copy": 1,
+ "oldfieldname": "to_discuss",
+ "oldfieldtype": "Small Text",
+ "permlevel": 0,
+ "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,
"depends_on": "with_items",
@@ -435,7 +593,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "",
+ "label": "Items",
"length": 0,
"no_copy": 0,
"oldfieldtype": "Section Break",
@@ -990,164 +1148,6 @@
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "contact_by",
- "columns": 0,
- "fieldname": "next_contact",
- "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": "Next Contact",
- "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,
- "description": "Your sales person who will contact the customer in future",
- "fieldname": "contact_by",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "label": "Next Contact By",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "contact_by",
- "oldfieldtype": "Link",
- "options": "User",
- "permlevel": 0,
- "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,
- "width": "75px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Your sales person will get a reminder on this date to contact the customer",
- "fieldname": "contact_date",
- "fieldtype": "Datetime",
- "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": "Next Contact Date",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "contact_date",
- "oldfieldtype": "Date",
- "permlevel": 0,
- "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_break2",
- "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,
- "oldfieldtype": "Column Break",
- "permlevel": 0,
- "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,
- "width": "50%"
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "to_discuss",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "To Discuss",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "to_discuss",
- "oldfieldtype": "Small Text",
- "permlevel": 0,
- "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": "amended_from",
@@ -1189,7 +1189,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-08-07 21:25:10.836517",
+ "modified": "2017-08-21 02:07:46.486433",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",
diff --git a/erpnext/demo/setup/setup_data.py b/erpnext/demo/setup/setup_data.py
index ae792ac..cec425c 100644
--- a/erpnext/demo/setup/setup_data.py
+++ b/erpnext/demo/setup/setup_data.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import random, json
import frappe, erpnext
@@ -42,7 +42,7 @@
frappe.clear_cache()
def complete_setup(domain='Manufacturing'):
- print "Complete Setup..."
+ print("Complete Setup...")
from frappe.desk.page.setup_wizard.setup_wizard import setup_complete
if not frappe.get_all('Company', limit=1):
diff --git a/erpnext/demo/user/stock.py b/erpnext/demo/user/stock.py
index 1b12db8..43668fe 100644
--- a/erpnext/demo/user/stock.py
+++ b/erpnext/demo/user/stock.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe, random
from frappe.desk import query_report
@@ -36,7 +36,7 @@
try:
pr.submit()
except NegativeStockError:
- print 'Negative stock for {0}'.format(po)
+ print('Negative stock for {0}'.format(po))
pass
frappe.db.commit()
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 6964925..0000000
--- a/erpnext/docs/assets/img/articles/$SGrab_253.png
+++ /dev/null
Binary files 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 7b2ea78..0000000
--- a/erpnext/docs/assets/img/articles/$SGrab_254.png
+++ /dev/null
Binary files 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 1fabda3..0000000
--- a/erpnext/docs/assets/img/articles/$SGrab_256.png
+++ /dev/null
Binary files 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 ebbb007..0000000
--- a/erpnext/docs/assets/img/articles/$SGrab_306.png
+++ /dev/null
Binary files 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 f3d1ee1..0000000
--- a/erpnext/docs/assets/img/articles/$SGrab_307.png
+++ /dev/null
Binary files 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 ae79a3e..0000000
--- a/erpnext/docs/assets/img/articles/$SGrab_431.png
+++ /dev/null
Binary files 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 cc49d85..0000000
--- a/erpnext/docs/assets/img/articles/$SGrab_432.png
+++ /dev/null
Binary files 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 3fb138a..0000000
--- a/erpnext/docs/assets/img/articles/SGrab_282.png
+++ /dev/null
Binary files 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 d726339..0000000
--- a/erpnext/docs/assets/img/articles/SGrab_283.png
+++ /dev/null
Binary files 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 8467e6d..0000000
--- a/erpnext/docs/assets/img/articles/Screen Shot 2015-02-19 at 5.28.57 pm.png
+++ /dev/null
Binary files 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 ac32083..0000000
--- a/erpnext/docs/assets/img/articles/Screen Shot 2015-04-02 at 3.26.51 pm.png
+++ /dev/null
Binary files 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 46c2047..0000000
--- a/erpnext/docs/assets/img/articles/Screen Shot 2015-04-09 at 1.37.38 pm.png
+++ /dev/null
Binary files 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 0000000..b687995
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/capacity-1.png
Binary files 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 0000000..9995b6c
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/capacity-2.png
Binary files 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 0000000..d074eb0
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/capacity-3.png
Binary files 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 0000000..fb19e26
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/child-1.png
Binary files 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 0000000..2141272
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/child-2.png
Binary files 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 0000000..a3667aa
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/child-3.png
Binary files 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 0000000..fab4ba7
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/child-4.gif
Binary files 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 0000000..6990021
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/child-5.png
Binary files 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 0000000..d654986
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/child-6.png
Binary files 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 0000000..33e92c1
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/common-receivable.png
Binary files 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 0000000..e8c5d73
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/email-setup-error.png
Binary files 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 0000000..5857164
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/hr-working-days.png
Binary files 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 0000000..f268fd7
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/purchase-invoice-account-type.png
Binary files 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 0000000..08c4f5a
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/report-permission-1.png
Binary files 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 0000000..5e5ef17
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/report-permission-2.png
Binary files 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 0000000..ef4a4d8
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/role-deskperm.png
Binary files 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 0000000..1ac12ad
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/sections-1.png
Binary files 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 0000000..48edb79
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/sections-2.gif
Binary files 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 0000000..221808e
--- /dev/null
+++ b/erpnext/docs/assets/img/articles/types-in-tax-masters.png
Binary files 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 0000000..1e79664
--- /dev/null
+++ b/erpnext/docs/assets/img/setup/integrations/razorpay-api.gif
Binary files differ
diff --git a/erpnext/docs/assets/old_images/erpnext/__init__.py b/erpnext/docs/assets/old_images/erpnext/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/docs/assets/old_images/erpnext/__init__.py
+++ /dev/null
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 a02f7c6..0000000
--- 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)
-
-<!-- markdown -->
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 0000000..6f92232
--- /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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/common-receivable.png">
+
+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/index.txt b/erpnext/docs/user/manual/en/accounts/articles/index.txt
index 77474bd..8b7768a 100644
--- a/erpnext/docs/user/manual/en/accounts/articles/index.txt
+++ b/erpnext/docs/user/manual/en/accounts/articles/index.txt
@@ -6,10 +6,11 @@
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
\ 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 0000000..e7a0772
--- /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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/purchase-invoice-account-type.png">
+
+**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 0000000..d8618be
--- /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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/types-in-tax-masters.png">
+
+**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 0000000..bc31cf2
--- /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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/child-1.png">
+
+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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/child-2.png">
+
+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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/child-3.png">
+
+**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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/child-4.gif">
+
+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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/child-5.png">
+
+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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/child-6.png">
\ 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 f8a81a4..1740ef0 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,5 @@
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
\ 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 3fbdc5b..3019af5 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 0000000..289a24a
--- /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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/hr-working-days.png">
+
+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/manufacturing/articles/capacity-planning.md b/erpnext/docs/user/manual/en/manufacturing/articles/capacity-planning.md
new file mode 100644
index 0000000..4dd10b3
--- /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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/capacity-1.png">
+
+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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/capacity-2.png">
+
+**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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/capacity-3.png">
+
+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 bb78d39..d0e429e 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 dad849e..2943ea6 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 @@
-<h1>Project Costing</h1>
+# 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 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)
+<img alt="Activity Cost" class="screenshot" src="/docs/assets/img/articles/Screen Shot 2015-06-11 at 4.57.01 pm.png">
#### 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)
+<img alt="Time Log" class="screenshot" src="/docs/assets/img/articles/Screen Shot 2015-06-11 at 4.59.49 pm.png">
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)
+<img alt="[Time Log Costing" class="screenshot" src="/docs/assets/img/articles/Screen Shot 2015-06-11 at 5.00.06 pm.png">
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 @@
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)
+<img alt="Costing in Task" class="screenshot" src="/docs/assets/img/articles/Screen Shot 2015-06-11 at 5.02.54 pm.png">
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)
+<img alt="Costing in Project" class="screenshot" src="/docs/assets/img/articles/Screen Shot 2015-06-11 at 5.02.29 pm.png">
<!-- markdown -->
\ 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 0000000..a11aa21
--- /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.
+
+<img alt="Role Desk Permission" class="screenshot" src="/docs/assets/img/articles/role-deskperm.png">
\ 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 acf1531..d175d92 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,7 @@
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
\ 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 9971610..e4362fb 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 @@
<img alt="New Company" class="screenshot" src="/docs/assets/img/articles/new-company-3.png">
-
<!-- markdown -->
\ 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 0000000..9694da1
--- /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.
+
+<img alt="Email Setup Error" class="screenshot" src="/docs/assets/img/articles/email-setup-error.png">
+
+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 0000000..93542e6
--- /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?
+
+<img alt="Email Setup Error" class="screenshot" src="/docs/assets/img/articles/sections-1.png">
+
+**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"
+
+<img alt="Email Setup Error" class="screenshot" src="/docs/assets/img/articles/sections-2.gif">
\ 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 0000000..c345d0a
--- /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.
+
+<img alt="Report Permission Error" class="screenshot" src="/docs/assets/img/articles/report-permission-1.png">
+
+**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.
+
+ <img alt="Permission Manager" class="screenshot" src="/docs/assets/img/articles/report-permission-2.png">
+
+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/integrations/razorpay-integration.md b/erpnext/docs/user/manual/en/setting-up/integrations/razorpay-integration.md
index 01f2975..d41283c 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`
-To enable Razorpay payment service, you need to configure parameters like API Key, API Secret
+<img class="screenshot" alt="Razorpay Settings" src="/docs/assets/img/setup/integrations/razorpay-api.gif">
+
+#### Setup RazorPay
+
+To enable RazorPay payment service, you need to configure parameters like API Key, API Secret
+
<img class="screenshot" alt="Razorpay Settings" src="/docs/assets/img/setup/integrations/razorpay_settings.png">
-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.
<img class="screenshot" alt="Razorpay COA" src="/docs/assets/img/setup/integrations/razorpay_coa.png">
-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.
<img class="screenshot" alt="Payment Gateway Account" src="/docs/assets/img/setup/integrations/payment_gateway_account_razorpay.png">
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/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 0000000..3a87e02
--- /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 74243df..2477fca 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 @@
user-permissions
role-permisison-for-page-and-report
sharing
+admin-user
\ No newline at end of file
diff --git a/erpnext/hr/doctype/appraisal/test_appraisal.js b/erpnext/hr/doctype/appraisal/test_appraisal.js
new file mode 100644
index 0000000..91da7d3
--- /dev/null
+++ b/erpnext/hr/doctype/appraisal/test_appraisal.js
@@ -0,0 +1,58 @@
+QUnit.module('hr');
+
+QUnit.test("Test: Expense Claim [HR]", function (assert) {
+ assert.expect(3);
+ let done = assert.async();
+ let employee_name;
+
+ frappe.run_serially([
+ // Creating Appraisal
+ () => frappe.set_route('List','Appraisal','List'),
+ () => frappe.timeout(0.3),
+ () => frappe.click_button('Make a new Appraisal'),
+ () => {
+ cur_frm.set_value('kra_template','Test Appraisal 1'),
+ cur_frm.set_value('start_date','2017-08-21'),
+ cur_frm.set_value('end_date','2017-09-21');
+ },
+ () => frappe.timeout(1),
+ () => frappe.model.set_value('Appraisal Goal','New Appraisal Goal 1','score',4),
+ () => frappe.model.set_value('Appraisal Goal','New Appraisal Goal 1','score_earned',2),
+ () => frappe.model.set_value('Appraisal Goal','New Appraisal Goal 2','score',4),
+ () => frappe.model.set_value('Appraisal Goal','New Appraisal Goal 2','score_earned',2),
+ () => frappe.timeout(1),
+ () => frappe.db.get_value('Employee', {'employee_name': 'Test Employee 1'}, 'name'),
+ (r) => {
+ employee_name = r.message.name;
+ },
+
+ () => frappe.timeout(1),
+ () => cur_frm.set_value('employee',employee_name),
+ () => cur_frm.set_value('employee_name','Test Employee 1'),
+ () => cur_frm.set_value('company','Test Company'),
+ () => frappe.click_button('Calculate Total Score'),
+ () => frappe.timeout(1),
+ () => cur_frm.save(),
+ () => frappe.timeout(1),
+ () => cur_frm.save(),
+
+ // Submitting the Appraisal
+ () => frappe.click_button('Submit'),
+ () => frappe.click_button('Yes'),
+ () => frappe.timeout(3),
+
+ // Checking if the appraisal is correctly set for the employee
+ () => {
+ assert.equal('Submitted',cur_frm.get_field('status').value,
+ 'Appraisal is submitted');
+
+ assert.equal('Test Employee 1',cur_frm.get_field('employee_name').value,
+ 'Appraisal is created for correct employee');
+
+ assert.equal(4,cur_frm.get_field('total_score').value,
+ 'Total score is correctly calculated');
+ },
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/hr/doctype/appraisal_template/test_appraisal_template.js b/erpnext/hr/doctype/appraisal_template/test_appraisal_template.js
new file mode 100644
index 0000000..4e245c7
--- /dev/null
+++ b/erpnext/hr/doctype/appraisal_template/test_appraisal_template.js
@@ -0,0 +1,30 @@
+QUnit.module('hr');
+QUnit.test("Test: Appraisal Template [HR]", function (assert) {
+ assert.expect(1);
+ let done = assert.async();
+ frappe.run_serially([
+ // Job Opening creation
+ () => {
+ frappe.tests.make('Appraisal Template', [
+ { kra_title: 'Test Appraisal 1'},
+ { description: 'This is just a test'},
+ { goals: [
+ [
+ { kra: 'Design'},
+ { per_weightage: 50}
+ ],
+ [
+ { kra: 'Code creation'},
+ { per_weightage: 50}
+ ]
+ ]},
+ ]);
+ },
+ () => frappe.timeout(5),
+ () => {
+ assert.equal('Test Appraisal 1',cur_frm.doc.kra_title, 'Appraisal name correctly set');
+ },
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/hr/doctype/employee_loan/test_employee_loan.js b/erpnext/hr/doctype/employee_loan/test_employee_loan.js
new file mode 100644
index 0000000..9039339
--- /dev/null
+++ b/erpnext/hr/doctype/employee_loan/test_employee_loan.js
@@ -0,0 +1,79 @@
+
+QUnit.test("Test Loan [HR]", function(assert) {
+ assert.expect(8);
+ let done = assert.async();
+ let employee_name;
+
+ // To create a loan and check principal,interest and balance amount
+ let loan_creation = (ename,lname) => {
+ return frappe.run_serially([
+ () => frappe.db.get_value('Employee', {'employee_name': ename}, 'name'),
+ (r) => {
+ employee_name = r.message.name;
+ },
+ () => frappe.db.get_value('Employee Loan Application', {'loan_type': lname}, 'name'),
+ (r) => {
+ // Creating loan for an employee
+ return frappe.tests.make('Employee Loan', [
+ { company: 'Test Company'},
+ { posting_date: '2017-08-26'},
+ { employee: employee_name},
+ { employee_loan_application: r.message.name},
+ { disbursement_date: '2018-08-26'},
+ { mode_of_payment: 'Cash'},
+ { employee_loan_account: 'Temporary Opening - TC'},
+ { interest_income_account: 'Service - TC'}
+ ]);
+ },
+ () => frappe.timeout(3),
+ () => frappe.click_button('Submit'),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Yes'),
+ () => frappe.timeout(3),
+
+ // Checking if all the amounts are correctly calculated
+ () => {
+ assert.ok(cur_frm.get_field('employee_name').value=='Test Employee 1'&&
+ (cur_frm.get_field('status').value=='Sanctioned'),
+ 'Loan Sanctioned for correct employee');
+
+ assert.equal(7270,
+ cur_frm.get_doc('repayment_schedule').repayment_schedule[0].principal_amount,
+ 'Principal amount for first instalment is correctly calculated');
+
+ assert.equal(2333,
+ cur_frm.get_doc('repayment_schedule').repayment_schedule[0].interest_amount,
+ 'Interest amount for first instalment is correctly calculated');
+
+ assert.equal(192730,
+ cur_frm.get_doc('repayment_schedule').repayment_schedule[0].balance_loan_amount,
+ 'Balance amount after first instalment is correctly calculated');
+
+ assert.equal(9479,
+ cur_frm.get_doc('repayment_schedule').repayment_schedule[23].principal_amount,
+ 'Principal amount for last instalment is correctly calculated');
+
+ assert.equal(111,
+ cur_frm.get_doc('repayment_schedule').repayment_schedule[23].interest_amount,
+ 'Interest amount for last instalment is correctly calculated');
+
+ assert.equal(0,
+ cur_frm.get_doc('repayment_schedule').repayment_schedule[23].balance_loan_amount,
+ 'Balance amount after last instalment is correctly calculated');
+
+ },
+ () => frappe.set_route('List','Employee Loan','List'),
+ () => frappe.timeout(2),
+
+ // Checking the submission of Loan
+ () => {
+ assert.ok(cur_list.data[0].docstatus==1,'Loan sanctioned and submitted successfully');
+ },
+ ]);
+ };
+ frappe.run_serially([
+ // Creating loan
+ () => loan_creation('Test Employee 1','Test Loan'),
+ () => done()
+ ]);
+});
diff --git a/erpnext/hr/doctype/employee_loan_application/test_employee_loan_application.js b/erpnext/hr/doctype/employee_loan_application/test_employee_loan_application.js
new file mode 100644
index 0000000..72ad915
--- /dev/null
+++ b/erpnext/hr/doctype/employee_loan_application/test_employee_loan_application.js
@@ -0,0 +1,68 @@
+QUnit.module('hr');
+
+QUnit.test("Test: Employee Loan Application [HR]", function (assert) {
+ assert.expect(8);
+ let done = assert.async();
+ let employee_name;
+
+ frappe.run_serially([
+ // Creation of Loan Application
+ () => frappe.db.get_value('Employee', {'employee_name': 'Test Employee 1'}, 'name'),
+ (r) => {
+ employee_name = r.message.name;
+ },
+ () => {
+ frappe.tests.make('Employee Loan Application', [
+ { company: 'Test Company'},
+ { employee: employee_name},
+ { employee_name: 'Test Employee 1'},
+ { status: 'Approved'},
+ { loan_type: 'Test Loan '},
+ { loan_amount: 200000},
+ { description: 'This is just a test'},
+ { repayment_method: 'Repay Over Number of Periods'},
+ { repayment_periods: 24},
+ { rate_of_interest: 14}
+ ]);
+ },
+ () => frappe.timeout(6),
+ () => frappe.click_button('Submit'),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Yes'),
+ () => frappe.timeout(2),
+ () => {
+ // To check if all the amounts are correctly calculated
+
+ assert.ok(cur_frm.get_field('employee_name').value == 'Test Employee 1',
+ 'Application created successfully');
+
+ assert.ok(cur_frm.get_field('status').value=='Approved',
+ 'Status of application is correctly set');
+
+ assert.ok(cur_frm.get_field('loan_type').value=='Test Loan',
+ 'Application is created for correct Loan Type');
+
+ assert.ok(cur_frm.get_field('status').value=='Approved',
+ 'Status of application is correctly set');
+
+ assert.ok(cur_frm.get_field('repayment_amount').value==9603,
+ 'Repayment amount is correctly calculated');
+
+ assert.ok(cur_frm.get_field('total_payable_interest').value==30459,
+ 'Interest amount is correctly calculated');
+
+ assert.ok(cur_frm.get_field('total_payable_amount').value==230459,
+ 'Total payable amount is correctly calculated');
+ },
+
+ () => frappe.set_route('List','Employee Loan Application','List'),
+ () => frappe.timeout(2),
+
+ // Checking the submission of Loan Application
+ () => {
+ assert.ok(cur_list.data[0].docstatus==1,'Loan Application submitted successfully');
+ },
+ () => frappe.timeout(1),
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.js b/erpnext/hr/doctype/expense_claim/test_expense_claim.js
new file mode 100644
index 0000000..c7c764c
--- /dev/null
+++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.js
@@ -0,0 +1,59 @@
+QUnit.module('hr');
+
+QUnit.test("Test: Expense Claim [HR]", function (assert) {
+ assert.expect(3);
+ let done = assert.async();
+ let employee_name;
+ let d;
+ frappe.run_serially([
+ // Creating Expense Claim
+ () => frappe.set_route('List','Expense Claim','List'),
+ () => frappe.timeout(0.3),
+ () => frappe.click_button('Make a new Expense Claim'),
+ () => {
+ cur_frm.set_value('exp_approver','Administrator'),
+ cur_frm.set_value('is_paid',1),
+ cur_frm.set_value('expenses',[]),
+ d = frappe.model.add_child(cur_frm.doc,'Expense Claim Detail','expenses'),
+ d.expense_date = '2017-08-01',
+ d.expense_type = 'Test Expense Type 1',
+ d.description = 'This is just to test Expense Claim',
+ d.claim_amount = 2000,
+ d.sanctioned_amount=2000,
+ refresh_field('expenses');
+ },
+ () => frappe.timeout(2),
+ () => frappe.db.get_value('Employee', {'employee_name': 'Test Employee 1'}, 'name'),
+ (r) => {
+ employee_name = r.message.name;
+ },
+ () => frappe.timeout(1),
+ () => cur_frm.set_value('employee',employee_name),
+ () => cur_frm.set_value('employee_name','Test Employee 1'),
+ () => cur_frm.set_value('company','Test Company'),
+ () => cur_frm.set_value('payable_account','Creditors - TC'),
+ () => cur_frm.set_value('cost_center','Main - TC'),
+ () => cur_frm.set_value('mode_of_payment','Cash'),
+ () => cur_frm.save(),
+ () => frappe.timeout(1),
+ () => cur_frm.set_value('approval_status','Approved'),
+ () => frappe.timeout(1),
+ () => cur_frm.save(),
+ // Submitting the Expense Claim
+ () => frappe.click_button('Submit'),
+ () => frappe.click_button('Yes'),
+ () => frappe.timeout(3),
+
+ // Checking if the amount is correctly reimbursed for the employee
+ () => {
+ assert.equal(employee_name,cur_frm.get_field('employee').value,
+ 'Expense Claim is created for correct employee');
+ assert.equal(1,cur_frm.get_field('is_paid').value,
+ 'Expense is paid as required');
+ assert.equal(2000,cur_frm.get_field('total_amount_reimbursed').value,
+ 'Amount is reimbursed correctly');
+ },
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.js b/erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.js
new file mode 100644
index 0000000..595454f
--- /dev/null
+++ b/erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.js
@@ -0,0 +1,30 @@
+QUnit.module('hr');
+
+QUnit.test("Test: Expense Claim Type [HR]", function (assert) {
+ assert.expect(1);
+ let done = assert.async();
+ frappe.run_serially([
+ // Creating a Expense Claim Type
+ () => {
+ frappe.tests.make('Expense Claim Type', [
+ { expense_type: 'Test Expense Type 1'},
+ { description:'This is just a test'},
+ { accounts: [
+ [
+ { company: 'Test Company'},
+ { default_account: 'Round Off - TC'}
+ ]
+ ]},
+ ]);
+ },
+ () => frappe.timeout(5),
+
+ // Checking if the created type is present in the list
+ () => {
+ assert.equal('Test Expense Type 1', cur_frm.doc.expense_type,
+ 'Expense Claim Type created successfully');
+ },
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.js b/erpnext/hr/doctype/leave_application/test_leave_application.js
index 51e8ed6..6028405 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.js
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.js
@@ -1,7 +1,7 @@
QUnit.module('hr');
QUnit.test("Test: Leave application [HR]", function (assert) {
- assert.expect(5);
+ assert.expect(4);
let done = assert.async();
let today_date = frappe.datetime.nowdate();
let leave_date = frappe.datetime.add_days(today_date, 1); // leave for tomorrow
@@ -22,8 +22,6 @@
},
() => frappe.timeout(1),
// check calculated total leave days
- () => assert.equal("0.5", cur_frm.doc.total_leave_days,
- "leave application for half day"),
() => assert.ok(!cur_frm.doc.docstatus,
"leave application not submitted with status as open"),
() => cur_frm.set_value("status", "Approved"), // approve the application [as administrator]
diff --git a/erpnext/hr/doctype/leave_block_list/test_leave_block_list.py b/erpnext/hr/doctype/leave_block_list/test_leave_block_list.py
index 42b26e3..210b8b7 100644
--- a/erpnext/hr/doctype/leave_block_list/test_leave_block_list.py
+++ b/erpnext/hr/doctype/leave_block_list/test_leave_block_list.py
@@ -10,7 +10,7 @@
class TestLeaveBlockList(unittest.TestCase):
def tearDown(self):
- frappe.set_user("Administrator")
+ frappe.set_user("Administrator")
def test_get_applicable_block_dates(self):
frappe.set_user("test@example.com")
diff --git a/erpnext/hr/doctype/loan_type/test_loan_type.js b/erpnext/hr/doctype/loan_type/test_loan_type.js
new file mode 100644
index 0000000..8b5032b
--- /dev/null
+++ b/erpnext/hr/doctype/loan_type/test_loan_type.js
@@ -0,0 +1,31 @@
+QUnit.module('hr');
+
+QUnit.test("Test: Loan Type [HR]", function (assert) {
+ assert.expect(3);
+ let done = assert.async();
+
+ frappe.run_serially([
+ // Loan Type creation
+ () => {
+ frappe.tests.make('Loan Type', [
+ { loan_name: 'Test Loan'},
+ { maximum_loan_amount: 400000},
+ { rate_of_interest: 14},
+ { description:
+ 'This is just a test.'}
+ ]);
+ },
+ () => frappe.timeout(3),
+ () => frappe.set_route('List','Loan Type','List'),
+ () => frappe.timeout(2),
+
+ // Checking if the fields are correctly set
+ () => {
+ assert.ok(cur_list.data.length==1, 'Loan Type created successfully');
+ assert.ok(cur_list.data[0].name=='Test Loan', 'Loan title Correctly set');
+ assert.ok(cur_list.data[0].disabled==0, 'Loan enabled');
+ },
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/hr/doctype/process_payroll/process_payroll.py b/erpnext/hr/doctype/process_payroll/process_payroll.py
index 7575ee4..55c0cce 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 @@
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 1f9ba26..cac43c4 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 @@
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/test_training_event.js
new file mode 100644
index 0000000..a359af3
--- /dev/null
+++ b/erpnext/hr/doctype/training_event/test_training_event.js
@@ -0,0 +1,55 @@
+QUnit.module('hr');
+
+QUnit.test("Test: Training Event [HR]", function (assert) {
+ assert.expect(4);
+ let done = assert.async();
+ let employee_name;
+
+ frappe.run_serially([
+ // Creation of Training Event
+ () => frappe.db.get_value('Employee', {'employee_name': 'Test Employee 1'}, 'name'),
+ (r) => {
+ employee_name = r.message.name;
+ },
+ () => {
+ frappe.tests.make('Training Event', [
+ { event_name: 'Test Training Event 1'},
+ { location: 'Mumbai'},
+ { start_time: '2017-09-01 11:00:0'},
+ { end_time: '2017-09-01 17:00:0'},
+ { introduction: 'This is just a test'},
+ { employees: [
+ [
+ {employee: employee_name},
+ {employee_name: 'Test Employee 1'}
+ ]
+ ]},
+ ]);
+ },
+ () => frappe.timeout(7),
+ () => frappe.click_button('Submit'),
+ () => frappe.timeout(1),
+ () => frappe.click_button('Yes'),
+ () => frappe.timeout(8),
+ () => {
+ // To check if the fields are correctly set
+ assert.ok(cur_frm.get_field('event_name').value == 'Test Training Event 1',
+ 'Event created successfully');
+
+ assert.ok(cur_frm.get_field('event_status').value=='Scheduled',
+ 'Status of event is correctly set');
+
+ assert.ok(cur_frm.doc.employees[0].employee_name=='Test Employee 1',
+ 'Attendee Employee is correctly set');
+ },
+
+ () => frappe.set_route('List','Training Event','List'),
+ () => frappe.timeout(2),
+ // Checking the submission of Training Event
+ () => {
+ assert.ok(cur_list.data[0].docstatus==1,'Training Event Submitted successfully');
+ },
+ () => frappe.timeout(2),
+ () => done()
+ ]);
+});
\ No newline at end of file
diff --git a/erpnext/hr/doctype/training_feedback/test_training_feedback.js b/erpnext/hr/doctype/training_feedback/test_training_feedback.js
new file mode 100644
index 0000000..9daa51f
--- /dev/null
+++ b/erpnext/hr/doctype/training_feedback/test_training_feedback.js
@@ -0,0 +1,52 @@
+QUnit.module('hr');
+
+QUnit.test("Test: Training Feedback [HR]", function (assert) {
+ assert.expect(3);
+ let done = assert.async();
+ let employee_name;
+
+ frappe.run_serially([
+ // Creating Training Feedback
+ () => frappe.set_route('List','Training Feedback','List'),
+ () => frappe.timeout(0.3),
+ () => frappe.click_button('Make a new Training Feedback'),
+ () => frappe.timeout(1),
+ () => frappe.db.get_value('Employee', {'employee_name': 'Test Employee 1'}, 'name'),
+ (r) => {
+ employee_name = r.message.name;
+ },
+ () => cur_frm.set_value('employee',employee_name),
+ () => cur_frm.set_value('employee_name','Test Employee 1'),
+ () => cur_frm.set_value('training_event','Test Training Event 1'),
+ () => cur_frm.set_value('event_name','Test Training Event 1'),
+ () => cur_frm.set_value('feedback','Great Experience. This is just a test.'),
+ () => frappe.timeout(1),
+ () => cur_frm.save(),
+ () => frappe.timeout(1),
+ () => cur_frm.save(),
+
+ // Submitting the feedback
+ () => frappe.click_button('Submit'),
+ () => frappe.click_button('Yes'),
+ () => frappe.timeout(3),
+
+ // Checking if the feedback is given by correct employee
+ () => {
+ assert.equal('Test Employee 1',cur_frm.get_field('employee_name').value,
+ 'Feedback is given by correct employee');
+
+ assert.equal('Test Training Event 1',cur_frm.get_field('training_event').value,
+ 'Feedback is given for correct event');
+ },
+
+ () => frappe.set_route('List','Training Feedback','List'),
+ () => frappe.timeout(2),
+
+ // Checking the submission of Training Result
+ () => {
+ assert.ok(cur_list.data[0].docstatus==1,'Training Feedback Submitted successfully');
+ },
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/hr/doctype/training_result_employee/test_training_result.js b/erpnext/hr/doctype/training_result_employee/test_training_result.js
new file mode 100644
index 0000000..2ebf896
--- /dev/null
+++ b/erpnext/hr/doctype/training_result_employee/test_training_result.js
@@ -0,0 +1,53 @@
+QUnit.module('hr');
+
+QUnit.test("Test: Training Result [HR]", function (assert) {
+ assert.expect(5);
+ let done = assert.async();
+ frappe.run_serially([
+ // Creating Training Result
+ () => frappe.set_route('List','Training Result','List'),
+ () => frappe.timeout(0.3),
+ () => frappe.click_button('Make a new Training Result'),
+ () => {
+ cur_frm.set_value('training_event','Test Training Event 1');
+ },
+ () => frappe.timeout(1),
+ () => frappe.model.set_value('Training Result Employee','New Training Result Employee 1','hours',4),
+ () => frappe.model.set_value('Training Result Employee','New Training Result Employee 1','grade','A'),
+ () => frappe.model.set_value('Training Result Employee','New Training Result Employee 1','comments','Nice Seminar'),
+ () => frappe.timeout(1),
+ () => cur_frm.save(),
+ () => frappe.timeout(1),
+ () => cur_frm.save(),
+
+ // Submitting the Training Result
+ () => frappe.click_button('Submit'),
+ () => frappe.click_button('Yes'),
+ () => frappe.timeout(4),
+
+ // Checking if the fields are correctly set
+ () => {
+ assert.equal('Test Training Event 1',cur_frm.get_field('training_event').value,
+ 'Training Result is created');
+
+ assert.equal('Test Employee 1',cur_frm.doc.employees[0].employee_name,
+ 'Training Result is created for correct employee');
+
+ assert.equal(4,cur_frm.doc.employees[0].hours,
+ 'Hours field is correctly calculated');
+
+ assert.equal('A',cur_frm.doc.employees[0].grade,
+ 'Grade field is correctly set');
+ },
+
+ () => frappe.set_route('List','Training Result','List'),
+ () => frappe.timeout(2),
+
+ // Checking the submission of Training Result
+ () => {
+ assert.ok(cur_list.data[0].docstatus==1,'Training Result Submitted successfully');
+ },
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 71ff43f..e48a002 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -259,15 +259,15 @@
def update_stock_qty(self):
- for m in self.get('items'):
+ for m in self.get('items'):
if not m.conversion_factor:
m.conversion_factor = flt(get_conversion_factor(m.item_code, m.uom)['conversion_factor'])
- if m.uom and m.qty:
- m.stock_qty = flt(m.conversion_factor)*flt(m.qty)
- if not m.uom and m.stock_uom:
- m.uom = m.stock_uom
- m.qty = m.stock_qty
+ if m.uom and m.qty:
+ m.stock_qty = flt(m.conversion_factor)*flt(m.qty)
+ if not m.uom and m.stock_uom:
+ m.uom = m.stock_uom
+ m.qty = m.stock_qty
def set_conversion_rate(self):
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 35530fd..7ec2753 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -433,4 +433,5 @@
erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager
erpnext.patches.v8_5.remove_project_type_property_setter
erpnext.patches.v8_7.add_more_gst_fields
-erpnext.patches.v8_7.fix_purchase_receipt_status
\ No newline at end of file
+erpnext.patches.v8_7.fix_purchase_receipt_status
+erpnext.patches.v8_6.rename_bom_update_tool
\ No newline at end of file
diff --git a/erpnext/patches/v4_0/new_address_template.py b/erpnext/patches/v4_0/new_address_template.py
index f644a5a..fa66027 100644
--- a/erpnext/patches/v4_0/new_address_template.py
+++ b/erpnext/patches/v4_0/new_address_template.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
def execute():
@@ -10,5 +10,5 @@
frappe.db.get_value("Global Defaults", "Global Defaults", "country")})
d.insert()
except:
- print frappe.get_traceback()
+ print(frappe.get_traceback())
diff --git a/erpnext/patches/v4_0/reset_permissions_for_masters.py b/erpnext/patches/v4_0/reset_permissions_for_masters.py
index b2f1fcd..bc1b438 100644
--- a/erpnext/patches/v4_0/reset_permissions_for_masters.py
+++ b/erpnext/patches/v4_0/reset_permissions_for_masters.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
from frappe.permissions import reset_perms
def execute():
@@ -16,5 +16,5 @@
try:
reset_perms(doctype)
except:
- print "Error resetting perms for", doctype
+ print("Error resetting perms for", doctype)
raise
diff --git a/erpnext/patches/v4_0/set_naming_series_property_setter.py b/erpnext/patches/v4_0/set_naming_series_property_setter.py
index 9d12f14..e61a596 100644
--- a/erpnext/patches/v4_0/set_naming_series_property_setter.py
+++ b/erpnext/patches/v4_0/set_naming_series_property_setter.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
@@ -91,7 +91,7 @@
(new_series, new_series))
if not (default_series and default_series[0][0]):
- print "[Skipping] Cannot guess which naming series to use for", doctype
+ print("[Skipping] Cannot guess which naming series to use for", doctype)
return
return default_series[0][0]
diff --git a/erpnext/patches/v4_0/split_email_settings.py b/erpnext/patches/v4_0/split_email_settings.py
index 21dc050..5d1dea6 100644
--- a/erpnext/patches/v4_0/split_email_settings.py
+++ b/erpnext/patches/v4_0/split_email_settings.py
@@ -1,11 +1,11 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
def execute():
- print "WARNING!!!! Email Settings not migrated. Please setup your email again."
+ print("WARNING!!!! Email Settings not migrated. Please setup your email again.")
# this will happen if you are migrating very old accounts
# comment out this line below and remember to create new Email Accounts
diff --git a/erpnext/patches/v4_0/update_account_root_type.py b/erpnext/patches/v4_0/update_account_root_type.py
index e3edee9..15ddf03 100644
--- a/erpnext/patches/v4_0/update_account_root_type.py
+++ b/erpnext/patches/v4_0/update_account_root_type.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
def execute():
@@ -31,4 +31,4 @@
frappe.db.sql("""UPDATE tabAccount SET root_type=%s WHERE lft>%s and rgt<%s""",
(root.root_type, root.lft, root.rgt))
else:
- print b"Root type not found for {0}".format(root.name.encode("utf-8"))
+ print(b"Root type not found for {0}".format(root.name.encode("utf-8")))
diff --git a/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py b/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
index 0df5801..16932af 100644
--- a/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
+++ b/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
from frappe.utils import flt
@@ -37,7 +37,7 @@
if stock_bal and account_bal and abs(flt(stock_bal[0][0]) - flt(account_bal[0][0])) > 0.1:
try:
- print voucher_type, voucher_no, stock_bal[0][0], account_bal[0][0]
+ print(voucher_type, voucher_no, stock_bal[0][0], account_bal[0][0])
frappe.db.sql("""delete from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
@@ -45,10 +45,10 @@
voucher = frappe.get_doc(voucher_type, voucher_no)
voucher.make_gl_entries(repost_future_gle=False)
frappe.db.commit()
- except Exception, e:
- print frappe.get_traceback()
+ except Exception as e:
+ print(frappe.get_traceback())
rejected.append([voucher_type, voucher_no])
frappe.db.rollback()
- print "Failed to repost: "
- print rejected
+ print("Failed to repost: ")
+ print(rejected)
diff --git a/erpnext/patches/v4_2/party_model.py b/erpnext/patches/v4_2/party_model.py
index 8f4fc33..6f93352 100644
--- a/erpnext/patches/v4_2/party_model.py
+++ b/erpnext/patches/v4_2/party_model.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
def execute():
@@ -109,7 +109,7 @@
and exists(select gle.name from `tabGL Entry` gle where gle.account = tabAccount.name)""")
if accounts_not_deleted:
- print "Accounts not deleted: " + "\n".join(accounts_not_deleted)
+ print("Accounts not deleted: " + "\n".join(accounts_not_deleted))
def remove_customer_supplier_account_report():
diff --git a/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py b/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
index 44bec00..1356129 100644
--- a/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
+++ b/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
@@ -1,7 +1,7 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
from erpnext.stock.stock_ledger import NegativeStockError
@@ -28,7 +28,7 @@
frappe.local.stockledger_exceptions = None
frappe.db.rollback()
- print "Failed to repost: ", failed_list
+ print("Failed to repost: ", failed_list)
\ No newline at end of file
diff --git a/erpnext/patches/v4_2/set_company_country.py b/erpnext/patches/v4_2/set_company_country.py
index 929f6c5..89f07f2 100644
--- a/erpnext/patches/v4_2/set_company_country.py
+++ b/erpnext/patches/v4_2/set_company_country.py
@@ -1,13 +1,13 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
def execute():
country = frappe.db.get_single_value("Global Defaults", "country")
if not country:
- print "Country not specified in Global Defaults"
+ print("Country not specified in Global Defaults")
return
for company in frappe.db.sql_list("""select name from `tabCompany`
diff --git a/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py b/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py
index da58ae2..76efdcc 100644
--- a/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py
+++ b/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py
@@ -1,7 +1,7 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
def execute():
@@ -21,6 +21,6 @@
je.make_gl_entries()
if je_list:
- print je_list
+ print(je_list)
\ No newline at end of file
diff --git a/erpnext/patches/v5_4/fix_missing_item_images.py b/erpnext/patches/v5_4/fix_missing_item_images.py
index 1891d2d..c0a2513 100644
--- a/erpnext/patches/v5_4/fix_missing_item_images.py
+++ b/erpnext/patches/v5_4/fix_missing_item_images.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
import os
from frappe.utils import get_files_path
@@ -45,7 +45,7 @@
try:
file_data.save()
except IOError:
- print "File {0} does not exist".format(new_file_url)
+ print("File {0} does not exist".format(new_file_url))
# marking fix to prevent further errors
fixed_files.append(file_url)
diff --git a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py b/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py
index 125b84f..ba31122 100644
--- a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py
+++ b/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py
@@ -1,7 +1,7 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
from frappe.email import sendmail_to_system_managers
from frappe.utils import get_link_to_form
@@ -36,6 +36,6 @@
except:
pass
- print "="*50
- print content
- print "="*50
\ No newline at end of file
+ print("="*50)
+ print(content)
+ print("="*50)
\ No newline at end of file
diff --git a/erpnext/patches/v5_7/item_template_attributes.py b/erpnext/patches/v5_7/item_template_attributes.py
index 9f141b5..22b15d3 100644
--- a/erpnext/patches/v5_7/item_template_attributes.py
+++ b/erpnext/patches/v5_7/item_template_attributes.py
@@ -1,7 +1,7 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
import MySQLdb
@@ -32,7 +32,7 @@
migrate_item_variants()
except MySQLdb.ProgrammingError:
- print "`tabItem Variant` not found"
+ print("`tabItem Variant` not found")
def rename_and_reload_doctypes():
if "tabVariant Attribute" in frappe.db.get_tables():
diff --git a/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py b/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py
index dc0df0f..fb5eab4 100644
--- a/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py
+++ b/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
"""
@@ -38,19 +38,19 @@
si_list = get_affected_sales_invoice()
if so_list or dn_list or si_list:
- print "Entries with Target Warehouse:"
+ print("Entries with Target Warehouse:")
if so_list:
- print "Sales Order"
- print so_list
+ print("Sales Order")
+ print(so_list)
if dn_list:
- print "Delivery Notes"
- print [d.name for d in dn_list]
+ print("Delivery Notes")
+ print([d.name for d in dn_list])
if si_list:
- print "Sales Invoice"
- print [d.name for d in si_list]
+ print("Sales Invoice")
+ print([d.name for d in si_list])
def repost():
@@ -61,34 +61,34 @@
frappe.db.commit()
if dn_failed_list:
- print "-"*40
- print "Delivery Note Failed to Repost"
- print dn_failed_list
+ print("-"*40)
+ print("Delivery Note Failed to Repost")
+ print(dn_failed_list)
if si_failed_list:
- print "-"*40
- print "Sales Invoice Failed to Repost"
- print si_failed_list
- print
+ print("-"*40)
+ print("Sales Invoice Failed to Repost")
+ print(si_failed_list)
+ print()
- print """
+ print("""
If above Delivery Notes / Sales Invoice failed due to negative stock, follow these steps:
- Ensure that stock is available for those items in the mentioned warehouse on the date mentioned in the error
- Run this patch again
-"""
+""")
def repost_dn(dn_failed_list):
dn_list = get_affected_delivery_notes()
if dn_list:
- print "-"*40
- print "Reposting Delivery Notes"
+ print("-"*40)
+ print("Reposting Delivery Notes")
for dn in dn_list:
if dn.docstatus == 0:
continue
- print dn.name
+ print(dn.name)
try:
dn_doc = frappe.get_doc("Delivery Note", dn.name)
@@ -107,7 +107,7 @@
except Exception:
dn_failed_list.append(dn.name)
frappe.local.stockledger_exceptions = None
- print frappe.get_traceback()
+ print(frappe.get_traceback())
frappe.db.rollback()
frappe.db.sql("update `tabDelivery Note Item` set target_warehouse='' where docstatus=0")
@@ -116,14 +116,14 @@
si_list = get_affected_sales_invoice()
if si_list:
- print "-"*40
- print "Reposting Sales Invoice"
+ print("-"*40)
+ print("Reposting Sales Invoice")
for si in si_list:
if si.docstatus == 0:
continue
- print si.name
+ print(si.name)
try:
si_doc = frappe.get_doc("Sales Invoice", si.name)
@@ -141,7 +141,7 @@
except Exception:
si_failed_list.append(si.name)
frappe.local.stockledger_exceptions = None
- print frappe.get_traceback()
+ print(frappe.get_traceback())
frappe.db.rollback()
frappe.db.sql("update `tabSales Invoice Item` set target_warehouse='' where docstatus=0")
@@ -152,8 +152,8 @@
frappe.db.sql("update `tabSales Order Item` set target_warehouse=''")
if so_list:
- print "-"*40
- print "Sales Order reposted"
+ print("-"*40)
+ print("Sales Order reposted")
def get_affected_delivery_notes():
diff --git a/erpnext/patches/v6_4/fix_expense_included_in_valuation.py b/erpnext/patches/v6_4/fix_expense_included_in_valuation.py
index 436dd02..7ed15ab 100644
--- a/erpnext/patches/v6_4/fix_expense_included_in_valuation.py
+++ b/erpnext/patches/v6_4/fix_expense_included_in_valuation.py
@@ -1,7 +1,7 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
from frappe.utils import cstr
@@ -33,7 +33,7 @@
(pi.name, company.expenses_included_in_valuation))
if gle_for_expenses_included_in_valuation:
- print pi.name
+ print(pi.name)
frappe.db.sql("""delete from `tabGL Entry`
where voucher_type='Purchase Invoice' and voucher_no=%s""", pi.name)
diff --git a/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py b/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py
index b1464d5..b53412d 100644
--- a/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py
+++ b/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py
@@ -1,7 +1,7 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
def execute():
@@ -44,7 +44,7 @@
where name=%s""", d.name)
for d in journal_entries:
- print d
+ print(d)
# delete existing gle
frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d)
diff --git a/erpnext/patches/v6_4/make_image_thumbnail.py b/erpnext/patches/v6_4/make_image_thumbnail.py
index 702148a..3315acc 100644
--- a/erpnext/patches/v6_4/make_image_thumbnail.py
+++ b/erpnext/patches/v6_4/make_image_thumbnail.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
import frappe
def execute():
@@ -11,4 +12,4 @@
if item_doc.thumbnail:
item_doc.db_set("thumbnail", item_doc.thumbnail, update_modified=False)
except Exception:
- print "Unable to make thumbnail for {0}".format(item.website_image.encode("utf-8"))
+ print("Unable to make thumbnail for {0}".format(item.website_image.encode("utf-8")))
diff --git a/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py b/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py
index e0268c4..1319b53 100644
--- a/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py
+++ b/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py
@@ -1,7 +1,7 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
def execute():
@@ -13,7 +13,7 @@
and against_voucher=je.reference_name)""")
for d in je_list:
- print d
+ print(d)
# delete existing gle
frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d)
diff --git a/erpnext/patches/v6_6/fix_website_image.py b/erpnext/patches/v6_6/fix_website_image.py
index b3b4cab..cc3e2d8 100644
--- a/erpnext/patches/v6_6/fix_website_image.py
+++ b/erpnext/patches/v6_6/fix_website_image.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
from frappe.utils import encode
@@ -25,7 +25,7 @@
try:
file.validate_file()
except IOError:
- print encode(item.website_image), "does not exist"
+ print(encode(item.website_image), "does not exist")
file.delete()
item.db_set("website_image", None, update_modified=False)
diff --git a/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py b/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py
index 58da059..2bc0971 100644
--- a/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py
+++ b/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe, erpnext
def execute():
@@ -35,11 +35,11 @@
voucher.make_gl_entries()
frappe.db.commit()
except Exception as e:
- print frappe.get_traceback()
+ print(frappe.get_traceback())
rejected.append([voucher_type, voucher_no])
frappe.db.rollback()
- print rejected
+ print(rejected)
def set_warehouse_for_stock_account(warehouse_account):
for account in warehouse_account:
diff --git a/erpnext/patches/v7_0/rename_salary_components.py b/erpnext/patches/v7_0/rename_salary_components.py
index 4e9ceb2..8409ca8 100644
--- a/erpnext/patches/v7_0/rename_salary_components.py
+++ b/erpnext/patches/v7_0/rename_salary_components.py
@@ -81,7 +81,7 @@
try:
frappe.db.sql("""INSERT INTO `tabSalary Component` ({0}) SELECT {1} FROM `tab{2}`"""
.format(target_cols, source_cols, doctype))
- except Exception, e:
+ except Exception as e:
if e.args[0]==1062:
pass
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 3850847..cb99fd0 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\": \"<div class=\\\"print-heading\\\">\\n\\t<h2>\\n\\t\\tTAX INVOICE<br>\\n\\t\\t<small>{{ doc.name }}</small>\\n\\t</h2>\\n</div>\\n<h2 class=\\\"text-center\\\">\\n\\t{% if doc.invoice_copy -%}\\n\\t\\t<small>{{ doc.invoice_copy }}</small>\\n\\t{% endif -%}\\n</h2>\"}, {\"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\": \"<hr>\", \"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\": \"<div class=\\\"print-heading\\\">\\n\\t<h2>\\n\\t\\tTAX INVOICE<br>\\n\\t\\t<small>{{ doc.name }}</small>\\n\\t</h2>\\n</div>\\n<h2 class=\\\"text-center\\\">\\n\\t{% if doc.invoice_copy -%}\\n\\t\\t<small>{{ doc.invoice_copy }}</small>\\n\\t{% endif -%}\\n</h2>\"}, {\"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\": \"<hr>\", \"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/api.py b/erpnext/schools/api.py
index c613c8c..ff2da07 100644
--- a/erpnext/schools/api.py
+++ b/erpnext/schools/api.py
@@ -63,7 +63,7 @@
:param student_group: Student Group.
:param date: Date.
"""
-
+
present = json.loads(students_present)
absent = json.loads(students_absent)
diff --git a/erpnext/schools/doctype/course_schedule/test_course_schedule.py b/erpnext/schools/doctype/course_schedule/test_course_schedule.py
index 6a3456f..f131382 100644
--- a/erpnext/schools/doctype/course_schedule/test_course_schedule.py
+++ b/erpnext/schools/doctype/course_schedule/test_course_schedule.py
@@ -17,7 +17,7 @@
cs1 = make_course_schedule_test_record(simulate= True)
cs2 = make_course_schedule_test_record(schedule_date=cs1.schedule_date, from_time= cs1.from_time,
- to_time= cs1.to_time, instructor="_T-Instructor-00002", room="RM0002", do_not_save= 1)
+ to_time= cs1.to_time, instructor="_Test Instructor 2", room="RM0002", do_not_save= 1)
self.assertRaises(OverlapError, cs2.save)
def test_instructor_conflict(self):
@@ -31,14 +31,14 @@
cs1 = make_course_schedule_test_record(simulate= True)
cs2 = make_course_schedule_test_record(from_time= cs1.from_time, to_time= cs1.to_time,
- student_group="Course-TC101-2014-2015 (_Test Academic Term)", instructor="_T-Instructor-00002", do_not_save= 1)
+ student_group="Course-TC101-2014-2015 (_Test Academic Term)", instructor="_Test Instructor 2", do_not_save= 1)
self.assertRaises(OverlapError, cs2.save)
def test_no_conflict(self):
cs1 = make_course_schedule_test_record(simulate= True)
make_course_schedule_test_record(from_time= cs1.from_time, to_time= cs1.to_time,
- student_group="Course-TC102-2014-2015 (_Test Academic Term)", instructor="_T-Instructor-00002", room="RM0002")
+ student_group="Course-TC102-2014-2015 (_Test Academic Term)", instructor="_Test Instructor 2", room="RM0002")
def make_course_schedule_test_record(**args):
args = frappe._dict(args)
@@ -46,7 +46,7 @@
course_schedule = frappe.new_doc("Course Schedule")
course_schedule.student_group = args.student_group or "Course-TC101-2014-2015 (_Test Academic Term)"
course_schedule.course = args.course or "TC101"
- course_schedule.instructor = args.instructor or "_T-Instructor-00001"
+ course_schedule.instructor = args.instructor or "_Test Instructor"
course_schedule.room = args.room or "RM0001"
course_schedule.schedule_date = args.schedule_date or today()
diff --git a/erpnext/schools/doctype/instructor/instructor.json b/erpnext/schools/doctype/instructor/instructor.json
index a98fe69..cd0b4f1 100644
--- a/erpnext/schools/doctype/instructor/instructor.json
+++ b/erpnext/schools/doctype/instructor/instructor.json
@@ -208,7 +208,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2017-06-30 08:21:49.055531",
+ "modified": "2017-08-25 01:03:14.602994",
"modified_by": "Administrator",
"module": "Schools",
"name": "Instructor",
diff --git a/erpnext/schools/doctype/instructor/instructor.py b/erpnext/schools/doctype/instructor/instructor.py
index 4331b91..ba179f7 100644
--- a/erpnext/schools/doctype/instructor/instructor.py
+++ b/erpnext/schools/doctype/instructor/instructor.py
@@ -4,7 +4,21 @@
from __future__ import unicode_literals
import frappe
+from frappe import _
from frappe.model.document import Document
+from frappe.model.naming import make_autoname
class Instructor(Document):
- pass
+ def autoname(self):
+ naming_method = frappe.db.get_value("School Settings", None, "instructor_created_by")
+ if not naming_method:
+ frappe.throw(_("Please setup Instructor Naming System in School > School Settings"))
+ else:
+ if naming_method == 'Naming Series':
+ self.name = make_autoname(self.naming_series + '.####')
+ elif naming_method == 'Employee Number':
+ if not self.employee:
+ frappe.throw("Please select Employee")
+ self.name = self.employee
+ elif naming_method == 'Full Name':
+ self.name = self.instructor_name
diff --git a/erpnext/schools/doctype/school_settings/school_settings.json b/erpnext/schools/doctype/school_settings/school_settings.json
index 3b5aae6..b6d9890 100644
--- a/erpnext/schools/doctype/school_settings/school_settings.json
+++ b/erpnext/schools/doctype/school_settings/school_settings.json
@@ -194,6 +194,67 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "section_break_7",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "Full Name",
+ "fieldname": "instructor_created_by",
+ "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": "Instructor Records to be created by",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Full Name\nNaming Series\nEmployee Number",
+ "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,
@@ -206,7 +267,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-06-30 08:21:50.339169",
+ "modified": "2017-08-25 02:36:48.744456",
"modified_by": "Administrator",
"module": "Schools",
"name": "School Settings",
diff --git a/erpnext/schools/doctype/school_settings/school_settings.py b/erpnext/schools/doctype/school_settings/school_settings.py
index 999014a..88235cf 100644
--- a/erpnext/schools/doctype/school_settings/school_settings.py
+++ b/erpnext/schools/doctype/school_settings/school_settings.py
@@ -26,3 +26,10 @@
def get_defaults(self):
return frappe.defaults.get_defaults()
+
+ def validate(self):
+ from frappe.custom.doctype.property_setter.property_setter import make_property_setter
+ if self.get('instructor_created_by')=='Naming Series':
+ make_property_setter('Instructor', "naming_series", "hidden", 0, "Check")
+ else:
+ make_property_setter('Instructor', "naming_series", "hidden", 1, "Check")
diff --git a/erpnext/schools/doctype/student/student.js b/erpnext/schools/doctype/student/student.js
index d3d248b..cadf272 100644
--- a/erpnext/schools/doctype/student/student.js
+++ b/erpnext/schools/doctype/student/student.js
@@ -3,6 +3,11 @@
frappe.ui.form.on('Student', {
setup: function(frm) {
+ frm.add_fetch("guardian", "guardian_name", "guardian_name");
+ frm.add_fetch("student", "title", "full_name");
+ frm.add_fetch("student", "gender", "gender");
+ frm.add_fetch("student", "date_of_birth", "date_of_birth");
+
frm.set_query("student", "siblings", function(doc, cdt, cdn) {
return {
"filters": {
@@ -11,18 +16,4 @@
};
})
}
-});
-
-frappe.ui.form.on("Student Guardian", {
- guardian: function(frm) {
- frm.add_fetch("guardian", "guardian_name", "guardian_name");
- }
-});
-
-frappe.ui.form.on('Student Sibling', {
- student: function(frm) {
- frm.add_fetch("student", "title", "full_name");
- frm.add_fetch("student", "gender", "gender");
- frm.add_fetch("student", "date_of_birth", "date_of_birth");
- }
-});
+});
\ No newline at end of file
diff --git a/erpnext/schools/doctype/student_applicant/student_applicant.js b/erpnext/schools/doctype/student_applicant/student_applicant.js
index 9b08ee5..40a6ac3 100644
--- a/erpnext/schools/doctype/student_applicant/student_applicant.js
+++ b/erpnext/schools/doctype/student_applicant/student_applicant.js
@@ -39,15 +39,12 @@
method: "erpnext.schools.api.enroll_student",
frm: frm
})
- }
-});
+ },
-
-frappe.ui.form.on('Student Sibling', {
- student: function(frm) {
+ setup: function(frm) {
+ frm.add_fetch("guardian", "guardian_name", "guardian_name");
frm.add_fetch("student", "title", "full_name");
frm.add_fetch("student", "gender", "gender");
frm.add_fetch("student", "date_of_birth", "date_of_birth");
}
-});
-
+});
\ No newline at end of file
diff --git a/erpnext/schools/doctype/student_applicant/student_applicant.json b/erpnext/schools/doctype/student_applicant/student_applicant.json
index 271f873..578f84c 100644
--- a/erpnext/schools/doctype/student_applicant/student_applicant.json
+++ b/erpnext/schools/doctype/student_applicant/student_applicant.json
@@ -881,7 +881,7 @@
"in_standard_filter": 0,
"label": "Guardians",
"length": 0,
- "no_copy": 1,
+ "no_copy": 0,
"options": "Student Guardian",
"permlevel": 0,
"precision": "",
@@ -1058,7 +1058,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2017-06-30 08:21:50.917086",
+ "modified": "2017-08-23 06:12:36.996978",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Applicant",
diff --git a/erpnext/schools/doctype/student_applicant/student_applicant.py b/erpnext/schools/doctype/student_applicant/student_applicant.py
index 047c702..081fa06 100644
--- a/erpnext/schools/doctype/student_applicant/student_applicant.py
+++ b/erpnext/schools/doctype/student_applicant/student_applicant.py
@@ -2,7 +2,7 @@
# Copyright (c) 2015, Frappe Technologies and contributors
# For license information, please see license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
@@ -13,7 +13,7 @@
if self.student_admission:
naming_series = frappe.db.get_value('Student Admission', self.student_admission,
'naming_series_for_student_applicant')
- print naming_series
+ print(naming_series)
if naming_series:
self.naming_series = naming_series
diff --git a/erpnext/schools/doctype/student_group/test_student_group.py b/erpnext/schools/doctype/student_group/test_student_group.py
index 18a6b14..e358c27 100644
--- a/erpnext/schools/doctype/student_group/test_student_group.py
+++ b/erpnext/schools/doctype/student_group/test_student_group.py
@@ -8,20 +8,20 @@
from frappe.utils.make_random import get_random
class TestStudentGroup(unittest.TestCase):
- def test_student_roll_no(self):
- doc = frappe.get_doc({
- "doctype": "Student Group",
- "student_group_name": "_Test Student Group R",
+ def test_student_roll_no(self):
+ doc = frappe.get_doc({
+ "doctype": "Student Group",
+ "student_group_name": "_Test Student Group R",
"group_based_on": "Activity"
- }).insert()
+ }).insert()
- student_list = []
- while len(student_list) < 3:
- s = get_random("Student")
- if s not in student_list:
- student_list.append(s)
+ student_list = []
+ while len(student_list) < 3:
+ s = get_random("Student")
+ if s not in student_list:
+ student_list.append(s)
- doc.extend("students", [{"student":d} for d in student_list])
- doc.save()
- self.assertEquals(max([d.group_roll_number for d in doc.students]), 3)
+ doc.extend("students", [{"student":d} for d in student_list])
+ doc.save()
+ self.assertEquals(max([d.group_roll_number for d in doc.students]), 3)
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 6c6eb3a..52dcb73 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -67,7 +67,7 @@
'''If Customer created from Lead, update lead status to "Converted"
update Customer link in Quotation, Opportunity'''
if self.lead_name:
- frappe.db.set_value('Lead', self.lead_name, 'status', 'Converted', update_modified=False)
+ frappe.db.set_value('Lead', self.lead_name, 'status', 'Converted', update_modified=False)
for doctype in ('Opportunity', 'Quotation'):
for d in frappe.get_all(doctype, {'lead': self.lead_name}):
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation_submit_cancel_amend.js b/erpnext/selling/doctype/quotation/tests/test_quotation_submit_cancel_amend.js
new file mode 100644
index 0000000..26a099e
--- /dev/null
+++ b/erpnext/selling/doctype/quotation/tests/test_quotation_submit_cancel_amend.js
@@ -0,0 +1,41 @@
+QUnit.module('Quotation');
+
+QUnit.test("test quotation submit cancel amend", function(assert) {
+ assert.expect(2);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Quotation', [
+ {customer: 'Test Customer 1'},
+ {items: [
+ [
+ {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
+ {'qty': 5},
+ {'item_code': 'Test Product 1'}
+ ]
+ ]},
+ {customer_address: 'Test1-Billing'},
+ {shipping_address_name: 'Test1-Shipping'},
+ {contact_person: 'Contact 1-Test Customer 1'}
+ ]);
+ },
+ () => cur_frm.save(),
+ () => {
+ // get_item_details
+ assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
+ // get uom details
+ assert.ok(cur_frm.doc.grand_total== 500, "Grand total correct ");
+
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(1),
+ () => frappe.tests.click_button('Close'),
+ () => frappe.tests.click_button('Cancel'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.5),
+ () => frappe.tests.click_button('Amend'),
+ () => cur_frm.save(),
+ () => done()
+ ]);
+});
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 396b1c2..5f904c2 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -51,9 +51,9 @@
# validate p.o date v/s delivery date
if self.po_date:
for d in self.get("items"):
- if d.delivery_date and getdate(self.po_date) > getdate(d.delivery_date):
- frappe.throw(_("Row #{0}: Expected Delivery Date cannot be before Purchase Order Date")
- .format(d.idx))
+ if d.delivery_date and getdate(self.po_date) > getdate(d.delivery_date):
+ frappe.throw(_("Row #{0}: Expected Delivery Date cannot be before Purchase Order Date")
+ .format(d.idx))
if self.po_no and self.customer:
so = frappe.db.sql("select name from `tabSales Order` \
diff --git a/erpnext/setup/doctype/item_group/test_item_group.py b/erpnext/setup/doctype/item_group/test_item_group.py
index bc88132..c487c72 100644
--- a/erpnext/setup/doctype/item_group/test_item_group.py
+++ b/erpnext/setup/doctype/item_group/test_item_group.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import unittest
import frappe
from frappe.utils.nestedset import NestedSetRecursionError, NestedSetMultipleRootsError, \
@@ -112,7 +112,7 @@
def print_tree(self):
import json
- print json.dumps(frappe.db.sql("select name, lft, rgt from `tabItem Group` order by lft"), indent=1)
+ print(json.dumps(frappe.db.sql("select name, lft, rgt from `tabItem Group` order by lft"), indent=1))
def test_move_leaf_into_another_group(self):
# before move
diff --git a/erpnext/setup/doctype/naming_series/naming_series.js b/erpnext/setup/doctype/naming_series/naming_series.js
index e2584bf..7c76d9c 100644
--- a/erpnext/setup/doctype/naming_series/naming_series.js
+++ b/erpnext/setup/doctype/naming_series/naming_series.js
@@ -1,47 +1,55 @@
-// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-// License: GNU General Public License v3. See license.txt
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
-cur_frm.cscript.onload_post_render = function(doc, cdt, cdn) {
- cur_frm.disable_save();
- cur_frm.toolbar.print_icon.addClass("hide");
- return cur_frm.call({
- doc: cur_frm.doc,
- method: 'get_transactions',
- callback: function(r) {
- cur_frm.cscript.update_selects(r);
- cur_frm.cscript.select_doc_for_series(doc, cdt, cdn);
- }
- });
-}
+frappe.ui.form.on("Naming Series", {
+ onload: function(frm) {
+ frm.disable_save();
+ frm.events.get_doc_and_prefix(frm);
+ },
-cur_frm.cscript.update_selects = function(r) {
- set_field_options('select_doc_for_series', r.message.transactions);
- set_field_options('prefix', r.message.prefixes);
-}
+ get_doc_and_prefix: function(frm) {
+ frappe.call({
+ method: "get_transactions",
+ doc: frm.doc,
+ callback: function(r) {
+ frm.set_df_property("select_doc_for_series", "options", r.message.transactions);
+ frm.set_df_property("prefix", "options", r.message.prefixes);
+ }
+ });
+ },
-cur_frm.cscript.select_doc_for_series = function(doc, cdt, cdn) {
- cur_frm.set_value('user_must_always_select', 0);
- cur_frm.toggle_display(['help_html','set_options', 'user_must_always_select', 'update'],
- doc.select_doc_for_series);
+ select_doc_for_series: function(frm) {
+ frm.set_value("user_must_always_select", 0);
+ frappe.call({
+ method: "get_options",
+ doc: frm.doc,
+ callback: function(r) {
+ frm.set_value("set_options", r.message);
+ if(r.message && r.message.split('\n')[0]=='')
+ frm.set_value('user_must_always_select', 1);
+ frm.refresh();
+ }
+ });
+ },
- var callback = function(r, rt){
- locals[cdt][cdn].set_options = r.message;
- refresh_field('set_options');
- if(r.message && r.message.split('\n')[0]=='')
- cur_frm.set_value('user_must_always_select', 1);
+ prefix: function(frm) {
+ frappe.call({
+ method: "get_current",
+ doc: frm.doc,
+ callback: function(r) {
+ frm.refresh_field("current_value");
+ }
+ });
+ },
+
+ update: function(frm) {
+ frappe.call({
+ method: "update_series",
+ doc: frm.doc,
+ callback: function(r) {
+ frm.events.get_doc_and_prefix(frm);
+ }
+ });
}
-
- if(doc.select_doc_for_series)
- return $c_obj(doc,'get_options','',callback);
-}
-
-cur_frm.cscript.update = function() {
- return cur_frm.call_server('update_series', '', cur_frm.cscript.update_selects);
-}
-
-cur_frm.cscript.prefix = function(doc, dt, dn) {
- return cur_frm.call_server('get_current', '', function(r) {
- refresh_field('current_value');
- });
-}
+});
diff --git a/erpnext/setup/doctype/naming_series/naming_series.json b/erpnext/setup/doctype/naming_series/naming_series.json
index 0daf1a1..f936dcf 100644
--- a/erpnext/setup/doctype/naming_series/naming_series.json
+++ b/erpnext/setup/doctype/naming_series/naming_series.json
@@ -1,29 +1,40 @@
{
"allow_copy": 0,
+ "allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
+ "beta": 0,
"creation": "2013-01-25 11:35:08",
"custom": 0,
"description": "Set prefix for numbering series on your transactions",
"docstatus": 0,
"doctype": "DocType",
+ "editable_grid": 0,
"fields": [
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"description": "Set prefix for numbering series on your transactions",
"fieldname": "setup_series",
"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": "Setup Series",
+ "length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
@@ -31,20 +42,28 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"fieldname": "select_doc_for_series",
"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": "Select Transaction",
+ "length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
@@ -52,21 +71,30 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
+ "depends_on": "select_doc_for_series",
"fieldname": "help_html",
"fieldtype": "HTML",
"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": "Help HTML",
+ "length": 0,
"no_copy": 0,
"options": "<div class=\"well\">\nEdit list of Series in the box below. Rules:\n<ul>\n<li>Each Series Prefix on a new line.</li>\n<li>Allowed special characters are \"/\" and \"-\"</li>\n<li>Optionally, set the number of digits in the series using dot (.) followed by hashes (#). For example, \".####\" means that the series will have four digits. Default is five digits.</li>\n</ul>\nExamples:<br>\nINV-<br>\nINV-10-<br>\nINVK-<br>\nINV-.####<br>\n</div>",
"permlevel": 0,
"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,
@@ -74,20 +102,29 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
+ "depends_on": "select_doc_for_series",
"fieldname": "set_options",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Series List for this Transaction",
+ "length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
@@ -95,21 +132,30 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
+ "depends_on": "select_doc_for_series",
"description": "Check this if you want to force the user to select a series before saving. There will be no default if you check this.",
"fieldname": "user_must_always_select",
"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": "User must always select",
+ "length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
@@ -117,20 +163,30 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
+ "depends_on": "select_doc_for_series",
"fieldname": "update",
"fieldtype": "Button",
"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": "Update",
+ "length": 0,
"no_copy": 0,
+ "options": "",
"permlevel": 0,
"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,
@@ -138,21 +194,29 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"description": "Change the starting / current sequence number of an existing series.",
"fieldname": "update_series",
"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": "Update Series",
+ "length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
@@ -160,20 +224,28 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"fieldname": "prefix",
"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": "Prefix",
+ "length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
@@ -181,21 +253,29 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"description": "This is the number of the last created transaction with this prefix",
"fieldname": "current_value",
"fieldtype": "Int",
"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": "Current Value",
+ "length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
@@ -203,21 +283,29 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"fieldname": "update_series_start",
"fieldtype": "Button",
"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": "Update Series Number",
+ "length": 0,
"no_copy": 0,
"options": "update_series_start",
"permlevel": 0,
"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,
@@ -225,16 +313,18 @@
"unique": 0
}
],
+ "has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 1,
"icon": "fa fa-sort-by-order",
"idx": 1,
+ "image_view": 0,
"in_create": 0,
- "in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
- "modified": "2015-02-05 05:11:41.473793",
+ "max_attachments": 0,
+ "modified": "2017-08-17 03:41:37.685910",
"modified_by": "Administrator",
"module": "Setup",
"name": "Naming Series",
@@ -261,6 +351,10 @@
"write": 1
}
],
+ "quick_entry": 0,
"read_only": 1,
- "read_only_onload": 0
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "track_changes": 0,
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/naming_series/naming_series.py b/erpnext/setup/doctype/naming_series/naming_series.py
index 536b72f..4534584 100644
--- a/erpnext/setup/doctype/naming_series/naming_series.py
+++ b/erpnext/setup/doctype/naming_series/naming_series.py
@@ -21,7 +21,6 @@
where fieldname='naming_series'""")))
doctypes = list(set(get_doctypes_with_read()) | set(doctypes))
-
prefixes = ""
for d in doctypes:
options = ""
@@ -34,9 +33,8 @@
if options:
prefixes = prefixes + "\n" + options
-
prefixes.replace("\n\n", "\n")
- prefixes = "\n".join(sorted(prefixes.split()))
+ prefixes = "\n".join(sorted(prefixes.split("\n")))
return {
"transactions": "\n".join([''] + sorted(doctypes)),
@@ -112,9 +110,7 @@
where dt.name = df.dt and df.fieldname='naming_series' and dt.name != %s""",
self.select_doc_for_series)
))
- sr = [[frappe.get_meta(p).get_field("naming_series").options, p]
- for p in parent]
-
+ sr = [[frappe.get_meta(p).get_field("naming_series").options, p] for p in parent]
dt = frappe.get_doc("DocType", self.select_doc_for_series)
options = self.scrub_options_list(self.set_options.split("\n"))
for series in options:
diff --git a/erpnext/setup/doctype/naming_series/test_naming_series.js b/erpnext/setup/doctype/naming_series/test_naming_series.js
new file mode 100644
index 0000000..22b664b
--- /dev/null
+++ b/erpnext/setup/doctype/naming_series/test_naming_series.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: Naming Series", function (assert) {
+ let done = assert.async();
+
+ // number of asserts
+ assert.expect(1);
+
+ frappe.run_serially([
+ // insert a new Naming Series
+ () => frappe.tests.make('Naming Series', [
+ // values to be set
+ {key: 'value'}
+ ]),
+ () => {
+ assert.equal(cur_frm.doc.key, 'value');
+ },
+ () => done()
+ ]);
+
+});
diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py
index 7b71675..9bf15ce 100644
--- a/erpnext/setup/install.py
+++ b/erpnext/setup/install.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
from frappe import _
@@ -19,10 +19,10 @@
def check_setup_wizard_not_completed():
if frappe.db.get_default('desktop:home_page') == 'desktop':
- print
- print "ERPNext can only be installed on a fresh site where the setup wizard is not completed"
- print "You can reinstall this site (after saving your data) using: bench --site [sitename] reinstall"
- print
+ print()
+ print("ERPNext can only be installed on a fresh site where the setup wizard is not completed")
+ print("You can reinstall this site (after saving your data) using: bench --site [sitename] reinstall")
+ print()
return False
def set_single_defaults():
diff --git a/erpnext/stock/doctype/batch/test_batch.js b/erpnext/stock/doctype/batch/test_batch.js
new file mode 100644
index 0000000..af7f50f
--- /dev/null
+++ b/erpnext/stock/doctype/batch/test_batch.js
@@ -0,0 +1,23 @@
+QUnit.module('Stock');
+
+QUnit.test("test Batch", function(assert) {
+ assert.expect(1);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Batch', [
+ {batch_id:'TEST-BATCH-001'},
+ {item:'Test Product 4'},
+ {expiry_date:frappe.datetime.add_days(frappe.datetime.now_date(), 2)},
+ ]);
+ },
+ () => cur_frm.save(),
+ () => {
+ // get_item_details
+ assert.ok(cur_frm.doc.batch_id=='TEST-BATCH-001', "Batch Id correct");
+ },
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index 4477c1d..41f8b84 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -3113,7 +3113,7 @@
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
- "in_standard_filter": 1,
+ "in_standard_filter": 0,
"label": "Installation Status",
"length": 0,
"no_copy": 0,
@@ -3487,7 +3487,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2017-08-09 15:44:14.253457",
+ "modified": "2017-08-23 13:25:34.182268",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 82beff8..f5a99af 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -92,9 +92,9 @@
def so_required(self):
"""check in manage account if sales order required or not"""
if frappe.db.get_value("Selling Settings", None, 'so_required') == 'Yes':
- for d in self.get('items'):
- if not d.against_sales_order:
- frappe.throw(_("Sales Order required for Item {0}").format(d.item_code))
+ for d in self.get('items'):
+ if not d.against_sales_order:
+ frappe.throw(_("Sales Order required for Item {0}").format(d.item_code))
def validate(self):
self.validate_posting_time()
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index d12c288..2d089c4 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -84,9 +84,9 @@
def po_required(self):
if frappe.db.get_value("Buying Settings", None, "po_required") == 'Yes':
- for d in self.get('items'):
- if not d.purchase_order:
- frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code))
+ for d in self.get('items'):
+ if not d.purchase_order:
+ frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code))
def get_already_received_qty(self, po, po_detail):
qty = frappe.db.sql("""select sum(qty) from `tabPurchase Receipt Item`
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 0000000..aac09c3
--- /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_material_receipt_for_serialize_item.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt_for_serialize_item.js
new file mode 100644
index 0000000..ffd0664
--- /dev/null
+++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt_for_serialize_item.js
@@ -0,0 +1,35 @@
+QUnit.module('Stock');
+
+QUnit.test("test material receipt", function(assert) {
+ assert.expect(2);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Stock Entry', [
+ {purpose:'Material Receipt'},
+ {to_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
+ {items: [
+ [
+ {'item_code': 'Test Product 4'},
+ {'qty': 5},
+ {'batch_no':'TEST-BATCH-001'},
+ {'serial_no':'Test-Product-001\nTest-Product-002\nTest-Product-003\nTest-Product-004\nTest-Product-005'},
+ {'basic_rate':100},
+ ]
+ ]},
+ ]);
+ },
+ () => cur_frm.save(),
+ () => 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_incoming_value==500, " Incoming 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_material_transfer_for_manufacture.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer_for_manufacture.js
new file mode 100644
index 0000000..e8b2973
--- /dev/null
+++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer_for_manufacture.js
@@ -0,0 +1,34 @@
+QUnit.module('Stock');
+
+QUnit.test("test material Transfer to manufacture", function(assert) {
+ assert.expect(3);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Stock Entry', [
+ {purpose:'Material Transfer for Manufacture'},
+ {from_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
+ {to_warehouse:'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
+ {items: [
+ [
+ {'item_code': 'Test Product 1'},
+ {'qty': 1},
+ ]
+ ]},
+ ]);
+ },
+ () => cur_frm.save(),
+ () => frappe.click_button('Update Rate and Availability'),
+ () => {
+ // get_item_details
+ assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
+ assert.ok(cur_frm.doc.total_outgoing_value==100, " Outgoing Value correct");
+ assert.ok(cur_frm.doc.total_incoming_value==100, " Incoming 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 0000000..699634d
--- /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/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js
new file mode 100644
index 0000000..131d3ca
--- /dev/null
+++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js
@@ -0,0 +1,34 @@
+QUnit.module('Stock');
+
+QUnit.test("test material Transfer to manufacture", function(assert) {
+ assert.expect(3);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make('Stock Entry', [
+ {purpose:'Subcontract'},
+ {from_warehouse:'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
+ {to_warehouse:'Finished Goods - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
+ {items: [
+ [
+ {'item_code': 'Test Product 1'},
+ {'qty': 1},
+ ]
+ ]},
+ ]);
+ },
+ () => cur_frm.save(),
+ () => frappe.click_button('Update Rate and Availability'),
+ () => {
+ // get_item_details
+ assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
+ assert.ok(cur_frm.doc.total_outgoing_value==100, " Outgoing Value correct");
+ assert.ok(cur_frm.doc.total_incoming_value==100, " Incoming Value correct");
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
+
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py
index d9d9568..186eaee 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.py
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.py
@@ -18,7 +18,7 @@
self.get("item_naming_by")=="Naming Series", hide_name_field=True)
stock_frozen_limit = 356
- submitted_stock_frozen = self.stock_frozen_upto_days
+ submitted_stock_frozen = self.stock_frozen_upto_days or 0
if submitted_stock_frozen > stock_frozen_limit:
self.stock_frozen_upto_days = stock_frozen_limit
frappe.msgprint (_("`Freeze Stocks Older Than` should be smaller than %d days.") %stock_frozen_limit)
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index 403d5cb..6a4ac43 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -1,7 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
+from __future__ import print_function, unicode_literals
import frappe
from frappe.utils import flt, cstr, nowdate, nowtime
@@ -170,7 +170,7 @@
where item_code=%s and warehouse=%s and docstatus < 2""", (d[0], d[1]))
if serial_nos and flt(serial_nos[0][0]) != flt(d[2]):
- print d[0], d[1], d[2], serial_nos[0][0]
+ print(d[0], d[1], d[2], serial_nos[0][0])
sle = frappe.db.sql("""select valuation_rate, company from `tabStock Ledger Entry`
where item_code = %s and warehouse = %s and ifnull(is_cancelled, 'No') = 'No'
@@ -244,7 +244,7 @@
i = 0
for voucher_type, voucher_no in vouchers:
i+=1
- print i, "/", len(vouchers), voucher_type, voucher_no
+ print(i, "/", len(vouchers), voucher_type, voucher_no)
try:
for dt in ["Stock Ledger Entry", "GL Entry"]:
frappe.db.sql("""delete from `tab%s` where voucher_type=%s and voucher_no=%s"""%
@@ -259,9 +259,9 @@
doc.update_stock_ledger()
doc.make_gl_entries(repost_future_gle=False)
frappe.db.commit()
- except Exception, e:
- print frappe.get_traceback()
+ except Exception as e:
+ print(frappe.get_traceback())
rejected.append([voucher_type, voucher_no])
frappe.db.rollback()
- print rejected
+ print(rejected)
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index c1b76e5..306736f 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -24,7 +24,7 @@
frm.timeline.wrapper.find('.comment-header .asset-details .btn-add-to-kb').remove();
$('<button class="btn btn-xs btn-link btn-add-to-kb text-muted hidden-xs pull-right">'+
__('Help Article') + '</button>')
- .appendTo(frm.timeline.wrapper.find('.comment-header .asset-details'))
+ .appendTo(frm.timeline.wrapper.find('.comment-header .asset-details:not([data-communication-type="Comment"])'))
.on('click', function() {
var content = $(this).parents('.timeline-item:first').find('.timeline-item-content').html();
var doc = frappe.model.get_new_doc('Help Article');
diff --git a/erpnext/templates/includes/itemised_tax_breakup.html b/erpnext/templates/includes/itemised_tax_breakup.html
index 75212d5..2fda0f8 100644
--- a/erpnext/templates/includes/itemised_tax_breakup.html
+++ b/erpnext/templates/includes/itemised_tax_breakup.html
@@ -4,9 +4,9 @@
<tr>
{% for key in headers %}
{% if loop.first %}
- <th style="min-width: 120px;" class="text-left">{{ key }}</th>
+ <th class="text-left">{{ key }}</th>
{% else %}
- <th style="min-width: 80px;" class="text-right">{{ key }}</th>
+ <th class="text-right">{{ key }}</th>
{% endif %}
{% endfor%}
</tr>
@@ -23,7 +23,7 @@
{% if tax_details %}
<td class='text-right'>
{% if tax_details.tax_rate or not tax_details.tax_amount %}
- ({{ tax_details.tax_rate }})
+ ({{ tax_details.tax_rate }}%)<br>
{% endif %}
{{ frappe.utils.fmt_money(tax_details.tax_amount, None, company_currency) }}
</td>
diff --git a/erpnext/templates/includes/product_page.js b/erpnext/templates/includes/product_page.js
index 3905959..b2d5ad9 100644
--- a/erpnext/templates/includes/product_page.js
+++ b/erpnext/templates/includes/product_page.js
@@ -73,7 +73,7 @@
}
}
- if (window.location.search.indexOf(item_code)!==-1) {
+ if (window.location.search == ("?variant=" + item_code) || window.location.search.includes(item_code)) {
return;
}
diff --git a/erpnext/templates/utils.py b/erpnext/templates/utils.py
index e46fed6..6ebe411 100644
--- a/erpnext/templates/utils.py
+++ b/erpnext/templates/utils.py
@@ -36,11 +36,11 @@
))
if customer:
- opportunity.customer = customer[0][0]
+ opportunity.customer = customer[0][0]
elif lead:
- opportunity.lead = lead
+ opportunity.lead = lead
else:
- opportunity.lead = new_lead.name
+ opportunity.lead = new_lead.name
opportunity.insert(ignore_permissions=True)
diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt
index cb33c90..880263f 100644
--- a/erpnext/tests/ui/tests.txt
+++ b/erpnext/tests/ui/tests.txt
@@ -66,12 +66,23 @@
erpnext/hr/doctype/job_opening/test_job_opening.js
erpnext/hr/doctype/job_applicant/test_job_applicant.js
erpnext/hr/doctype/offer_letter/test_offer_letter.js
+erpnext/hr/doctype/appraisal_template/test_appraisal_template.js
+erpnext/hr/doctype/appraisal/test_appraisal.js
+erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.js
+erpnext/hr/doctype/expense_claim/test_expense_claim.js
+erpnext/hr/doctype/training_event/test_training_event.js
+erpnext/hr/doctype/training_result_employee/test_training_result.js
+erpnext/hr/doctype/training_feedback/test_training_feedback.js
+erpnext/hr/doctype/loan_type/test_loan_type.js
+erpnext/hr/doctype/employee_loan_application/test_employee_loan_application.js
+erpnext/hr/doctype/employee_loan/test_employee_loan.js
erpnext/buying/doctype/supplier/test_supplier.js
erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js
erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js
erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js
erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js
erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js
+erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment_request.js
erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js
erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js
erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js
@@ -102,4 +113,15 @@
erpnext/schools/doctype/assessment_plan/test_assessment_plan.js
erpnext/schools/doctype/assessment_result/test_assessment_result.js
erpnext/schools/doctype/assessment_result_tool/test_assessment_result_tool.js
+erpnext/accounts/doctype/journal_entry/test_journal_entry.js
erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js
+erpnext/accounts/doctype/payment_entry/tests/test_payment_entry.js
+erpnext/selling/doctype/quotation/tests/test_quotation_submit_cancel_amend.js
+erpnext/stock/doctype/batch/test_batch.js
+erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.js
+erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt_for_serialize_item.js
+erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer_for_manufacture.js
+erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js
+erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue_with_serialize_item.js
+erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_repack.js
+erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_item.js
\ No newline at end of file
diff --git a/erpnext/utilities/__init__.py b/erpnext/utilities/__init__.py
index 944f978..0f641b2 100644
--- a/erpnext/utilities/__init__.py
+++ b/erpnext/utilities/__init__.py
@@ -1,5 +1,5 @@
## temp utility
-
+from __future__ import print_function
import frappe
from erpnext.utilities.activation import get_level
from frappe.utils import cstr
@@ -12,7 +12,7 @@
for f in dt.fields:
if f.fieldname == d.fieldname and f.fieldtype in ("Text", "Small Text"):
- print f.parent, f.fieldname
+ print(f.parent, f.fieldname)
f.fieldtype = "Text Editor"
dt.save()
break