GST tax invoice print format and more (#9616)
* GST Tax Invoice print format and more. Fixes #9545 #9566 #9608 * Reload gst print format only for Indian users * Fixes as Codacy
This commit is contained in:
parent
b66fb9a4c0
commit
852cb64e4f
@ -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", "");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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<div class="tax-break-up" style="overflow-x: auto;">\n\t<table class="table table-bordered table-hover">\n\t\t<thead><tr><th class="text-left" style="min-width: 120px;">Item Name</th>\n<th class="text-right" style="min-width: 80px;">Taxable Amount</th>\n<th class="text-right" style="min-width: 80px;">_Test Account Service Tax - _TC</th></tr></thead>\n\t\t<tbody><tr><td>_Test Item</td><td class="text-right">5000.0</td><td class="text-right">(10.0%) \u20b9 500.00</td></tr></tbody>\n\t</table>\n</div>'''
|
||||
|
||||
self.assertEqual(si.other_charges_calculation, tax_breakup_html)
|
||||
|
||||
|
||||
def create_sales_invoice(**args):
|
||||
si = frappe.new_doc("Sales Invoice")
|
||||
args = frappe._dict(args)
|
||||
|
@ -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 = '''
|
||||
<div class="tax-break-up" style="overflow-x: auto;">
|
||||
<table class="table table-bordered table-hover">
|
||||
<thead><tr>{headings}</tr></thead>
|
||||
<tbody>{rows}</tbody>
|
||||
</table>
|
||||
</div>'''.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('<th style="min-width: 120px;" class="text-left">' + (head or "") + "</th>")
|
||||
else:
|
||||
headings.append('<th style="min-width: 80px;" class="text-right">' + (head or "") + "</th>")
|
||||
|
||||
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("<td class='text-right'>(" + item_tax_record[head[0]][0] + ") "
|
||||
+ item_tax_record[head[0]][1] + "</td>")
|
||||
else:
|
||||
taxes.append("<td></td>")
|
||||
|
||||
rows.append("<tr><td>{item_name}</td><td class='text-right'>{taxable_amount}</td>{taxes}</tr>".format(**{
|
||||
"item_name": item.item_name,
|
||||
"taxable_amount": item.net_amount,
|
||||
"taxes": "\n".join(taxes)
|
||||
}))
|
||||
|
||||
return rows
|
Binary file not shown.
After Width: | Height: | Size: 222 KiB |
Binary file not shown.
After Width: | Height: | Size: 356 KiB |
@ -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.</p>
|
||||
|
||||
<pre><code> <one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
<pre><code> <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
|
||||
|
@ -14,6 +14,13 @@ Go to the Company master and add the GSTIN to your default address.
|
||||
|
||||
<img class="screenshot" alt="GST in Company" src="{{docs_base_url}}/assets/img/regional/india/gstin-company.gif">
|
||||
|
||||
**Include GSTIN number in the Address Template**
|
||||
|
||||
Open Address Template record for India, and add GSTIN number there if not exists.
|
||||
|
||||
<img class="screenshot" alt="GST in Company" src="{{docs_base_url}}/assets/img/regional/india/address-template-gstin.png">
|
||||
|
||||
|
||||
### 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**,
|
||||
|
||||
<img class="screenshot" alt="GST Invoice" src="{{docs_base_url}}/assets/img/regional/india/gst-invoice.gif">
|
||||
|
||||
### 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.
|
||||
|
||||
<img class="screenshot" alt="Sample GST Tax Invoice" src="{{docs_base_url}}/assets/img/regional/india/sample-gst-tax-invoice.png">
|
||||
|
||||
### Reports
|
||||
|
||||
ERPNext comes with most of your reports you need to prepare your GST Returns. Go to Accounts > GST India head for the list.
|
||||
|
@ -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
|
||||
erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account
|
||||
erpnext.patches.v8_1.gst_fixes
|
||||
|
27
erpnext/patches/v8_1/gst_fixes.py
Normal file
27
erpnext/patches/v8_1/gst_fixes.py
Normal file
@ -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")
|
@ -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 '<th style="min-width: 100px;" class="text-left">' + (head || "") + "</th>";
|
||||
} else {
|
||||
return '<th style="min-width: 80px;" class="text-right">' + (head || "") + "</th>";
|
||||
}
|
||||
}
|
||||
).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("<tr><td>%(item_name)s</td><td class='text-right'>%(taxable_amount)s</td>%(taxes)s</tr>", {
|
||||
item_name: item.item_name,
|
||||
taxable_amount: item.net_amount,
|
||||
taxes: $.map(tax_accounts, function(head) {
|
||||
return item_tax_record[head[0]] ?
|
||||
"<td class='text-right'>(" + item_tax_record[head[0]][0] + ") " + item_tax_record[head[0]][1] + "</td>" :
|
||||
"<td></td>";
|
||||
}).join("\n")
|
||||
});
|
||||
}).join("\n");
|
||||
|
||||
if(!rows) return "";
|
||||
return '<div class="tax-break-up" style="overflow-x: auto;">\
|
||||
<table class="table table-bordered table-hover">\
|
||||
<thead><tr>' + headings + '</tr></thead> \
|
||||
<tbody>' + rows + '</tbody> \
|
||||
</table></div>';
|
||||
}
|
||||
})
|
||||
|
@ -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 '<th style="min-width: 100px;">' + (head || "") + "</th>" }).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("<tr><td>%(item_name)s</td>%(taxes)s</tr>", {
|
||||
item_name: item.item_name,
|
||||
taxes: $.map(tax_accounts, function(head) {
|
||||
return item_tax_record[head[0]] ?
|
||||
"<td>(" + item_tax_record[head[0]][0] + ") " + item_tax_record[head[0]][1] + "</td>" :
|
||||
"<td></td>";
|
||||
}).join("\n")
|
||||
});
|
||||
}).join("\n");
|
||||
|
||||
if(!rows) return "";
|
||||
return '<p><a class="h6 text-muted" href="#" onclick="$(\'.tax-break-up\').toggleClass(\'hide\'); return false;">'
|
||||
+ __("Show tax break-up") + '</a></p>\
|
||||
<div class="tax-break-up hide" style="overflow-x: auto;"><table class="table table-bordered table-hover">\
|
||||
<thead><tr>' + headings + '</tr></thead> \
|
||||
<tbody>' + rows + '</tbody> \
|
||||
</table></div>';
|
||||
},
|
||||
|
||||
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) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
{% if state %}{{ state }}<br>{% endif -%}
|
||||
{% if pincode %}{{ pincode }}<br>{% endif -%}
|
||||
{{ country }}<br>
|
||||
{% if gstin %}GSTIN: {{ gstin }}<br>{% endif -%}
|
||||
{% if phone %}Phone: {{ phone }}<br>{% endif -%}
|
||||
{% if fax %}Fax: {{ fax }}<br>{% endif -%}
|
||||
{% if email_id %}Email: {{ email_id }}<br>{% endif -%}
|
||||
{% if email_id %}Email: {{ email_id }}<br>{% endif -%}
|
||||
{% if gstin %}GSTIN: {{ gstin }}<br>{% endif -%}
|
@ -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'},
|
||||
|
@ -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))
|
||||
|
0
erpnext/regional/print_format/__init__.py
Normal file
0
erpnext/regional/print_format/__init__.py
Normal file
@ -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\": \"<div class=\\\"print-heading\\\">\\t\\t\\t\\t<h2>Sales Invoice<br><small>{{ doc.name }}</small>\\t\\t\\t\\t</h2></div>\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"company\", \"label\": \"Company\"}, {\"print_hide\": 0, \"fieldname\": \"company_address_display\", \"label\": \"Company Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"posting_date\", \"label\": \"Date\"}, {\"print_hide\": 0, \"fieldname\": \"due_date\", \"label\": \"Payment Due Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"options\": \"<hr>\", \"fieldname\": \"_custom_html\", \"fieldtype\": \"HTML\", \"label\": \"Custom HTML\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"customer_name\", \"label\": \"Customer Name\"}, {\"print_hide\": 0, \"fieldname\": \"address_display\", \"label\": \"Address\"}, {\"print_hide\": 0, \"fieldname\": \"contact_display\", \"label\": \"Contact\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"shipping_address\", \"label\": \"Shipping Address\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"200px\"}, {\"print_hide\": 0, \"fieldname\": \"gst_hsn_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"items\", \"label\": \"Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"label\": \"Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}], \"print_hide\": 0, \"fieldname\": \"taxes\", \"label\": \"Sales Taxes and Charges\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"grand_total\", \"label\": \"Grand Total\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\", \"label\": \"Rounded Total\"}, {\"print_hide\": 0, \"fieldname\": \"in_words\", \"label\": \"In Words\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"other_charges_calculation\", \"align\": \"left\", \"label\": \"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"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user