[regional] ability to send gst reminders to all parties

This commit is contained in:
Rushabh Mehta 2017-06-27 17:31:41 +05:30
parent 51520f9de6
commit 00ae424cac
22 changed files with 432 additions and 71 deletions

View File

@ -0,0 +1,3 @@
{% include "erpnext/regional/india/party.js" %}
erpnext.setup_gst_reminder_button('Supplier');

View File

@ -201,6 +201,10 @@ def get_data():
{
"label": _("Goods and Services Tax (GST India)"),
"items": [
{
"type": "doctype",
"name": "GST Settings",
},
{
"type": "doctype",
"name": "GST HSN Code",

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

View File

@ -0,0 +1,21 @@
# Sending GST Reminders
You can send email reminders to your Customers and Suppliers so that they can directly add or update their GSTIN numbers
To send GSTIN Reminders, you can either open the Customer / Supplier record or **GST Settings**
<img class="screenshot" alt="GST Settings" src="{{docs_base_url}}/assets/img/regional/india/gstin-settings.png">
Here you can click on the "Send GSTIN Update Reminders" button to send email reminders to all your customers
### Updating GSTIN
Your customers will receive an email asking them to update their GSTIN and that email will link them to a portal page:
<img class="screenshot" alt="GST Portal Page" src="{{docs_base_url}}/assets/img/regional/india/gstin-portal-update.png">
Here they can update their GSTIN and it will automatically be added to your customer GSTIN record.
#### Sample GSTIN Reminder Email
<img class="screenshot" alt="GST Reminder Email" src="{{docs_base_url}}/assets/img/regional/india/gstin-reminder-email.png">

View File

@ -0,0 +1,67 @@
# GST Features in ERPNext
### 1. Setting up GSTIN
GST Law requires that you maintain the GSTIN number for all your suppliers and vendors. In ERPNext, GSTIN is linked to the **Address**
<img class="screenshot" alt="GST in Customer" src="{{docs_base_url}}/assets/img/regional/india/gstin-customer.gif">
**GST for your Company Address**
You also need to set the Address for your own Company and your Company's GST Number
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">
### 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
<img class="screenshot" alt="HSN in Item" src="{{docs_base_url}}/assets/img/regional/india/hsn-item.gif">
### 3. Making Tax Masters
To setup Billing in GST, you need to create 3 Tax Accounts for the various GST reporting heads CGST - Central GST, SGST - State GST, IGST - Inter-state GST
Go to your **Chart of Accounts**, under the Duties and Taxes head of your account, create 3 Accounts
**Note:** Usually the rate in CGST and SGST is half of IGST. For example if most of your items are billed at 18%, then create IGST at 18%, CGST and SGST at 9% each.
<img class="screenshot" alt="GST in Customer" src="{{docs_base_url}}/assets/img/regional/india/gst-in-coa.png">
### 4. Make Tax Templates
You will have have to make two tax templates for both your sales and purchase, one for in state sales and other for out of state sales.
In your **In State GST** template, select 2 accounts, SGST and CGST
<img class="screenshot" alt="GST in Customer" src="{{docs_base_url}}/assets/img/regional/india/gst-template-in-state.png">
In your **Out of State GST** template, select IGST
### 5. Making GST Ready Invoices
If you have setup the GSTIN of your Customers and Suppliers, and your tax template, you are ready to go for making GST Ready Invoices!
For **Sales Invoice**,
1. Select the correct Customer and Item and the address where the transaction will happen.
2. Check if the GSTIN of your Company and Supplier have been correctly set.
3. Check if the HSN Number has been set in the Item
4. Select the the **In State GST** or **Out of State GST** template that you have created based on the type of transaction
5. Save and Submit the Invoice
<img class="screenshot" alt="GST Invoice" src="{{docs_base_url}}/assets/img/regional/india/gst-invoice.gif">
### Reports
ERPNext comes with most of your reports you need to prepare your GST Returns. Go to Accounts > GST India head for the list.
<img class="screenshot" alt="GST Menus" src="{{docs_base_url}}/assets/img/regional/india/gst-menu.png">
You can check the impact of your invoice in the **GST Sales Register** and **GST Itemised Sales Register**
<img class="screenshot" alt="GST Itemised Sales Register" src="{{docs_base_url}}/assets/img/regional/india/gst-itemised.png">

View File

@ -2,70 +2,4 @@
As of 2017, India will fall under the new GST (Goods and Services Tax) regime and ERPNext makes it easy for users to track the details of its Supplier and Customers across Invoices and make the required reports.
## GST Features in ERPNext
### 1. Setting up GSTIN
GST Law requires that you maintain the GSTIN number for all your suppliers and vendors. In ERPNext, GSTIN is linked to the **Address**
<img class="screenshot" alt="GST in Customer" src="{{docs_base_url}}/assets/img/regional/india/gstin-customer.gif">
**GST for your Company Address**
You also need to set the Address for your own Company and your Company's GST Number
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">
### 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
<img class="screenshot" alt="HSN in Item" src="{{docs_base_url}}/assets/img/regional/india/hsn-item.gif">
### 3. Making Tax Masters
To setup Billing in GST, you need to create 3 Tax Accounts for the various GST reporting heads CGST - Central GST, SGST - State GST, IGST - Inter-state GST
Go to your **Chart of Accounts**, under the Duties and Taxes head of your account, create 3 Accounts
**Note:** Usually the rate in CGST and SGST is half of IGST. For example if most of your items are billed at 18%, then create IGST at 18%, CGST and SGST at 9% each.
<img class="screenshot" alt="GST in Customer" src="{{docs_base_url}}/assets/img/regional/india/gst-in-coa.png">
### 4. Make Tax Templates
You will have have to make two tax templates for both your sales and purchase, one for in state sales and other for out of state sales.
In your **In State GST** template, select 2 accounts, SGST and CGST
<img class="screenshot" alt="GST in Customer" src="{{docs_base_url}}/assets/img/regional/india/gst-template-in-state.png">
In your **Out of State GST** template, select IGST
### 5. Making GST Ready Invoices
If you have setup the GSTIN of your Customers and Suppliers, and your tax template, you are ready to go for making GST Ready Invoices!
For **Sales Invoice**,
1. Select the correct Customer and Item and the address where the transaction will happen.
2. Check if the GSTIN of your Company and Supplier have been correctly set.
3. Check if the HSN Number has been set in the Item
4. Select the the **In State GST** or **Out of State GST** template that you have created based on the type of transaction
5. Save and Submit the Invoice
<img class="screenshot" alt="GST Invoice" src="{{docs_base_url}}/assets/img/regional/india/gst-invoice.gif">
### Reports
ERPNext comes with most of your reports you need to prepare your GST Returns. Go to Accounts > GST India head for the list.
<img class="screenshot" alt="GST Menus" src="{{docs_base_url}}/assets/img/regional/india/gst-menu.png">
You can check the impact of your invoice in the **GST Sales Register** and **GST Itemised Sales Register**
<img class="screenshot" alt="GST Itemised Sales Register" src="{{docs_base_url}}/assets/img/regional/india/gst-itemised.png">
{index}

View File

@ -0,0 +1,2 @@
gst-setup
gst-reminders

View File

@ -407,4 +407,4 @@ erpnext.patches.v8_0.create_domain_docs #16-05-2017
erpnext.patches.v8_0.update_sales_cost_in_project
erpnext.patches.v8_0.save_system_settings
erpnext.patches.v8_1.delete_deprecated_reports
erpnext.patches.v8_1.setup_gst_india
erpnext.patches.v8_1.setup_gst_india #2017-06-27

View File

@ -17,9 +17,10 @@ def execute():
def send_gst_update_email():
message = """Hello,
<p>ERPNext is now GST Ready.</p>
<p>ERPNext is now GST Ready!</p>
<p>To start making GST Invoices from 1st of July, you just need to create new Tax Accounts, Templates and update your Customer's and Supplier's GST Numbers.</p>
<p>To start making GST Invoices from 1st of July, you just need to create new Tax Accounts,
Templates and update your Customer's and Supplier's GST Numbers.</p>
<p>Please refer {gst_document_link} to know more about how to setup and implement GST in ERPNext.</p>

View File

@ -0,0 +1,25 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('GST Settings', {
refresh: function(frm) {
frm.add_custom_button('Send GST Update Reminder', () => {
return new Promise((resolve) => {
return frappe.call({
method: 'erpnext.regional.doctype.gst_settings.gst_settings.send_reminder'
}).always(() => { resolve(); });
});
});
$(frm.fields_dict.gst_summary.wrapper).empty().html(
`<table class="table table-bordered">
<tbody>
<tr>
<td>Total Addresses</td><td>${frm.doc.__onload.data.total_addresses}</td>
</tr><tr>
<td>Total Addresses with GST</td><td>${frm.doc.__onload.data.total_addresses_with_gstin}</td>
</tr>
</tbody></table>`
)
}
});

View File

@ -0,0 +1,101 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2017-06-27 15:09:01.318003",
"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": "gst_summary",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "GST Summary",
"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": "gstin_email_sent_on",
"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": "GSTIN Email Sent On",
"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
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2017-06-27 16:20:21.206397",
"modified_by": "Administrator",
"module": "Regional",
"name": "GST Settings",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"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
}

View File

@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe, os
from frappe.utils import get_url, nowdate, date_diff
from frappe.model.document import Document
from frappe.contacts.doctype.contact.contact import get_default_contact
class EmailMissing(frappe.ValidationError): pass
class GSTSettings(Document):
def onload(self):
data = frappe._dict()
data.total_addresses = frappe.db.sql('''select count(*) from tabAddress where country = "India"''')
data.total_addresses_with_gstin = frappe.db.sql('''select distinct count(*)
from tabAddress where country = "India" and ifnull(gstin, '')!='' ''')
self.set_onload('data', data)
@frappe.whitelist()
def send_reminder():
frappe.has_permission('GST Settings', throw=True)
last_sent = frappe.db.get_single_value('GST Settings', 'gstin_email_sent_on')
if last_sent and date_diff(nowdate(), last_sent) < 3:
frappe.throw("Please wait 3 days before resending the reminder.")
frappe.db.set_value('GST Settings', 'GST Settings', 'gstin_email_sent_on', nowdate())
# enqueue if large number of customers, suppliser
frappe.enqueue('erpnext.regional.doctype.gst_settings.gst_settings.send_gstin_reminder_to_all_parties')
frappe.msgprint('Email Reminders will be sent to all parties with email contacts')
def send_gstin_reminder_to_all_parties():
parties = []
for address_name in frappe.db.sql('''select name
from tabAddress where country = "India" and ifnull(gstin, '')='' '''):
address = frappe.get_doc('Address', address_name[0])
for link in address.links:
party = frappe.get_doc(link.link_doctype, link.link_name)
if link.link_doctype in ('Customer', 'Supplier'):
t = (link.link_doctype, link.link_name, address.email_id)
if not t in parties:
parties.append(t)
sent_to = []
for party in parties:
# get email from default contact
try:
email_id = _send_gstin_reminder(party[0], party[1], party[2], sent_to)
sent_to.append(email_id)
except EmailMissing:
pass
@frappe.whitelist()
def send_gstin_reminder(party_type, party):
'''Send GSTIN reminder to one party (called from Customer, Supplier form)'''
frappe.has_permission(party_type, throw=True)
email = _send_gstin_reminder(party_type ,party)
if email:
frappe.msgprint('Reminder to update GSTIN Sent', title='Reminder sent', indicator='green')
def _send_gstin_reminder(party_type, party, default_email_id=None, sent_to=None):
'''Send GST Reminder email'''
email_id = frappe.db.get_value('Contact', get_default_contact(party_type, party), 'email_id')
if not email_id:
# get email from address
email_id = default_email_id
if not email_id:
frappe.throw('Email not found in default contact', exception=EmailMissing)
if sent_to and email_id in sent_to:
return
frappe.sendmail(
subject='Please update your GSTIN',
recipients=email_id,
message='''
<p>Hello,</p>
<p>Please help us send you GST Ready Invoices.</p>
<p>
<a href="{0}?party={1}">
Click on the here to update your GSTIN Number in our system
</a>
</p>
<p style="color: #aaa; font-size: 11px; margin-top: 30px;">
Get your GST Ready ERP system at <a href="https://erpnext.com">https://erpnext.com</a>
<br>
ERPNext is a free and open source ERP system.
</p>
'''.format(os.path.join(get_url(), '/regional/india/update-gstin'), party)
)
return email_id

View File

@ -0,0 +1,25 @@
erpnext.setup_gst_reminder_button = (doctype) => {
frappe.ui.form.on(doctype, {
refresh: (frm) => {
if(!frm.is_new()) {
var missing = false;
frm.doc.__onload.addr_list && frm.doc.__onload.addr_list.forEach((d) => {
if(!d.gstin) missing = true;
});
if (!missing) return;
frm.add_custom_button('Send GST Update Reminder', () => {
return new Promise((resolve) => {
return frappe.call({
method: 'erpnext.regional.doctype.gst_settings.gst_settings.send_gstin_reminder',
args: {
party_type: frm.doc.doctype,
party: frm.doc.name,
}
}).always(() => { resolve(); });
});
});
}
}
})
};

View File

@ -64,7 +64,7 @@ def add_custom_roles_for_reports():
)).insert()
def add_permissions():
for doctype in ('GST HSN Code',):
for doctype in ('GST HSN Code', 'GST Settings'):
add_permission(doctype, 'Accounts Manager', 0)
add_permission(doctype, 'All', 0)

View File

@ -0,0 +1,3 @@
{% include "erpnext/regional/india/party.js" %}
erpnext.setup_gst_reminder_button('Customer')

View File

@ -0,0 +1,37 @@
{% extends "templates/web.html" %}
{% block title %}Update GSTIN{% endblock %}
{% block header %}<h2>Update GSTIN</h2>{% endblock %}
{% block page_content %}
<h3>{{ party.name }}</h3>
{% if invalid_gstin %}
<p class='alert alert-danger' style='max-width: 300px;'>
Invalid GSTIN
</p>
<p>
<a href="?party={{ party.name }}">Edit Again</a>
</p>
{% elif updated %}
<p class='alert alert-success' style='max-width: 300px;'>
<i class='octicon octicon-check'></i> GSTIN Updated
</p>
<p>
<a href="?party={{ party.name }}">Edit Again</a>
</p>
{% else %}
<p class='text-muted'>Please update your GSTIN for us to issue correct tax invoice</p>
<form method='GET' action='/regional/india/update-gstin.html'>
<input type='hidden' value='{{ party.name }}' name='party'>
{% for address in party.__onload.addr_list %}
<div class='bordered' style='max-width: 300px; margin-bottom: 15px;'>
{{ address.display }}
<p><input type='text' class='form-control'
value='{{ address.gstin }}' name='{{ address.name }}' placeholder='GSTIN'></p>
</div>
{% endfor %}
<p><input type='submit' class='btn btn-primary' value='Update'></p>
</form>
{% endif %}
{% endblock %}

View File

@ -0,0 +1,40 @@
import frappe
from frappe import _
def get_context(context):
context.no_cache = 1
party = frappe.form_dict.party
try:
update_gstin(context)
except frappe.ValidationError:
context.invalid_gstin = 1
party_type = 'Customer'
party = frappe.db.get_value('Customer', party)
if not party:
party_type = 'Supplier'
party = frappe.db.get_value('Supplier', party)
if not party:
frappe.throw(_("Not Found"), frappe.DoesNotExistError)
context.party = frappe.get_doc(party_type, party)
context.party.onload()
def update_gstin(context):
dirty = False
for key, value in frappe.form_dict.items():
if key != 'party':
address_name = frappe.get_value('Address', key)
if address_name:
address = frappe.get_doc('Address', address_name)
address.gstin = value
address.save(ignore_permissions=True)
dirty = True
if dirty:
frappe.db.commit()
context.updated = True