Fixed merge conflict
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 416aaf4..a2dc172 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
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 2692f3c..fd48faa 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -88,6 +88,9 @@
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 0479cd8..e047b6d 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -132,7 +132,7 @@
"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 15b8cfc..cfcc341 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 0377ff9..33af313 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": "<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{% if doc.docstatus == 0 %}\n\t\t<b>{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }}</b><br>\n\t{% else %}\n\t\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n\t{% endif %}\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{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\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<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\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\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\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>",
+ "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{% if doc.docstatus == 0 %}\n\t\t<b>{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }}</b><br>\n\t{% else %}\n\t\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n\t{% endif %}\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{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\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<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\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\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\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>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- if doc.change_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- endif -%}\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": "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 bef6a02..c3450d6 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": "<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.docstatus == 0 %}\n\t\t{{ doc.status + \" \" + (doc.select_print_heading or _(\"Invoice\")) }}<br>\n\t{% else %}\n\t\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n\t{% endif %}\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<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\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=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" 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 }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"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{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\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<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\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\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t{%- if doc.pos_total_qty -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Total Qty\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"pos_total_qty\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
+ "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.docstatus == 0 %}\n\t\t{{ doc.status + \" \" + (doc.select_print_heading or _(\"Invoice\")) }}<br>\n\t{% else %}\n\t\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n\t{% endif %}\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<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\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=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" 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 }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"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{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\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<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\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\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\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>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t\t{%- if doc.pos_total_qty -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Total Qty\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"pos_total_qty\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
"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 0c24feb..63ef832 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.js
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js
@@ -14,7 +14,13 @@
"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 @@
"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 d96fc99..10f3262 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
@@ -13,6 +13,11 @@
<h2 class="text-center">{%= __(report.report_name) %}</h2>
<h4 class="text-center">{%= filters.customer || filters.supplier %} </h4>
+<h6 class="text-center">
+ {% if (filters.tax_id) { %}
+ {%= __("Tax Id: ")%} {%= filters.tax_id %}
+ {% } %}
+</h6>
<h5 class="text-center">
{%= __(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 82f3507..ec1e9f9 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -14,7 +14,13 @@
"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 @@
"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 845a2c5..08b24fb 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 @@
})
)
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 7f50599..9a2205a 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 %}
{% } %}
</h4>
+
+<h6 class="text-center">
+ {% if (filters.tax_id) { %}
+ {%= __("Tax Id: ")%} {%= filters.tax_id %}
+ {% } %}
+</h6>
+
<h5 class="text-center">
{%= 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 d6a2aec..b7f96c6 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -87,6 +87,12 @@
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"]);
+ });
+ }
}
},
{
@@ -96,6 +102,12 @@
"hidden": 1
},
{
+ "fieldname":"tax_id",
+ "label": __("Tax Id"),
+ "fieldtype": "Data",
+ "hidden": 1
+ },
+ {
"fieldname":"group_by_voucher",
"label": __("Group by Voucher"),
"fieldtype": "Check",
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py
index 73bb4dc..cf599a0 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -43,7 +43,7 @@
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 @@
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 @@
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 757b760..a318751 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -47,6 +47,7 @@
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 @@
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 @@
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 e4e77f3..5a05a25 100644
--- a/erpnext/config/education.py
+++ b/erpnext/config/education.py
@@ -135,6 +135,10 @@
"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 df0fec8..e8e851d 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -285,7 +285,7 @@
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 b40b986..8b0ea3e 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -252,7 +252,7 @@
"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 a830e5b..841c2e8 100644
--- a/erpnext/education/doctype/student/student.py
+++ b/erpnext/education/doctype/student/student.py
@@ -22,14 +22,16 @@
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 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/student_report_generation_tool/__init__.py
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 0000000..72772b7
--- /dev/null
+++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html
@@ -0,0 +1,371 @@
+<style>
+ @media screen {
+ .print-format-gutter {
+ background-color: #ddd;
+ padding: 15px 0px;
+ }
+ .print-format {
+ background-color: white;
+ box-shadow: 0px 0px 9px rgba(0,0,0,0.5);
+ max-width: 8.3in;
+ min-height: 11.69in;
+ padding: 0.75in;
+ margin: auto;
+ }
+
+ .print-format.landscape {
+ max-width: 11.69in;
+ padding: 0.2in;
+ }
+
+ .page-break {
+ padding: 30px 0px;
+ border-bottom: 1px dashed #888;
+ }
+
+ .page-break:first-child {
+ padding-top: 0px;
+ }
+
+ .page-break:last-child {
+ border-bottom: 0px;
+ }
+
+ /* mozilla hack for images in table */
+ body:last-child .print-format td img {
+ width: 100% !important;
+ }
+
+ @media(max-width: 767px) {
+ .print-format {
+ padding: 0.2in;
+ }
+ }
+ }
+
+ @media print {
+ .print-format p {
+ margin-left: 1px;
+ margin-right: 1px;
+ }
+ }
+
+ .data-field {
+ margin-top: 5px;
+ margin-bottom: 5px;
+ }
+
+ .data-field .value {
+ word-wrap: break-word;
+ }
+
+ .important .value {
+ font-size: 120%;
+ font-weight: bold;
+ }
+
+ .important label {
+ line-height: 1.8;
+ margin: 0px;
+ }
+
+ .table {
+ margin: 20px 0px;
+ }
+
+ .square-image {
+ width: 100%;
+ height: 0;
+ padding: 50% 0;
+ background-size: contain;
+ /*background-size: cover;*/
+ background-repeat: no-repeat !important;
+ background-position: center center;
+ border-radius: 4px;
+ }
+
+ .print-item-image {
+ object-fit: contain;
+ }
+
+ .pdf-variables,
+ .pdf-variable,
+ .visible-pdf {
+ display: none !important;
+ }
+
+ .print-format {
+ font-size: 9pt;
+ font-family: "Helvetica Neue", Helvetica, Arial, "Open Sans", sans-serif;
+ -webkit-print-color-adjust:exact;
+ }
+
+ .page-break {
+ page-break-after: always;
+ }
+
+ .print-heading {
+ border-bottom: 1px solid #aaa;
+ margin-bottom: 10px;
+ }
+
+ .print-heading h2 {
+ margin: 0px;
+ }
+ .print-heading h4 {
+ margin-top: 5px;
+ }
+
+ table.no-border, table.no-border td {
+ border: 0px;
+ }
+
+ .print-format label {
+ /* wkhtmltopdf breaks label into multiple lines when it is inline-block */
+ display: block;
+ }
+
+ .print-format img {
+ max-width: 100%;
+ }
+
+ .print-format table td > .primary:first-child {
+ font-weight: bold;
+ }
+
+ .print-format td, .print-format th {
+ vertical-align: top !important;
+ padding: 6px !important;
+ }
+
+ .print-format p {
+ margin: 3px 0px 3px;
+ }
+
+ table td div {
+
+ /* needed to avoid partial cutting of text between page break in wkhtmltopdf */
+ page-break-inside: avoid !important;
+
+ }
+
+ /* hack for webkit specific browser */
+ @media (-webkit-min-device-pixel-ratio:0) {
+ thead, tfoot { display: table-row-group; }
+ }
+
+ [document-status] {
+ margin-bottom: 5mm;
+ }
+
+ .signature-img {
+ background: #fff;
+ border-radius: 3px;
+ margin-top: 5px;
+ max-height: 150px;
+ }
+
+ .print-heading {
+ text-align: right;
+ text-transform: uppercase;
+ color: #666;
+ padding-bottom: 20px;
+ margin-bottom: 20px;
+ border-bottom: 1px solid #d1d8dd;
+ }
+
+ .print-heading h2 {
+ font-size: 24px;
+ }
+
+ .print-format th {
+ background-color: #eee !important;
+ border-bottom: 0px !important;
+ }
+
+ /* modern format: for-test */
+
+ .pbi_avoid {
+ page-break-inside: avoid !important;
+ }
+ .pb_before {
+ page-break-before: always !important;
+ }
+</style>
+
+
+
+<div class="page-break">
+
+ <div id="header-html" class="hidden-pdf">
+
+ {% if letterhead and add_letterhead %}
+ <div class="">{{ letterhead }}</div>
+ {% endif %}
+ <div class="print-heading">
+ <h2>{{ _("Student Report Card") }}<br>
+ <small>{{ doc.student_name }}</small>
+ </h2>
+ </div>
+ </div>
+
+ <div class="row section-break">
+ <div class="col-xs-6 column-break">
+ <div class="row data-field">
+ <div class="col-xs-5">
+ <label>{{ _("Student ID: ") }}</label>
+ </div>
+ <div class="col-xs-7">
+ {{ doc.students[0] }}
+ </div>
+ </div>
+
+ <div class="row data-field">
+ <div class="col-xs-5">
+ <label>{{ _("Student Name: ") }}</label>
+ </div>
+ <div class="col-xs-7">
+ {{ doc.student_name }}
+ </div>
+ </div>
+
+ <div class="row data-field">
+ <div class="col-xs-5">
+ <label>{{ _("Program: ") }}</label>
+ </div>
+ <div class="col-xs-7">
+ {{ doc.program }}
+ </div>
+ </div>
+
+ <div class="row data-field">
+ <div class="col-xs-5">
+ <label>{{ _("Batch: ") }}</label>
+ </div>
+ <div class="col-xs-7">
+ {{ doc.student_batch }}
+ </div>
+ </div>
+ </div>
+
+ <div class="col-xs-6 column-break">
+ <div class="row data-field">
+ <div class="col-xs-5">
+ <label>{{ _("Academic Year: ") }}</label>
+ </div>
+ <div class="col-xs-7">
+ {{ doc.academic_year }}
+ </div>
+ </div>
+
+ {% if doc.academic_term %}
+ <div class="row data-field">
+ <div class="col-xs-5">
+ <label>{{ _("Academic Term: ") }}</label>
+ </div>
+ <div class="col-xs-7">
+ {{ doc.academic_term }}
+ </div>
+ </div>
+ {% endif %}
+
+ <div class="row data-field">
+ <div class="col-xs-5">
+ <label>{{ _("Assessment Group: ") }}</label>
+ </div>
+ <div class="col-xs-7">
+ {{ doc.assessment_group }}
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+{% if doc.show_marks | int %}
+ {% set result_data = 'score' %}
+{% else %}
+ {% set result_data = 'grade' %}
+{% endif %}
+
+
+{% for course in courses %}
+
+<div class="row section-break pbi_avoid">
+ <div class="col-xs-12 column-break">
+
+ <div>
+ <table class="table table-bordered table-condensed">
+ <caption>
+ <div class="row">
+ <div class="col-xs-1">
+ <label>{{ _("Course: ") }}</label>
+ </div>
+ <div class="col-xs-11">
+ {{ course }} ({{ frappe.db.get_value("Course", course, "course_name") }})
+ </div>
+ </div>
+ </caption>
+ <thead>
+ <tr>
+ <th style="width: {{ 650//(assessment_groups|length + 1) }}px">{{ _("Assessment Criteria") }}</th>
+ {% for assessment_group in assessment_groups %}
+ <th> {{ assessment_group }}</th>
+ {% endfor %}
+ </tr>
+ </thead>
+
+ <tbody>
+ {% for criteria in course_criteria[course] %}
+ <tr>
+ <td>{{ criteria }}</td>
+ {% 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)) %}
+ <td>
+ {{ 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 %}
+ </td>
+ {% else %}
+ <td></td>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% endfor %}
+ </tbody>
+
+ </table>
+ </div>
+ </div>
+</div>
+
+{% endfor %}
+
+<br>
+
+<div class="row section-break pbi_avoid">
+ <div class="col-xs-6 column-break">
+ <h4>{{ _("Student Attendance")}}</h4> <br>
+ <div>
+ Present {{ doc.attendance.get("Present") if doc.attendance.get("Present") != None else '0' }} days
+ out of {{ doc.attendance.get("Present") + doc.attendance.get("Absent") }}
+ </div>
+ </div>
+
+ <div class="col-xs-6 column-break">
+ <h4>{{ _("Parents Teacher Meeting Attendance")}}</h4> <br>
+ <div>
+ Present {{ doc.parents_attendance if doc.parents_attendance != None else '0' }}
+ out of {{ doc.parents_meeting if doc.parents_meeting != None else '0' }}
+ </div>
+ </div>
+</div>
+
+{% if doc.assessment_terms %}
+<div class="row section-break pb_before">
+ <div class="col-xs-12">
+ <p> {{ doc.assessment_terms }} </p>
+ </div>
+</div>
+{% endif %}
+</div>
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 0000000..d5103ca
--- /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 0000000..88c59c2
--- /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 0000000..7b2e007
--- /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 0000000..10be092
--- /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 0000000..4178166
--- /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 a50ad7b..ce58148 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 @@
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 @@
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 @@
# 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 @@
},
"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 328a7e4..fca4134 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -510,3 +510,7 @@
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 0000000..6ac1451
--- /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 0000000..808ae77
--- /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 0000000..08c64f1
--- /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 7b4d718..8b41adc 100644
--- a/erpnext/projects/doctype/project/project.json
+++ b/erpnext/projects/doctype/project/project.json
@@ -1125,6 +1125,36 @@
"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,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "cost_center",
"fieldtype": "Link",
"hidden": 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 6455be0..2d2a18b 100644
--- a/erpnext/setup/doctype/naming_series/naming_series.py
+++ b/erpnext/setup/doctype/naming_series/naming_series.py
@@ -20,7 +20,7 @@
+ 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 @@
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 @@
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 2aa4d5e..045dca0 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -217,6 +217,7 @@
{'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 2748436..dff65af 100644
--- a/erpnext/stock/dashboard/item_dashboard.js
+++ b/erpnext/stock/dashboard/item_dashboard.js
@@ -18,12 +18,12 @@
// 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 e0b3431..5a3fa2e 100644
--- a/erpnext/stock/dashboard/item_dashboard_list.html
+++ b/erpnext/stock/dashboard/item_dashboard_list.html
@@ -45,12 +45,12 @@
<button class="btn btn-default btn-xs btn-move"
data-warehouse="{{ d.warehouse }}"
data-actual_qty="{{ d.actual_qty }}"
- data-item="{{ d.item_code }}">{{ __("Move") }}</a>
+ data-item="{{ escape(d.item_code) }}">{{ __("Move") }}</a>
{% endif %}
<button style="margin-left: 7px;" class="btn btn-default btn-xs btn-add"
data-warehouse="{{ d.warehouse }}"
data-actual_qty="{{ d.actual_qty }}"
- data-item="{{ d.item_code }}"
+ data-item="{{ escape(d.item_code) }}"
data-rate="{{ d.valuation_rate }}">{{ __("Add") }}</a>
</div>
{% endif %}
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 5f16d8b..8886f33 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -309,7 +309,8 @@
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 9da35aa..4f9cefe 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -77,6 +77,7 @@
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 @@
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 e95f5ca..d4f5ab5 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.js
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.js
@@ -59,6 +59,12 @@
"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 e436132..305702e 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -24,7 +24,7 @@
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 @@
_("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_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 @@
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 ""