diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 1a55d847ba7..dc547e3767a 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -305,6 +305,23 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte } this.frm.refresh_fields(); + }, + + company_address: function() { + var me = this; + if(this.frm.doc.company_address) { + frappe.call({ + method: "frappe.contacts.doctype.address.address.get_address_display", + args: {"address_dict": this.frm.doc.company_address }, + callback: function(r) { + if(r.message) { + me.frm.set_value("company_address_display", r.message) + } + } + }) + } else { + this.frm.set_value("company_address_display", ""); + } } }); diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index a2e9ddf51a4..4c05b94af4a 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -190,7 +190,7 @@ "no_copy": 0, "permlevel": 0, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 1, "remember_last_selected_value": 0, @@ -200,37 +200,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "due_date", - "fieldtype": "Date", - "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": "Payment Due Date", - "length": 0, - "no_copy": 1, - "oldfieldname": "due_date", - "oldfieldtype": "Date", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -253,7 +222,7 @@ "oldfieldtype": "Link", "options": "Project", "permlevel": 0, - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -314,7 +283,7 @@ "no_copy": 0, "permlevel": 0, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 1, "remember_last_selected_value": 0, @@ -345,7 +314,7 @@ "options": "POS Profile", "permlevel": 0, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -510,6 +479,37 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "due_date", + "fieldtype": "Date", + "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": "Payment Due Date", + "length": 0, + "no_copy": 1, + "oldfieldname": "due_date", + "oldfieldtype": "Date", + "permlevel": 0, + "print_hide": 1, + "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, @@ -844,6 +844,37 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "territory", + "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": "Territory", + "length": 0, + "no_copy": 0, + "options": "Territory", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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, @@ -949,13 +980,13 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Company Address", + "label": "Company Address Name", "length": 0, "no_copy": 0, "options": "Address", "permlevel": 0, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -971,24 +1002,23 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "territory", - "fieldtype": "Link", - "hidden": 0, + "fieldname": "company_address_display", + "fieldtype": "Small Text", + "hidden": 1, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Territory", + "label": "Company Address", "length": 0, "no_copy": 0, - "options": "Territory", "permlevel": 0, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, - "read_only": 0, + "read_only": 1, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, @@ -1479,7 +1509,7 @@ "options": "Sales Invoice Timesheet", "permlevel": 0, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -1882,6 +1912,36 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "columns": 0, + "fieldname": "sec_tax_breakup", + "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": "Item-wise Tax Breakup", + "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, @@ -1889,7 +1949,7 @@ "collapsible": 0, "columns": 0, "fieldname": "other_charges_calculation", - "fieldtype": "HTML", + "fieldtype": "Text", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -1899,12 +1959,12 @@ "in_standard_filter": 0, "label": "Taxes and Charges Calculation", "length": 0, - "no_copy": 0, + "no_copy": 1, "oldfieldtype": "HTML", "permlevel": 0, "print_hide": 1, "print_hide_if_no_value": 0, - "read_only": 0, + "read_only": 1, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, @@ -2984,7 +3044,7 @@ "options": "Account", "permlevel": 0, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -4450,7 +4510,7 @@ "options": "Print Format", "permlevel": 0, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -4511,7 +4571,7 @@ "length": 0, "no_copy": 1, "permlevel": 0, - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -4542,7 +4602,7 @@ "length": 0, "no_copy": 1, "permlevel": 0, - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -4627,7 +4687,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-06-29 10:47:49.522969", + "modified": "2017-07-04 17:11:09.477003", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 2e044cc9812..071e72b4fb6 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1105,6 +1105,22 @@ class TestSalesInvoice(unittest.TestCase): for i, k in enumerate(expected_values["keys"]): self.assertEquals(d.get(k), expected_values[d.item_code][i]) + def test_item_wise_tax_breakup(self): + si = create_sales_invoice(qty=100, rate=50, do_not_save=True) + si.append("taxes", { + "charge_type": "On Net Total", + "account_head": "_Test Account Service Tax - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Service Tax", + "rate": 10 + }) + si.insert() + + tax_breakup_html = '''\n
\n\t\n\t\t\n\n\n\t\t\n\t
Item NameTaxable Amount_Test Account Service Tax - _TC
_Test Item5000.0(10.0%) \u20b9 500.00
\n
''' + + self.assertEqual(si.other_charges_calculation, tax_breakup_html) + + def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") args = frappe._dict(args) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 50f6b61c32b..b0fe39547f5 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import json import frappe, erpnext from frappe import _, scrub -from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction +from frappe.utils import cint, flt, cstr, fmt_money, round_based_on_smallest_currency_fraction from erpnext.controllers.accounts_controller import validate_conversion_rate, \ validate_taxes_and_charges, validate_inclusive_tax @@ -24,6 +24,9 @@ class calculate_taxes_and_totals(object): if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]: self.calculate_total_advance() + + if self.doc.meta.get_field("other_charges_calculation"): + self.set_item_wise_tax_breakup() def _calculate(self): self.calculate_item_values() @@ -504,3 +507,106 @@ class calculate_taxes_and_totals(object): rate_with_margin = flt(item.price_list_rate) + flt(margin_value) return rate_with_margin + + def set_item_wise_tax_breakup(self): + item_tax = {} + tax_accounts = [] + + item_tax, tax_accounts = self.get_item_tax(item_tax, tax_accounts) + + headings = get_table_column_headings(tax_accounts) + + distinct_items = self.get_distinct_items() + + rows = get_table_rows(distinct_items, item_tax, tax_accounts) + + if not rows: + self.doc.other_charges_calculation = "" + else: + self.doc.other_charges_calculation = ''' +
+ + {headings} + {rows} +
+
'''.format(**{ + "headings": "\n".join(headings), + "rows": "\n".join(rows) +}) + + def get_item_tax(self, item_tax, tax_accounts): + company_currency = erpnext.get_company_currency(self.doc.company) + + for tax in self.doc.taxes: + tax_amount_precision = tax.precision("tax_amount") + tax_rate_precision = tax.precision("rate"); + + item_tax_map = self._load_item_tax_rate(tax.item_wise_tax_detail) + for item_code, tax_data in item_tax_map.items(): + if not item_tax.get(item_code): + item_tax[item_code] = {} + + if isinstance(tax_data, list): + tax_rate = "" + if tax_data[0]: + if tax.charge_type == "Actual": + tax_rate = fmt_money(flt(tax_data[0], tax_amount_precision), + tax_amount_precision, company_currency) + else: + tax_rate = cstr(flt(tax_data[0], tax_rate_precision)) + "%" + + tax_amount = fmt_money(flt(tax_data[1], tax_amount_precision), + tax_amount_precision, company_currency) + + item_tax[item_code][tax.name] = [tax_rate, tax_amount] + else: + item_tax[item_code][tax.name] = [cstr(flt(tax_data, tax_rate_precision)) + "%", ""] + tax_accounts.append([tax.name, tax.account_head]) + + return item_tax, tax_accounts + + + def get_distinct_items(self): + distinct_item_names = [] + distinct_items = [] + for item in self.doc.items: + item_code = item.item_code or item.item_name + if item_code not in distinct_item_names: + distinct_item_names.append(item_code) + distinct_items.append(item) + + return distinct_items + +def get_table_column_headings(tax_accounts): + headings_name = [_("Item Name"), _("Taxable Amount")] + [d[1] for d in tax_accounts] + headings = [] + for head in headings_name: + if head == _("Item Name"): + headings.append('' + (head or "") + "") + else: + headings.append('' + (head or "") + "") + + return headings + +def get_table_rows(distinct_items, item_tax, tax_accounts): + rows = [] + for item in distinct_items: + item_tax_record = item_tax.get(item.item_code or item.item_name) + if not item_tax_record: + continue + + taxes = [] + for head in tax_accounts: + if item_tax_record[head[0]]: + taxes.append("(" + item_tax_record[head[0]][0] + ") " + + item_tax_record[head[0]][1] + "") + else: + taxes.append("") + + rows.append("{item_name}{taxable_amount}{taxes}".format(**{ + "item_name": item.item_name, + "taxable_amount": item.net_amount, + "taxes": "\n".join(taxes) + })) + + return rows \ No newline at end of file diff --git a/erpnext/docs/assets/img/regional/india/address-template-gstin.png b/erpnext/docs/assets/img/regional/india/address-template-gstin.png new file mode 100644 index 00000000000..8740609dd36 Binary files /dev/null and b/erpnext/docs/assets/img/regional/india/address-template-gstin.png differ diff --git a/erpnext/docs/assets/img/regional/india/sample-gst-tax-invoice.png b/erpnext/docs/assets/img/regional/india/sample-gst-tax-invoice.png new file mode 100644 index 00000000000..4f4a9b19ab1 Binary files /dev/null and b/erpnext/docs/assets/img/regional/india/sample-gst-tax-invoice.png differ diff --git a/erpnext/docs/license.html b/erpnext/docs/license.html index 4740c5c1455..1d50b78b305 100644 --- a/erpnext/docs/license.html +++ b/erpnext/docs/license.html @@ -640,8 +640,8 @@ attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.

-
    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
+
    <one line="" to="" give="" the="" program's="" name="" and="" a="" brief="" idea="" of="" what="" it="" does.="">
+    Copyright (C) <year>  <name of="" author="">
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff --git a/erpnext/docs/user/manual/en/regional/india/gst-setup.md b/erpnext/docs/user/manual/en/regional/india/gst-setup.md
index 48e5066611c..0ba8284bcbe 100644
--- a/erpnext/docs/user/manual/en/regional/india/gst-setup.md
+++ b/erpnext/docs/user/manual/en/regional/india/gst-setup.md
@@ -14,6 +14,13 @@ Go to the Company master and add the GSTIN to your default address.
 
 GST in Company
 
+**Include GSTIN number in the Address Template**
+
+Open Address Template record for India, and add GSTIN number there if not exists.
+
+GST in Company
+
+
 ### 2. Setting up HSN Codes
 
 According to the GST Law, your itemised invoices must contain the HSN Code related to that Item. ERPNext comes pre-installed with all 12,000+ HSN Codes so that you can easily select the relevant HSN Code in your Item
@@ -54,6 +61,12 @@ For **Sales Invoice**,
 
 GST Invoice
 
+### 6. Print GST Tax Invoice
+
+To print Tax Invoice as per GSTN guidelines, please select **GST Tax Invoice** print format. This print format includes company address, GSTIN numbers, HSN/SAC Code and item-wise tax breakup.
+
+Sample GST Tax Invoice
+
 ### Reports
 
 ERPNext comes with most of your reports you need to prepare your GST Returns. Go to Accounts > GST India head for the list.
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 30a24f87197..e7cf5f2f1b0 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -410,4 +410,5 @@ erpnext.patches.v8_0.save_system_settings
 erpnext.patches.v8_1.delete_deprecated_reports
 erpnext.patches.v8_1.setup_gst_india #2017-06-27
 execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
-erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account
\ No newline at end of file
+erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account
+erpnext.patches.v8_1.gst_fixes
diff --git a/erpnext/patches/v8_1/gst_fixes.py b/erpnext/patches/v8_1/gst_fixes.py
new file mode 100644
index 00000000000..5454f0ff18d
--- /dev/null
+++ b/erpnext/patches/v8_1/gst_fixes.py
@@ -0,0 +1,27 @@
+import frappe
+
+def execute():
+	frappe.db.sql("""update `tabCustom Field` set label = 'HSN/SAC Code'
+		where fieldname='gst_hsn_code' and label='GST HSN Code'
+	""")
+
+	frappe.db.sql("""update `tabCustom Field` set print_hide = 1
+		where fieldname in ('customer_gstin', 'supplier_gstin', 'company_gstin')
+	""")
+
+	frappe.db.sql("""update `tabCustom Field` set insert_after = 'address_display'
+		where fieldname in ('customer_gstin', 'supplier_gstin')
+	""")
+
+	frappe.db.sql("""update `tabCustom Field` set insert_after = 'company_address_display'
+		where fieldname = 'company_gstin'
+	""")
+
+	frappe.db.sql("""update `tabCustom Field` set insert_after = 'description'
+		where fieldname='gst_hsn_code' and dt in ('Sales Invoice Item', 'Purchase Invoice Item')
+	""")
+
+	# reload gst print format for Indian users
+	company = frappe.get_all('Company', filters = {'country': 'India'})
+	if company:
+		frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
\ No newline at end of file
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index c4d8155e799..642ff1b3e90 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -634,5 +634,91 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
 		}
 		
 		this.calculate_outstanding_amount(false)
+	},
+	
+	show_item_wise_taxes: function() {
+		if(this.frm.fields_dict.other_charges_calculation) {
+			this.frm.toggle_display("other_charges_calculation", this.frm.doc.other_charges_calculation);
+		}
+	},
+	
+	set_item_wise_tax_breakup: function() {
+		if(this.frm.fields_dict.other_charges_calculation) {
+			var html = this.get_item_wise_taxes_html();
+			// console.log(html);
+			this.frm.set_value("other_charges_calculation", html);
+			this.show_item_wise_taxes();
+		}
+	},
+		
+	get_item_wise_taxes_html: function() {
+		var item_tax = {};
+		var tax_accounts = [];
+		var company_currency = this.get_company_currency();
+
+		$.each(this.frm.doc["taxes"] || [], function(i, tax) {
+			var tax_amount_precision = precision("tax_amount", tax);
+			var tax_rate_precision = precision("rate", tax);
+			$.each(JSON.parse(tax.item_wise_tax_detail || '{}'),
+				function(item_code, tax_data) {
+					if(!item_tax[item_code]) item_tax[item_code] = {};
+					if($.isArray(tax_data)) {
+						var tax_rate = "";
+						if(tax_data[0] != null) {
+							tax_rate = (tax.charge_type === "Actual") ?
+								format_currency(flt(tax_data[0], tax_amount_precision),
+									company_currency, tax_amount_precision) :
+								(flt(tax_data[0], tax_rate_precision) + "%");
+						}
+						var tax_amount = format_currency(flt(tax_data[1], tax_amount_precision),
+							company_currency, tax_amount_precision);
+
+						item_tax[item_code][tax.name] = [tax_rate, tax_amount];
+					} else {
+						item_tax[item_code][tax.name] = [flt(tax_data, tax_rate_precision) + "%", ""];
+					}
+				});
+			tax_accounts.push([tax.name, tax.account_head]);
+		});
+		
+		var headings = $.map([__("Item Name"), __("Taxable Amount")].concat($.map(tax_accounts, 
+			function(head) { return head[1]; })), function(head) {
+				if(head==__("Item Name")) {
+					return '' + (head || "") + "";
+				} else {
+					return '' + (head || "") + "";
+				}	
+			}
+		).join("\n");
+
+		var distinct_item_names = [];
+		var distinct_items = [];
+		$.each(this.frm.doc["items"] || [], function(i, item) {
+			if(distinct_item_names.indexOf(item.item_code || item.item_name)===-1) {
+				distinct_item_names.push(item.item_code || item.item_name);
+				distinct_items.push(item);
+			}
+		});
+
+		var rows = $.map(distinct_items, function(item) {
+			var item_tax_record = item_tax[item.item_code || item.item_name];
+			if(!item_tax_record) { return null; }
+			return repl("%(item_name)s%(taxable_amount)s%(taxes)s", {
+				item_name: item.item_name,
+				taxable_amount: item.net_amount,
+				taxes: $.map(tax_accounts, function(head) {
+					return item_tax_record[head[0]] ?
+						"(" + item_tax_record[head[0]][0] + ") " + item_tax_record[head[0]][1] + "" :
+						"";
+				}).join("\n")
+			});
+		}).join("\n");
+
+		if(!rows) return "";
+		return '
\ + \ + ' + headings + ' \ + ' + rows + ' \ +
'; } }) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index cd8e7bd93be..c4f9e8a8add 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -374,6 +374,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ validate: function() { this.calculate_taxes_and_totals(false); + this.set_item_wise_tax_breakup(); }, company: function() { @@ -936,69 +937,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }); }, - get_item_wise_taxes_html: function() { - var item_tax = {}; - var tax_accounts = []; - var company_currency = this.get_company_currency(); - - $.each(this.frm.doc["taxes"] || [], function(i, tax) { - var tax_amount_precision = precision("tax_amount", tax); - var tax_rate_precision = precision("rate", tax); - $.each(JSON.parse(tax.item_wise_tax_detail || '{}'), - function(item_code, tax_data) { - if(!item_tax[item_code]) item_tax[item_code] = {}; - if($.isArray(tax_data)) { - var tax_rate = ""; - if(tax_data[0] != null) { - tax_rate = (tax.charge_type === "Actual") ? - format_currency(flt(tax_data[0], tax_amount_precision), company_currency, tax_amount_precision) : - (flt(tax_data[0], tax_rate_precision) + "%"); - } - var tax_amount = format_currency(flt(tax_data[1], tax_amount_precision), company_currency, - tax_amount_precision); - - item_tax[item_code][tax.name] = [tax_rate, tax_amount]; - } else { - item_tax[item_code][tax.name] = [flt(tax_data, tax_rate_precision) + "%", ""]; - } - }); - tax_accounts.push([tax.name, tax.account_head]); - }); - - var headings = $.map([__("Item Name")].concat($.map(tax_accounts, function(head) { return head[1]; })), - function(head) { return '' + (head || "") + "" }).join("\n"); - - var distinct_item_names = []; - var distinct_items = []; - $.each(this.frm.doc["items"] || [], function(i, item) { - if(distinct_item_names.indexOf(item.item_code || item.item_name)===-1) { - distinct_item_names.push(item.item_code || item.item_name); - distinct_items.push(item); - } - }); - - var rows = $.map(distinct_items, function(item) { - var item_tax_record = item_tax[item.item_code || item.item_name]; - if(!item_tax_record) { return null; } - return repl("%(item_name)s%(taxes)s", { - item_name: item.item_name, - taxes: $.map(tax_accounts, function(head) { - return item_tax_record[head[0]] ? - "(" + item_tax_record[head[0]][0] + ") " + item_tax_record[head[0]][1] + "" : - ""; - }).join("\n") - }); - }).join("\n"); - - if(!rows) return ""; - return '

' - + __("Show tax break-up") + '

\ -
\ - ' + headings + ' \ - ' + rows + ' \ -
'; - }, - validate_company_and_party: function() { var me = this; var valid = true; @@ -1046,18 +984,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, - show_item_wise_taxes: function() { - if(this.frm.fields_dict.other_charges_calculation) { - var html = this.get_item_wise_taxes_html(); - if (html) { - this.frm.toggle_display("other_charges_calculation", true); - $(this.frm.fields_dict.other_charges_calculation.wrapper).html(html); - } else { - this.frm.toggle_display("other_charges_calculation", false); - } - } - }, - is_recurring: function() { // set default values for recurring documents if(this.frm.doc.is_recurring && this.frm.doc.__islocal) { diff --git a/erpnext/regional/india/address_template.html b/erpnext/regional/india/address_template.html index 706c7a4e207..46879ad6b88 100644 --- a/erpnext/regional/india/address_template.html +++ b/erpnext/regional/india/address_template.html @@ -2,7 +2,7 @@ {% if state %}{{ state }}
{% endif -%} {% if pincode %}{{ pincode }}
{% endif -%} {{ country }}
-{% if gstin %}GSTIN: {{ gstin }}
{% endif -%} {% if phone %}Phone: {{ phone }}
{% endif -%} {% if fax %}Fax: {{ fax }}
{% endif -%} -{% if email_id %}Email: {{ email_id }}
{% endif -%} \ No newline at end of file +{% if email_id %}Email: {{ email_id }}
{% endif -%} +{% if gstin %}GSTIN: {{ gstin }}
{% endif -%} \ No newline at end of file diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index a9f3a30d105..46cfdb805ba 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -14,6 +14,7 @@ def setup(company=None, patch=True): add_custom_roles_for_reports() add_hsn_codes() update_address_template() + add_print_formats() if not patch: make_fixtures() @@ -69,6 +70,9 @@ def add_permissions(): add_permission(doctype, 'Accounts Manager', 0) add_permission(doctype, 'All', 0) +def add_print_formats(): + frappe.reload_doc("regional", "print_format", "gst_tax_invoice") + def make_custom_fields(): custom_fields = { 'Address': [ @@ -80,39 +84,39 @@ def make_custom_fields(): 'Purchase Invoice': [ dict(fieldname='supplier_gstin', label='Supplier GSTIN', fieldtype='Data', insert_after='supplier_address', - options='supplier_address.gstin'), + options='supplier_address.gstin', print_hide=1), dict(fieldname='company_gstin', label='Company GSTIN', fieldtype='Data', insert_after='shipping_address', - options='shipping_address.gstin'), + options='shipping_address.gstin', print_hide=1), ], 'Sales Invoice': [ dict(fieldname='customer_gstin', label='Customer GSTIN', fieldtype='Data', insert_after='shipping_address', - options='shipping_address_name.gstin'), + options='shipping_address_name.gstin', print_hide=1), dict(fieldname='company_gstin', label='Company GSTIN', fieldtype='Data', insert_after='company_address', - options='company_address.gstin'), + options='company_address.gstin', print_hide=1), ], 'Item': [ - dict(fieldname='gst_hsn_code', label='GST HSN Code', + dict(fieldname='gst_hsn_code', label='HSN/SAC Code', fieldtype='Link', options='GST HSN Code', insert_after='item_group'), ], 'Sales Invoice Item': [ - dict(fieldname='gst_hsn_code', label='GST HSN Code', + dict(fieldname='gst_hsn_code', label='HSN/SAC Code', fieldtype='Data', options='item_code.gst_hsn_code', - insert_after='income_account'), + insert_after='description'), ], 'Purchase Invoice Item': [ - dict(fieldname='gst_hsn_code', label='GST HSN Code', + dict(fieldname='gst_hsn_code', label='HSN/SAC Code', fieldtype='Data', options='item_code.gst_hsn_code', - insert_after='expense_account'), + insert_after='description'), ] } for doctype, fields in custom_fields.items(): for df in fields: create_custom_field(doctype, df) - + def make_fixtures(): docs = [ {'doctype': 'Salary Component', 'salary_component': 'Professional Tax', 'description': 'Professional Tax', 'type': 'Deduction'}, diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 4d37498114f..c4acafc944f 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -16,7 +16,7 @@ def validate_gstin_for_india(doc, method): if doc.state in states: doc.gst_state = doc.state - if doc.gst_state: - state_number = state_numbers[doc.gst_state] - if state_number != doc.gstin[:2]: - frappe.throw(_("First 2 digits of GSTIN should match with State number {0}").format(state_number)) + if doc.gst_state: + state_number = state_numbers[doc.gst_state] + if state_number != doc.gstin[:2]: + frappe.throw(_("First 2 digits of GSTIN should match with State number {0}").format(state_number)) diff --git a/erpnext/regional/print_format/__init__.py b/erpnext/regional/print_format/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/regional/print_format/gst_tax_invoice/__init__.py b/erpnext/regional/print_format/gst_tax_invoice/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/regional/print_format/gst_tax_invoice/gst_tax_invoice.json b/erpnext/regional/print_format/gst_tax_invoice/gst_tax_invoice.json new file mode 100644 index 00000000000..b16aadaa8e8 --- /dev/null +++ b/erpnext/regional/print_format/gst_tax_invoice/gst_tax_invoice.json @@ -0,0 +1,22 @@ +{ + "align_labels_left": 0, + "creation": "2017-07-04 16:26:21.120187", + "custom_format": 0, + "disabled": 0, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype": "Print Format", + "font": "Default", + "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"
\\t\\t\\t\\t

Sales Invoice
{{ doc.name }}\\t\\t\\t\\t

\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"company\", \"label\": \"Company\"}, {\"print_hide\": 0, \"fieldname\": \"company_address_display\", \"label\": \"Company Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"posting_date\", \"label\": \"Date\"}, {\"print_hide\": 0, \"fieldname\": \"due_date\", \"label\": \"Payment Due Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"options\": \"
\", \"fieldname\": \"_custom_html\", \"fieldtype\": \"HTML\", \"label\": \"Custom HTML\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"customer_name\", \"label\": \"Customer Name\"}, {\"print_hide\": 0, \"fieldname\": \"address_display\", \"label\": \"Address\"}, {\"print_hide\": 0, \"fieldname\": \"contact_display\", \"label\": \"Contact\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"shipping_address\", \"label\": \"Shipping Address\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"200px\"}, {\"print_hide\": 0, \"fieldname\": \"gst_hsn_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"items\", \"label\": \"Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"label\": \"Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}], \"print_hide\": 0, \"fieldname\": \"taxes\", \"label\": \"Sales Taxes and Charges\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"grand_total\", \"label\": \"Grand Total\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\", \"label\": \"Rounded Total\"}, {\"print_hide\": 0, \"fieldname\": \"in_words\", \"label\": \"In Words\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"other_charges_calculation\", \"align\": \"left\", \"label\": \"Item-wise Tax Breakup\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Terms\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"terms\", \"label\": \"Terms and Conditions Details\"}]", + "idx": 0, + "line_breaks": 0, + "modified": "2017-07-04 17:13:44.911156", + "modified_by": "Administrator", + "module": "Regional", + "name": "GST Tax Invoice", + "owner": "Administrator", + "print_format_builder": 1, + "print_format_type": "Server", + "show_section_headings": 0, + "standard": "Yes" +} \ No newline at end of file