diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 416aaf4454b..a2dc1727673 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '10.1.13'
+__version__ = '10.1.14'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 2692f3ce479..fd48faa3a29 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -88,6 +88,9 @@ class PaymentRequest(Document):
controller = get_payment_gateway_controller(self.payment_gateway)
controller.validate_transaction_currency(self.currency)
+ if hasattr(controller, 'validate_minimum_transaction_amount'):
+ controller.validate_minimum_transaction_amount(self.currency, self.grand_total)
+
return controller.get_payment_url(**{
"amount": flt(self.grand_total, self.precision("grand_total")),
"title": data.company.encode("utf-8"),
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index 0479cd8d18c..e047b6d67e0 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -132,7 +132,7 @@ def get_serial_no_for_item(args):
"name": args.name,
"serial_no": args.serial_no
})
- if args.get("parenttype") in ("Sales Invoice", "Delivery Note") and args.stock_qty > 0:
+ if args.get("parenttype") in ("Sales Invoice", "Delivery Note") and flt(args.stock_qty) > 0:
item_details.serial_no = get_serial_no(args)
return item_details
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 15b8cfc2dcd..cfcc3412914 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -751,7 +751,7 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 1,
+ "read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -4713,7 +4713,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2018-03-13 15:19:54.711885",
+ "modified": "2018-03-16 15:19:54.711885",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
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
index 0377ff9a66b..33af3135dd2 100644
--- a/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json
+++ b/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json
@@ -7,10 +7,10 @@
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
- "html": "\n\n
\n\t{{ doc.company }} \n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\" \", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t{{ _(\"GSTIN\") }}: {{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \" GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t \n\t{% if doc.docstatus == 0 %}\n\t\t{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }} \n\t{% else %}\n\t\t{{ doc.select_print_heading or _(\"Invoice\") }} \n\t{% endif %}\n
\n\n\t{{ _(\"Receipt No\") }}: {{ doc.name }} \n\t{{ _(\"Date\") }}: {{ doc.get_formatted(\"posting_date\") }} \n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\" \", \" \") %}\n\t\t{{ _(\"Customer\") }}: \n\t\t{{ doc.customer_name }} \n\t\t{{ customer_address }}\n\t{% endif %}\n
\n\n \n\n\t\n\t\t\n\t\t\t{{ _(\"Item\") }} \n\t\t\t{{ _(\"Qty\") }} \n\t\t\t{{ _(\"Amount\") }} \n\t\t \n\t \n\t\n\t\t{%- for item in doc.items -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t {{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t{{ _(\"HSN/SAC\") }}: {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t{{ _(\"Serial No\") }}: {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t \n\t\t\t{{ item.qty }} @ {{ item.rate }} \n\t\t\t{{ item.get_formatted(\"amount\") }} \n\t\t \n\t\t{%- endfor -%}\n\t \n
\n\n\t\n\t\t\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t \n\t\t\t{% else %}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t \n\t\t\t{% endif %}\n\t\t \n\t\t{%- for row in doc.taxes -%}\n\t\t {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t \n\t\t\t \n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t \n\t\t\t\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t \n\t\t \n\t\t{%- endif -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Grand Total\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t \n\t\t \n\t\t{%- if doc.rounded_total -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Rounded Total\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t \n\t\t \n\t\t{%- endif -%}\n\t \n
\nTax Breakup:
\n\n\t{{ doc.other_charges_calculation }}\n
\n{{ doc.terms or \"\" }}
\n{{ _(\"Thank you, please visit again.\") }}
",
+ "html": "\n\n\n\t{{ doc.company }} \n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\" \", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t{{ _(\"GSTIN\") }}: {{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \" GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t \n\t{% if doc.docstatus == 0 %}\n\t\t{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }} \n\t{% else %}\n\t\t{{ doc.select_print_heading or _(\"Invoice\") }} \n\t{% endif %}\n
\n\n\t{{ _(\"Receipt No\") }}: {{ doc.name }} \n\t{{ _(\"Date\") }}: {{ doc.get_formatted(\"posting_date\") }} \n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\" \", \" \") %}\n\t\t{{ _(\"Customer\") }}: \n\t\t{{ doc.customer_name }} \n\t\t{{ customer_address }}\n\t{% endif %}\n
\n\n \n\n\t\n\t\t\n\t\t\t{{ _(\"Item\") }} \n\t\t\t{{ _(\"Qty\") }} \n\t\t\t{{ _(\"Amount\") }} \n\t\t \n\t \n\t\n\t\t{%- for item in doc.items -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t {{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t{{ _(\"HSN/SAC\") }}: {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t{{ _(\"Serial No\") }}: {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t \n\t\t\t{{ item.qty }} @ {{ item.rate }} \n\t\t\t{{ item.get_formatted(\"amount\") }} \n\t\t \n\t\t{%- endfor -%}\n\t \n
\n\n\t\n\t\t\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t \n\t\t\t{% else %}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t \n\t\t\t{% endif %}\n\t\t \n\t\t{%- for row in doc.taxes -%}\n\t\t {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t \n\t\t\t \n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t \n\t\t\t\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t \n\t\t \n\t\t{%- endif -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Grand Total\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t \n\t\t \n\t\t{%- if doc.rounded_total -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Rounded Total\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t \n\t\t \n\t\t{%- endif -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Paid Amount\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t \n\t\t \n\t{%- if doc.change_amount -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Change Amount\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t \n\t\t \n\t{%- endif -%}\n\t \n
\nTax Breakup:
\n\n\t{{ doc.other_charges_calculation }}\n
\n{{ doc.terms or \"\" }}
\n{{ _(\"Thank you, please visit again.\") }}
",
"idx": 0,
"line_breaks": 0,
- "modified": "2018-02-07 12:38:36.011318",
+ "modified": "2018-03-20 14:24:08.167930",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GST POS Invoice",
diff --git a/erpnext/accounts/print_format/pos_invoice/pos_invoice.json b/erpnext/accounts/print_format/pos_invoice/pos_invoice.json
index bef6a02a992..c3450d6a73c 100644
--- a/erpnext/accounts/print_format/pos_invoice/pos_invoice.json
+++ b/erpnext/accounts/print_format/pos_invoice/pos_invoice.json
@@ -6,10 +6,10 @@
"doc_type": "Sales Invoice",
"docstatus": 0,
"doctype": "Print Format",
- "html": "\n\n\n\t{{ doc.company }} \n\t{% if doc.docstatus == 0 %}\n\t\t{{ doc.status + \" \" + (doc.select_print_heading or _(\"Invoice\")) }} \n\t{% else %}\n\t\t{{ doc.select_print_heading or _(\"Invoice\") }} \n\t{% endif %}\n
\n\n\t{{ _(\"Receipt No\") }}: {{ doc.name }} \n\t{{ _(\"Date\") }}: {{ doc.get_formatted(\"posting_date\") }} \n\t{{ _(\"Customer\") }}: {{ doc.customer_name }}\n
\n\n \n\n\t\n\t\t\n\t\t\t{{ _(\"Item\") }} \n\t\t\t{{ _(\"Qty\") }} \n\t\t\t{{ _(\"Amount\") }} \n\t\t \n\t \n\t\n\t\t{%- for item in doc.items -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t {{ item.item_name }}{%- endif -%}\n\t\t\t \n\t\t\t{{ item.qty }} @ {{ item.get_formatted(\"rate\") }} \n\t\t\t{{ item.get_formatted(\"amount\") }} \n\t\t \n\t\t{%- endfor -%}\n\t \n
\n\n\t\n\t\t\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t \n\t\t\t{% else %}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t \n\t\t\t{% endif %}\n\t\t \n\t\t{%- for row in doc.taxes -%}\n\t\t {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t \n\t\t\t \n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t \n\t\t\t\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t \n\t\t \n\t\t{%- endif -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Grand Total\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t \n\t\t \n\t\t{%- if doc.rounded_total -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Rounded Total\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t \n\t\t \n\t\t{%- endif -%}\n\t\t{%- if doc.pos_total_qty -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Total Qty\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"pos_total_qty\") }}\n\t\t\t \n\t\t \n\t\t{%- endif -%}\n\t \n
\n \n{{ doc.terms or \"\" }}
\n{{ _(\"Thank you, please visit again.\") }}
",
+ "html": "\n\n\n\t{{ doc.company }} \n\t{% if doc.docstatus == 0 %}\n\t\t{{ doc.status + \" \" + (doc.select_print_heading or _(\"Invoice\")) }} \n\t{% else %}\n\t\t{{ doc.select_print_heading or _(\"Invoice\") }} \n\t{% endif %}\n
\n\n\t{{ _(\"Receipt No\") }}: {{ doc.name }} \n\t{{ _(\"Date\") }}: {{ doc.get_formatted(\"posting_date\") }} \n\t{{ _(\"Customer\") }}: {{ doc.customer_name }}\n
\n\n \n\n\t\n\t\t\n\t\t\t{{ _(\"Item\") }} \n\t\t\t{{ _(\"Qty\") }} \n\t\t\t{{ _(\"Amount\") }} \n\t\t \n\t \n\t\n\t\t{%- for item in doc.items -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t {{ item.item_name }}{%- endif -%}\n\t\t\t \n\t\t\t{{ item.qty }} @ {{ item.get_formatted(\"rate\") }} \n\t\t\t{{ item.get_formatted(\"amount\") }} \n\t\t \n\t\t{%- endfor -%}\n\t \n
\n\n\t\n\t\t\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t \n\t\t\t{% else %}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t \n\t\t\t{% endif %}\n\t\t \n\t\t{%- for row in doc.taxes -%}\n\t\t {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t \n\t\t\t \n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t \n\t\t\t\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t \n\t\t \n\t\t{%- endif -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Grand Total\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t \n\t\t \n\t\t{%- if doc.rounded_total -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Rounded Total\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t \n\t\t \n\t\t{%- endif -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Paid Amount\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t \n\t\t \n\t\t{%- if doc.change_amount -%}\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Change Amount\") }} \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t \n\t\t\t \n\t\t{%- endif -%}\n\t\t{%- if doc.pos_total_qty -%}\n\t\t\n\t\t\t\n\t\t\t\t{{ _(\"Total Qty\") }} \n\t\t\t \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"pos_total_qty\") }}\n\t\t\t \n\t\t \n\t\t{%- endif -%}\n\t \n
\n \n{{ doc.terms or \"\" }}
\n{{ _(\"Thank you, please visit again.\") }}
",
"idx": 1,
"line_breaks": 0,
- "modified": "2018-02-08 05:39:47.280705",
+ "modified": "2018-03-20 14:24:12.394354",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Invoice",
diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js
index 0c24feb96d5..63ef83263cc 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.js
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js
@@ -14,7 +14,13 @@ frappe.query_reports["Accounts Payable"] = {
"fieldname":"supplier",
"label": __("Supplier"),
"fieldtype": "Link",
- "options": "Supplier"
+ "options": "Supplier",
+ on_change: () => {
+ var supplier = frappe.query_report_filters_by_name.supplier.get_value();
+ frappe.db.get_value('Supplier', supplier, "tax_id", function(value) {
+ frappe.query_report_filters_by_name.tax_id.set_value(value["tax_id"]);
+ });
+ }
},
{
"fieldname":"report_date",
@@ -52,6 +58,12 @@ frappe.query_reports["Accounts Payable"] = {
"fieldtype": "Int",
"default": "90",
"reqd": 1
+ },
+ {
+ "fieldname":"tax_id",
+ "label": __("Tax Id"),
+ "fieldtype": "Data",
+ "hidden": 1
}
],
onload: function(report) {
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
index d96fc996bce..10f326242b7 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
@@ -13,6 +13,11 @@
{%= __(report.report_name) %}
{%= filters.customer || filters.supplier %}
+
+ {% if (filters.tax_id) { %}
+ {%= __("Tax Id: ")%} {%= filters.tax_id %}
+ {% } %}
+
{%= __(filters.ageing_based_on) %}
{%= __("Until") %}
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
index 82f35078a2a..ec1e9f9d61f 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -14,7 +14,13 @@ frappe.query_reports["Accounts Receivable"] = {
"fieldname":"customer",
"label": __("Customer"),
"fieldtype": "Link",
- "options": "Customer"
+ "options": "Customer",
+ on_change: () => {
+ var customer = frappe.query_report_filters_by_name.customer.get_value();
+ frappe.db.get_value('Customer', customer, "tax_id", function(value) {
+ frappe.query_report_filters_by_name.tax_id.set_value(value["tax_id"]);
+ });
+ }
},
{
"fieldname":"customer_group",
@@ -87,6 +93,12 @@ frappe.query_reports["Accounts Receivable"] = {
"fieldname":"show_pdc_in_print",
"label": __("Show PDC in Print"),
"fieldtype": "Check",
+ },
+ {
+ "fieldname":"tax_id",
+ "label": __("Tax Id"),
+ "fieldtype": "Data",
+ "hidden": 1
}
],
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
index 845a2c5362f..08b24fb1478 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
@@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
+from frappe.utils import flt
from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
class AccountsReceivableSummary(ReceivablePayableReport):
@@ -88,7 +89,8 @@ class AccountsReceivableSummary(ReceivablePayableReport):
})
)
for k in party_total[d.party].keys():
- party_total[d.party][k] += d.get(k, 0)
+ if k != "currency":
+ party_total[d.party][k] += flt(d.get(k, 0))
party_total[d.party].currency = d.currency
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.html b/erpnext/accounts/report/general_ledger/general_ledger.html
index 7f50599fbe1..9a2205a5791 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.html
+++ b/erpnext/accounts/report/general_ledger/general_ledger.html
@@ -8,6 +8,13 @@
{%= filters.account %}
{% } %}
+
+
+ {% if (filters.tax_id) { %}
+ {%= __("Tax Id: ")%} {%= filters.tax_id %}
+ {% } %}
+
+
{%= frappe.datetime.str_to_user(filters.from_date) %}
{%= __("to") %}
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index d6a2aec9545..b7f96c6a3d9 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -87,6 +87,12 @@ frappe.query_reports["General Ledger"] = {
frappe.db.get_value(party_type, party, fieldname, function(value) {
frappe.query_report_filters_by_name.party_name.set_value(value[fieldname]);
});
+
+ if (party_type === "Customer" || party_type === "Supplier") {
+ frappe.db.get_value(party_type, party, "tax_id", function(value) {
+ frappe.query_report_filters_by_name.tax_id.set_value(value["tax_id"]);
+ });
+ }
}
},
{
@@ -95,6 +101,12 @@ frappe.query_reports["General Ledger"] = {
"fieldtype": "Data",
"hidden": 1
},
+ {
+ "fieldname":"tax_id",
+ "label": __("Tax Id"),
+ "fieldtype": "Data",
+ "hidden": 1
+ },
{
"fieldname":"group_by_voucher",
"label": __("Group by Voucher"),
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py
index 73bb4dc22d8..cf599a0ccc6 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -43,7 +43,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
row += [
supplier_details.get(inv.supplier), # supplier_type
- inv.credit_to, inv.mode_of_payment, ", ".join(project),
+ inv.tax_id, inv.credit_to, inv.mode_of_payment, ", ".join(project),
inv.bill_no, inv.bill_date, inv.remarks,
", ".join(purchase_order), ", ".join(purchase_receipt), company_currency
]
@@ -83,7 +83,7 @@ def get_columns(invoice_list, additional_table_columns):
columns += additional_table_columns
columns += [
- _("Supplier Type") + ":Link/Supplier Type:120", _("Payable Account") + ":Link/Account:120",
+ _("Supplier Type") + ":Link/Supplier Type:120", _("Tax Id") + "::80", _("Payable Account") + ":Link/Account:120",
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
_("Bill No") + "::120", _("Bill Date") + ":Date:80", _("Remarks") + "::150",
_("Purchase Order") + ":Link/Purchase Order:100",
@@ -143,7 +143,7 @@ def get_invoices(filters, additional_query_columns):
conditions = get_conditions(filters)
return frappe.db.sql("""
select
- name, posting_date, credit_to, supplier, supplier_name, bill_no, bill_date,
+ name, posting_date, credit_to, supplier, supplier_name, tax_id, bill_no, bill_date,
remarks, base_net_total, base_grand_total, outstanding_amount,
mode_of_payment {0}
from `tabPurchase Invoice`
diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py
index 757b7609f0b..a318751ee04 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -47,6 +47,7 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
row +=[
inv.get("customer_group"),
inv.get("territory"),
+ inv.get("tax_id"),
inv.debit_to, ", ".join(mode_of_payments.get(inv.name, [])),
inv.project, inv.owner, inv.remarks,
", ".join(sales_order), ", ".join(delivery_note),", ".join(cost_center),
@@ -89,7 +90,7 @@ def get_columns(invoice_list, additional_table_columns):
columns +=[
_("Customer Group") + ":Link/Customer Group:120", _("Territory") + ":Link/Territory:80",
- _("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120",
+ _("Tax Id") + "::80", _("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120",
_("Project") +":Link/Project:80", _("Owner") + "::150", _("Remarks") + "::150",
_("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100",
_("Cost Center") + ":Link/Cost Center:100", _("Warehouse") + ":Link/Warehouse:100",
@@ -161,7 +162,7 @@ def get_invoices(filters, additional_query_columns):
conditions = get_conditions(filters)
return frappe.db.sql("""
select name, posting_date, debit_to, project, customer,
- customer_name, owner, remarks, territory, customer_group,
+ customer_name, owner, remarks, territory, tax_id, customer_group,
base_net_total, base_grand_total, base_rounded_total, outstanding_amount {0}
from `tabSales Invoice`
where docstatus = 1 %s order by posting_date desc, name desc""".format(additional_query_columns or '') %
diff --git a/erpnext/config/education.py b/erpnext/config/education.py
index e4e77f36d60..5a05a258b21 100644
--- a/erpnext/config/education.py
+++ b/erpnext/config/education.py
@@ -135,6 +135,10 @@ def get_data():
"name": "Assessment Plan Status",
"doctype": "Assessment Plan"
},
+ {
+ "type": "doctype",
+ "name": "Student Report Generation Tool"
+ }
]
},
{
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index df0fec833d9..e8e851d513a 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -285,7 +285,7 @@ class StatusUpdater(Document):
ifnull((select
ifnull(sum(if(%(target_ref_field)s > %(target_field)s, abs(%(target_field)s), abs(%(target_ref_field)s))), 0)
/ sum(abs(%(target_ref_field)s)) * 100
- from `tab%(target_dt)s` where parent="%(name)s"), 0), 2)
+ from `tab%(target_dt)s` where parent="%(name)s" having sum(abs(%(target_ref_field)s)) > 0), 0), 2)
%(update_modified)s
where name='%(name)s'""" % args)
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index b40b986ea5e..8b0ea3ed09c 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -252,7 +252,7 @@ class StockController(AccountsController):
"company": self.company,
"batch_no": cstr(d.get("batch_no")).strip(),
"serial_no": d.get("serial_no"),
- "project": d.get("project"),
+ "project": d.get("project") or self.get('project'),
"is_cancelled": self.docstatus==2 and "Yes" or "No"
})
diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py
index a830e5bdc06..841c2e88c42 100644
--- a/erpnext/education/doctype/student/student.py
+++ b/erpnext/education/doctype/student/student.py
@@ -22,14 +22,16 @@ class Student(Document):
def update_student_name_in_linked_doctype(self):
linked_doctypes = get_linked_doctypes("Student")
for d in linked_doctypes:
- if "student_name" in [f.fieldname for f in frappe.get_meta(d).fields]:
- frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s"""
- .format(d, linked_doctypes[d]["fieldname"]),(self.title, self.name))
+ meta = frappe.get_meta(d)
+ if not meta.issingle:
+ if "student_name" in [f.fieldname for f in meta.fields]:
+ frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s"""
+ .format(d, linked_doctypes[d]["fieldname"]),(self.title, self.name))
- if "child_doctype" in linked_doctypes[d].keys() and "student_name" in \
- [f.fieldname for f in frappe.get_meta(linked_doctypes[d]["child_doctype"]).fields]:
- frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s"""
- .format(linked_doctypes[d]["child_doctype"], linked_doctypes[d]["fieldname"]),(self.title, self.name))
+ if "child_doctype" in linked_doctypes[d].keys() and "student_name" in \
+ [f.fieldname for f in frappe.get_meta(linked_doctypes[d]["child_doctype"]).fields]:
+ frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s"""
+ .format(linked_doctypes[d]["child_doctype"], linked_doctypes[d]["fieldname"]),(self.title, self.name))
def check_unique(self):
"""Validates if the Student Applicant is Unique"""
diff --git a/erpnext/education/doctype/student_report_generation_tool/__init__.py b/erpnext/education/doctype/student_report_generation_tool/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html
new file mode 100644
index 00000000000..72772b7b32c
--- /dev/null
+++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html
@@ -0,0 +1,371 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ _("Student ID: ") }}
+
+
+ {{ doc.students[0] }}
+
+
+
+
+
+ {{ _("Student Name: ") }}
+
+
+ {{ doc.student_name }}
+
+
+
+
+
+ {{ _("Program: ") }}
+
+
+ {{ doc.program }}
+
+
+
+
+
+ {{ _("Batch: ") }}
+
+
+ {{ doc.student_batch }}
+
+
+
+
+
+
+
+ {{ _("Academic Year: ") }}
+
+
+ {{ doc.academic_year }}
+
+
+
+ {% if doc.academic_term %}
+
+
+ {{ _("Academic Term: ") }}
+
+
+ {{ doc.academic_term }}
+
+
+ {% endif %}
+
+
+
+ {{ _("Assessment Group: ") }}
+
+
+ {{ doc.assessment_group }}
+
+
+
+
+
+
+{% if doc.show_marks | int %}
+ {% set result_data = 'score' %}
+{% else %}
+ {% set result_data = 'grade' %}
+{% endif %}
+
+
+{% for course in courses %}
+
+
+
+
+
+
+
+
+
+ {{ _("Course: ") }}
+
+
+ {{ course }} ({{ frappe.db.get_value("Course", course, "course_name") }})
+
+
+
+
+
+ {{ _("Assessment Criteria") }}
+ {% for assessment_group in assessment_groups %}
+ {{ assessment_group }}
+ {% endfor %}
+
+
+
+
+ {% for criteria in course_criteria[course] %}
+
+ {{ criteria }}
+ {% for assessment_group in assessment_groups %}
+ {% if (assessment_result.get(course) and assessment_result.get(course).get(assessment_group) and assessment_result.get(course).get(assessment_group).get(criteria)) %}
+
+ {{ assessment_result.get(course).get(assessment_group).get(criteria).get(result_data) }}
+ {% if result_data == 'score' %}
+ ({{ assessment_result.get(course).get(assessment_group).get(criteria).get('maximum_score') }})
+ {% endif %}
+
+ {% else %}
+
+ {% endif %}
+ {% endfor %}
+
+ {% endfor %}
+
+
+
+
+
+
+
+{% endfor %}
+
+
+
+
+
+
{{ _("Student Attendance")}}
+
+ Present {{ doc.attendance.get("Present") if doc.attendance.get("Present") != None else '0' }} days
+ out of {{ doc.attendance.get("Present") + doc.attendance.get("Absent") }}
+
+
+
+
+
{{ _("Parents Teacher Meeting Attendance")}}
+
+ Present {{ doc.parents_attendance if doc.parents_attendance != None else '0' }}
+ out of {{ doc.parents_meeting if doc.parents_meeting != None else '0' }}
+
+
+
+
+{% if doc.assessment_terms %}
+
+
+
{{ doc.assessment_terms }}
+
+
+{% endif %}
+
diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.js b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.js
new file mode 100644
index 00000000000..d5103ca2ad3
--- /dev/null
+++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.js
@@ -0,0 +1,66 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Student Report Generation Tool', {
+ onload: function(frm) {
+ frm.set_query("academic_term",function(){
+ return{
+ "filters":{
+ "academic_year": frm.doc.academic_year
+ }
+ };
+ });
+ frm.set_query("assessment_group", function() {
+ return{
+ filters: {
+ "is_group": 1
+ }
+ };
+ });
+ },
+
+ refresh: function(frm) {
+ frm.disable_save();
+ frm.page.clear_indicator();
+ frm.page.set_primary_action(__('Print Report Card'), () => {
+ let url = "/api/method/erpnext.education.doctype.student_report_generation_tool.student_report_generation_tool.preview_report_card";
+ open_url_post(url, frm.doc, true);
+ });
+ },
+
+ student: function(frm) {
+ if (frm.doc.student) {
+ frappe.call({
+ method:"erpnext.education.api.get_current_enrollment",
+ args: {
+ "student": frm.doc.student,
+ "academic_year": frm.doc.academic_year
+ },
+ callback: function(r) {
+ if(r){
+ $.each(r.message, function(i, d) {
+ if (frm.fields_dict.hasOwnProperty(i)) {
+ frm.set_value(i, d);
+ }
+ });
+ }
+ }
+ });
+ }
+ },
+
+ terms: function(frm) {
+ if(frm.doc.terms) {
+ return frappe.call({
+ method: 'erpnext.setup.doctype.terms_and_conditions.terms_and_conditions.get_terms_and_conditions',
+ args: {
+ template_name: frm.doc.terms,
+ doc: frm.doc
+ },
+ callback: function(r) {
+ frm.set_value("assessment_terms", r.message);
+ }
+ });
+ }
+ }
+});
diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.json b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.json
new file mode 100644
index 00000000000..88c59c2bdb6
--- /dev/null
+++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.json
@@ -0,0 +1,582 @@
+{
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2018-01-15 15:36:32.830069",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "student",
+ "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": "Student",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Student",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "student_name",
+ "fieldtype": "Read Only",
+ "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": "Student Name",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "program",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Program",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Program",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "student_batch",
+ "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": "Batch",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Student Batch Name",
+ "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": "include_all_assessment",
+ "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": "Include All Assessment Group",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "show_marks",
+ "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": "Show Marks",
+ "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": "1",
+ "fieldname": "add_letterhead",
+ "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": "Add letterhead",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "assessment_group",
+ "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": "Assessment Group",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Assessment Group",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "academic_year",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Academic Year",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Academic Year",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "academic_term",
+ "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": "Academic Term",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Academic Term",
+ "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": "add_letterhead",
+ "fieldname": "letter_head",
+ "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": "Letter Head",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Letter Head",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Print Section",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "parents_meeting",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Total Parents Teacher Meeting",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "parents_attendance",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Attended by Parents",
+ "length": 0,
+ "no_copy": 0,
+ "options": "",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "terms",
+ "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": "Terms",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Terms and Conditions",
+ "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": "assessment_terms",
+ "fieldtype": "Text Editor",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Assessment Terms",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 1,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 1,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-03-20 17:57:53.936119",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Report Generation Tool",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 0,
+ "email": 0,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 0,
+ "read": 1,
+ "report": 0,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 0,
+ "submit": 0,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py
new file mode 100644
index 00000000000..7b2e00713ab
--- /dev/null
+++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from erpnext.education.api import get_grade
+from frappe.utils.pdf import get_pdf
+from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import get_formatted_result
+from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import get_child_assessment_groups
+
+
+class StudentReportGenerationTool(Document):
+ pass
+
+
+@frappe.whitelist()
+def preview_report_card(**kwargs):
+ doc = frappe._dict(**kwargs)
+ doc.students = [doc.student]
+ if not (doc.student_name and doc.student_batch):
+ program_enrollment = frappe.get_all("Program Enrollment", fields=["student_batch_name", "student_name"],
+ filters={"student": doc.student, "docstatus": ('!=', 2), "academic_year": doc.academic_year})
+ if program_enrollment:
+ doc.batch = program_enrollment[0].student_batch_name
+ doc.student_name = program_enrollment[0].student_name
+
+ # get the assessment result of the selected student
+ values = get_formatted_result(doc, get_course=True, get_all_assessment_groups=doc.include_all_assessment)
+ assessment_result = values.get("assessment_result").get(doc.student)
+ courses = values.get("course_dict")
+ course_criteria = get_courses_criteria(courses)
+
+ # get the assessment group as per the user selection
+ if int(doc.include_all_assessment):
+ assessment_groups = get_child_assessment_groups(doc.assessment_group)
+ else:
+ assessment_groups = [doc.assessment_group]
+
+ # get the attendance of the student for that peroid of time.
+ doc.attendance = get_attendance_count(doc.students[0], doc.academic_year, doc.academic_term)
+
+ template = "erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html"
+ base_template_path = "frappe/www/printview.html"
+
+ from frappe.www.printview import get_letter_head
+ letterhead = get_letter_head(frappe._dict({"letter_head": doc.letterhead}), not doc.add_letterhead)
+
+ html = frappe.render_template(template,
+ {
+ "doc": doc,
+ "assessment_result": assessment_result,
+ "courses": courses,
+ "assessment_groups": assessment_groups,
+ "course_criteria": course_criteria,
+ "letterhead": letterhead.content,
+ "add_letterhead": int(doc.add_letterhead) if int(doc.add_letterhead) else 0
+ })
+ final_template = frappe.render_template(base_template_path, {"body": html, "title": "Report Card"})
+
+ frappe.response.filename = "Report Card " + doc.students[0] + ".pdf"
+ frappe.response.filecontent = get_pdf(final_template)
+ frappe.response.type = "download"
+
+
+def get_courses_criteria(courses):
+ course_criteria = frappe._dict()
+ for course in courses:
+ course_criteria[course] = [d.assessment_criteria for d in frappe.get_all("Course Assessment Criteria",
+ fields=["assessment_criteria"], filters={"parent": course})]
+ return course_criteria
+
+
+def get_attendance_count(student, academic_year, academic_term=None):
+ if academic_year:
+ from_date, to_date = frappe.db.get_value("Academic Year", academic_year, ["year_start_date", "year_end_date"])
+ elif academic_term:
+ from_date, to_date = frappe.db.get_value("Academic Term", academic_term, ["term_start_date", "term_end_date"])
+ if from_date and to_date:
+ attendance = dict(frappe.db.sql('''select status, count(student) as no_of_days
+ from `tabStudent Attendance` where student = %s
+ and date between %s and %s group by status''',
+ (student, from_date, to_date)))
+ if "Absent" not in attendance.keys():
+ attendance["Absent"] = 0
+ if "Present" not in attendance.keys():
+ attendance["Present"] = 0
+ return attendance
+ else:
+ frappe.throw("Provide the academic year and set the starting and ending date.")
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.js b/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.js
new file mode 100644
index 00000000000..10be092bb92
--- /dev/null
+++ b/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.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: Student Report Generation Tool", function (assert) {
+ let done = assert.async();
+
+ // number of asserts
+ assert.expect(1);
+
+ frappe.run_serially([
+ // insert a new Student Report Generation Tool
+ () => frappe.tests.make('Student Report Generation Tool', [
+ // values to be set
+ {key: 'value'}
+ ]),
+ () => {
+ assert.equal(cur_frm.doc.key, 'value');
+ },
+ () => done()
+ ]);
+
+});
diff --git a/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.py b/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.py
new file mode 100644
index 00000000000..417816642ec
--- /dev/null
+++ b/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestStudentReportGenerationTool(unittest.TestCase):
+ pass
diff --git a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py
index a50ad7b91eb..ce581486ec3 100644
--- a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py
+++ b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py
@@ -60,7 +60,7 @@ def execute(filters=None):
return columns, data, None, chart
-def get_formatted_result(args, get_assessment_criteria=False, get_course=False):
+def get_formatted_result(args, get_assessment_criteria=False, get_course=False, get_all_assessment_groups=False):
cond, cond1, cond2, cond3, cond4 = " ", " ", " ", " ", " "
args_list = [args.academic_year]
@@ -77,15 +77,9 @@ def get_formatted_result(args, get_assessment_criteria=False, get_course=False):
args_list.append(args.student_group)
create_total_dict = False
- group_type = frappe.get_value("Assessment Group", args.assessment_group, "is_group")
- if group_type:
- from frappe.desk.treeview import get_children
- assessment_groups = [d.get("value") for d in get_children("Assessment Group",
- args.assessment_group) if d.get("value") and not d.get("expandable")]
- cond3 = " and ar.assessment_group in (%s)"%(', '.join(['%s']*len(assessment_groups)))
- else:
- assessment_groups = [args.assessment_group]
- cond3 = " and ar.assessment_group=%s"
+
+ assessment_groups = get_child_assessment_groups(args.assessment_group)
+ cond3 = " and ar.assessment_group in (%s)"%(', '.join(['%s']*len(assessment_groups)))
args_list += assessment_groups
if args.students:
@@ -156,6 +150,9 @@ def get_formatted_result(args, get_assessment_criteria=False, get_course=False):
# create the total of all the assessment groups criteria-wise
elif create_total_dict:
+ if get_all_assessment_groups:
+ formatted_assessment_result[result.student][result.course][result.assessment_group]\
+ [result.assessment_criteria] = assessment_criteria_details
if not formatted_assessment_result[result.student][result.course][args.assessment_group]:
formatted_assessment_result[result.student][result.course][args.assessment_group] = defaultdict(dict)
formatted_assessment_result[result.student][result.course][args.assessment_group]\
@@ -238,3 +235,15 @@ def get_chart_data(grades, criteria_list, kounter):
},
"type": 'bar',
}
+
+
+def get_child_assessment_groups(assessment_group):
+ assessment_groups = []
+ group_type = frappe.get_value("Assessment Group", assessment_group, "is_group")
+ if group_type:
+ from frappe.desk.treeview import get_children
+ assessment_groups = [d.get("value") for d in get_children("Assessment Group",
+ assessment_group) if d.get("value") and not d.get("expandable")]
+ else:
+ assessment_groups = [assessment_group]
+ return assessment_groups
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 328a7e45823..fca413482b9 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -510,3 +510,7 @@ erpnext.patches.v10_0.update_status_for_multiple_source_in_po
erpnext.patches.v10_0.set_auto_created_serial_no_in_stock_entry
erpnext.patches.v10_0.update_territory_and_customer_group
erpnext.patches.v10_0.update_warehouse_address_details
+erpnext.patches.v10_0.update_reserved_qty_for_purchase_order
+erpnext.patches.v10_0.update_hub_connector_domain
+erpnext.patches.v10_0.set_student_party_type
+erpnext.patches.v10_0.update_project_in_sle
diff --git a/erpnext/patches/v10_0/set_student_party_type.py b/erpnext/patches/v10_0/set_student_party_type.py
new file mode 100644
index 00000000000..6ac1451623b
--- /dev/null
+++ b/erpnext/patches/v10_0/set_student_party_type.py
@@ -0,0 +1,7 @@
+import frappe
+
+def execute():
+ if not frappe.db.exists("Party Type", "Student"):
+ party = frappe.new_doc("Party Type")
+ party.party_type = "Student"
+ party.save()
diff --git a/erpnext/patches/v10_0/update_hub_connector_domain.py b/erpnext/patches/v10_0/update_hub_connector_domain.py
new file mode 100644
index 00000000000..808ae77129f
--- /dev/null
+++ b/erpnext/patches/v10_0/update_hub_connector_domain.py
@@ -0,0 +1,9 @@
+import frappe
+
+def execute():
+ if frappe.db.table_exists("Data Migration Connector"):
+ frappe.db.sql("""
+ UPDATE `tabData Migration Connector`
+ SET hostname = 'https://hubmarket.org'
+ WHERE connector_name = 'Hub Connector'
+ """)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_project_in_sle.py b/erpnext/patches/v10_0/update_project_in_sle.py
new file mode 100644
index 00000000000..08c64f18d80
--- /dev/null
+++ b/erpnext/patches/v10_0/update_project_in_sle.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ for doctype in ['Sales Invoice', 'Delivery Note', 'Stock Entry']:
+ frappe.db.sql(""" update
+ `tabStock Ledger Entry` sle, `tab{0}` parent_doc
+ set
+ sle.project = parent_doc.project
+ where
+ sle.voucher_no = parent_doc.name and sle.voucher_type = %s and sle.project is null
+ and parent_doc.project is not null and parent_doc.project != ''""".format(doctype), doctype)
diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json
index 7b4d7188e28..8b41adc3ce4 100644
--- a/erpnext/projects/doctype/project/project.json
+++ b/erpnext/projects/doctype/project/project.json
@@ -1119,6 +1119,36 @@
"set_only_once": 0,
"unique": 0
},
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "total_consumed_material_cost",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Total Consumed Material Cost (via Stock Entry)",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -1626,7 +1656,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 4,
- "modified": "2018-01-29 11:48:21.156697",
+ "modified": "2018-03-22 11:44:38.723507",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project",
diff --git a/erpnext/setup/doctype/naming_series/naming_series.py b/erpnext/setup/doctype/naming_series/naming_series.py
index 6455be0de7b..2d2a18b71e8 100644
--- a/erpnext/setup/doctype/naming_series/naming_series.py
+++ b/erpnext/setup/doctype/naming_series/naming_series.py
@@ -20,7 +20,7 @@ class NamingSeries(Document):
+ frappe.db.sql_list("""select dt from `tabCustom Field`
where fieldname='naming_series'""")))
- doctypes = list(set(get_doctypes_with_read()) | set(doctypes))
+ doctypes = list(set(get_doctypes_with_read()).intersection(set(doctypes)))
prefixes = ""
for d in doctypes:
options = ""
@@ -47,6 +47,7 @@ class NamingSeries(Document):
def update_series(self, arg=None):
"""update series list"""
+ self.validate_series_set()
self.check_duplicate()
series_list = self.set_options.split("\n")
@@ -60,6 +61,10 @@ class NamingSeries(Document):
return self.get_transactions()
+ def validate_series_set(self):
+ if self.select_doc_for_series and not self.set_options:
+ frappe.throw(_("Please set the series to be used."))
+
def set_series_for(self, doctype, ol):
options = self.scrub_options_list(ol)
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index 2aa4d5ef68f..045dca04ec7 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -217,6 +217,7 @@ def install(country=None):
{'doctype': "Party Type", "party_type": "Employee"},
{'doctype': "Party Type", "party_type": "Member"},
{'doctype': "Party Type", "party_type": "Shareholder"},
+ {'doctype': "Party Type", "party_type": "Student"},
{'doctype': "Opportunity Type", "name": "Hub"},
{'doctype': "Opportunity Type", "name": _("Sales")},
diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js
index 2748436fd84..dff65afca3d 100644
--- a/erpnext/stock/dashboard/item_dashboard.js
+++ b/erpnext/stock/dashboard/item_dashboard.js
@@ -18,12 +18,12 @@ erpnext.stock.ItemDashboard = Class.extend({
// move
this.content.on('click', '.btn-move', function() {
- erpnext.stock.move_item($(this).attr('data-item'), $(this).attr('data-warehouse'),
+ erpnext.stock.move_item(unescape($(this).attr('data-item')), $(this).attr('data-warehouse'),
null, $(this).attr('data-actual_qty'), null, function() { me.refresh(); });
});
this.content.on('click', '.btn-add', function() {
- erpnext.stock.move_item($(this).attr('data-item'), null, $(this).attr('data-warehouse'),
+ erpnext.stock.move_item(unescape($(this).attr('data-item')), null, $(this).attr('data-warehouse'),
$(this).attr('data-actual_qty'), $(this).attr('data-rate'),
function() { me.refresh(); });
});
diff --git a/erpnext/stock/dashboard/item_dashboard_list.html b/erpnext/stock/dashboard/item_dashboard_list.html
index e0b34318395..5a3fa2ed485 100644
--- a/erpnext/stock/dashboard/item_dashboard_list.html
+++ b/erpnext/stock/dashboard/item_dashboard_list.html
@@ -45,12 +45,12 @@
{{ __("Move") }}
+ data-item="{{ escape(d.item_code) }}">{{ __("Move") }}
{% endif %}
{{ __("Add") }}
{% endif %}
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 5f16d8ba2da..8886f330b45 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -309,7 +309,8 @@ class DeliveryNote(SellingController):
for dn in set(updated_delivery_notes):
dn_doc = self if (dn == self.name) else frappe.get_doc("Delivery Note", dn)
- dn_doc.update_billing_percentage(update_modified=update_modified)
+ if dn_doc.net_total > 0:
+ dn_doc.update_billing_percentage(update_modified=update_modified)
self.load_from_db()
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 9da35aae05b..4f9cefe5d17 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -77,6 +77,7 @@ class StockEntry(StockController):
if self.purchase_order and self.purpose == "Subcontract":
self.update_purchase_order_supplied_items()
self.make_gl_entries()
+ self.update_cost_in_project()
def on_cancel(self):
self.update_stock_ledger()
@@ -100,6 +101,18 @@ class StockEntry(StockController):
item.transfer_qty = flt(flt(item.qty) * flt(item.conversion_factor),
self.precision("transfer_qty", item))
+ def update_cost_in_project(self):
+ if self.project:
+ amount = frappe.db.sql(""" select ifnull(sum(sed.amount), 0)
+ from
+ `tabStock Entry` se, `tabStock Entry Detail` sed
+ where
+ se.docstatus = 1 and se.project = %s and sed.parent = se.name
+ and (sed.t_warehouse is null or sed.t_warehouse = '')""", self.project, as_list=1)
+
+ if amount:
+ frappe.db.set_value('Project', self.project, 'total_consumed_material_cost', amount[0][0])
+
def validate_item(self):
stock_items = self.get_stock_items()
serialized_items = self.get_serialized_items()
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.js b/erpnext/stock/report/stock_ledger/stock_ledger.js
index e95f5cab57c..d4f5ab5414f 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.js
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.js
@@ -59,6 +59,12 @@ frappe.query_reports["Stock Ledger"] = {
"fieldname":"voucher_no",
"label": __("Voucher #"),
"fieldtype": "Data"
+ },
+ {
+ "fieldname":"project",
+ "label": __("Project"),
+ "fieldtype": "Link",
+ "options": "Project"
}
]
}
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index e436132ec87..305702e755b 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -24,7 +24,7 @@ def execute(filters=None):
item_detail.stock_uom, sle.actual_qty, sle.qty_after_transaction,
(sle.incoming_rate if sle.actual_qty > 0 else 0.0),
sle.valuation_rate, sle.stock_value, sle.voucher_type, sle.voucher_no,
- sle.batch_no, sle.serial_no, sle.company])
+ sle.batch_no, sle.serial_no, sle.project, sle.company])
return columns, data
@@ -45,6 +45,7 @@ def get_columns():
_("Voucher #") + ":Dynamic Link/" + _("Voucher Type") + ":100",
_("Batch") + ":Link/Batch:100",
_("Serial #") + ":Link/Serial No:100",
+ _("Project") + ":Link/Project:100",
{"label": _("Company"), "fieldtype": "Link", "width": 110,
"options": "company", "fieldname": "company"}
]
@@ -54,7 +55,7 @@ def get_columns():
def get_stock_ledger_entries(filters):
return frappe.db.sql("""select concat_ws(" ", posting_date, posting_time) as date,
item_code, warehouse, actual_qty, qty_after_transaction, incoming_rate, valuation_rate,
- stock_value, voucher_type, voucher_no, batch_no, serial_no, company
+ stock_value, voucher_type, voucher_no, batch_no, serial_no, company, project
from `tabStock Ledger Entry` sle
where company = %(company)s and
posting_date between %(from_date)s and %(to_date)s
@@ -96,6 +97,8 @@ def get_sle_conditions(filters):
conditions.append("voucher_no=%(voucher_no)s")
if filters.get("batch_no"):
conditions.append("batch_no=%(batch_no)s")
+ if filters.get("project"):
+ conditions.append("project=%(project)s")
return "and {}".format(" and ".join(conditions)) if conditions else ""