refactor: remove India specific code
This commit is contained in:
parent
83a60a2a17
commit
3936d8b70e
@ -1 +0,0 @@
|
||||
C Form (India specific only) - Will be deprecated.
|
@ -1,43 +0,0 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
//c-form js file
|
||||
// -----------------------------
|
||||
|
||||
frappe.ui.form.on('C-Form', {
|
||||
setup(frm) {
|
||||
frm.fields_dict.invoices.grid.get_field("invoice_no").get_query = function(doc) {
|
||||
return {
|
||||
filters: {
|
||||
"docstatus": 1,
|
||||
"customer": doc.customer,
|
||||
"company": doc.company,
|
||||
"c_form_applicable": 'Yes',
|
||||
"c_form_no": ''
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
frm.fields_dict.state.get_query = function() {
|
||||
return {
|
||||
filters: {
|
||||
country: "India"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on('C-Form Invoice Detail', {
|
||||
invoice_no(frm, cdt, cdn) {
|
||||
let d = frappe.get_doc(cdt, cdn);
|
||||
|
||||
if (d.invoice_no) {
|
||||
frm.call('get_invoice_details', {
|
||||
invoice_no: d.invoice_no
|
||||
}).then(r => {
|
||||
frappe.model.set_value(cdt, cdn, r.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
@ -1,511 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "naming_series:",
|
||||
"beta": 0,
|
||||
"creation": "2013-03-07 11:55:06",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"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": "Series",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "ACC-CF-.YYYY.-",
|
||||
"permlevel": 0,
|
||||
"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": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "c_form_no",
|
||||
"fieldtype": "Data",
|
||||
"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": "C-Form No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "received_date",
|
||||
"fieldtype": "Date",
|
||||
"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": "Received Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "customer",
|
||||
"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": "Customer",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break1",
|
||||
"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,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "50%",
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company",
|
||||
"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": 1,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "quarter",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Quarter",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nI\nII\nIII\nIV",
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_amount",
|
||||
"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 Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "state",
|
||||
"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": "State",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break0",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoices",
|
||||
"fieldtype": "Table",
|
||||
"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": "Invoices",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "C-Form Invoice Detail",
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_invoiced_amount",
|
||||
"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 Invoiced Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 1,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "C-Form",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 3,
|
||||
"modified": "2018-08-21 14:44:30.558767",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "C-Form",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 1,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "All",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_order": "DESC",
|
||||
"timeline_field": "customer",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt
|
||||
|
||||
|
||||
class CForm(Document):
|
||||
def validate(self):
|
||||
"""Validate invoice that c-form is applicable
|
||||
and no other c-form is received for that"""
|
||||
|
||||
for d in self.get('invoices'):
|
||||
if d.invoice_no:
|
||||
inv = frappe.db.sql("""select c_form_applicable, c_form_no from
|
||||
`tabSales Invoice` where name = %s and docstatus = 1""", d.invoice_no)
|
||||
|
||||
if inv and inv[0][0] != 'Yes':
|
||||
frappe.throw(_("C-form is not applicable for Invoice: {0}").format(d.invoice_no))
|
||||
|
||||
elif inv and inv[0][1] and inv[0][1] != self.name:
|
||||
frappe.throw(_("""Invoice {0} is tagged in another C-form: {1}.
|
||||
If you want to change C-form no for this invoice,
|
||||
please remove invoice no from the previous c-form and then try again"""\
|
||||
.format(d.invoice_no, inv[0][1])))
|
||||
|
||||
elif not inv:
|
||||
frappe.throw(_("Row {0}: Invoice {1} is invalid, it might be cancelled / does not exist. \
|
||||
Please enter a valid Invoice".format(d.idx, d.invoice_no)))
|
||||
|
||||
def on_update(self):
|
||||
""" Update C-Form No on invoices"""
|
||||
self.set_total_invoiced_amount()
|
||||
|
||||
def on_submit(self):
|
||||
self.set_cform_in_sales_invoices()
|
||||
|
||||
def before_cancel(self):
|
||||
# remove cform reference
|
||||
frappe.db.sql("""update `tabSales Invoice` set c_form_no=null where c_form_no=%s""", self.name)
|
||||
|
||||
def set_cform_in_sales_invoices(self):
|
||||
inv = [d.invoice_no for d in self.get('invoices')]
|
||||
if inv:
|
||||
frappe.db.sql("""update `tabSales Invoice` set c_form_no=%s, modified=%s where name in (%s)""" %
|
||||
('%s', '%s', ', '.join(['%s'] * len(inv))), tuple([self.name, self.modified] + inv))
|
||||
|
||||
frappe.db.sql("""update `tabSales Invoice` set c_form_no = null, modified = %s
|
||||
where name not in (%s) and ifnull(c_form_no, '') = %s""" %
|
||||
('%s', ', '.join(['%s']*len(inv)), '%s'), tuple([self.modified] + inv + [self.name]))
|
||||
else:
|
||||
frappe.throw(_("Please enter atleast 1 invoice in the table"))
|
||||
|
||||
def set_total_invoiced_amount(self):
|
||||
total = sum(flt(d.grand_total) for d in self.get('invoices'))
|
||||
frappe.db.set(self, 'total_invoiced_amount', total)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_invoice_details(self, invoice_no):
|
||||
""" Pull details from invoices for referrence """
|
||||
if invoice_no:
|
||||
inv = frappe.db.get_value("Sales Invoice", invoice_no,
|
||||
["posting_date", "territory", "base_net_total", "base_grand_total"], as_dict=True)
|
||||
return {
|
||||
'invoice_date' : inv.posting_date,
|
||||
'territory' : inv.territory,
|
||||
'net_total' : inv.base_net_total,
|
||||
'grand_total' : inv.base_grand_total
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('C-Form')
|
||||
|
||||
class TestCForm(unittest.TestCase):
|
||||
pass
|
@ -1 +0,0 @@
|
||||
Invoice detail for parent C-Form.
|
@ -1,168 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:38",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "invoice_no",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Invoice",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "160px",
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "160px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "invoice_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "120px",
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "",
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Territory",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Territory",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "120px",
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "net_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Net Total",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "120px",
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "grand_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Grand Total",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "120px",
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "120px"
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-11 03:27:58.768719",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "C-Form Invoice Detail",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"track_seen": 0
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class CFormInvoiceDetail(Document):
|
||||
pass
|
@ -27,7 +27,6 @@ def test_create_test_data():
|
||||
"item_name": "_Test Tesla Car",
|
||||
"apply_warehouse_wise_reorder_level": 0,
|
||||
"warehouse":"Stores - _TC",
|
||||
"gst_hsn_code": "999800",
|
||||
"valuation_rate": 5000,
|
||||
"standard_rate":5000,
|
||||
"item_defaults": [{
|
||||
|
@ -1,82 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2018-01-02 15:48:58.768352",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"company",
|
||||
"cgst_account",
|
||||
"sgst_account",
|
||||
"igst_account",
|
||||
"cess_account",
|
||||
"is_reverse_charge_account"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"columns": 1,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "cgst_account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "CGST Account",
|
||||
"options": "Account",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "sgst_account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "SGST Account",
|
||||
"options": "Account",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "igst_account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "IGST Account",
|
||||
"options": "Account",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "cess_account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "CESS Account",
|
||||
"options": "Account"
|
||||
},
|
||||
{
|
||||
"columns": 1,
|
||||
"default": "0",
|
||||
"fieldname": "is_reverse_charge_account",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Is Reverse Charge Account"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-04-09 12:30:25.889993",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GST Account",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class GSTAccount(Document):
|
||||
pass
|
@ -1,17 +0,0 @@
|
||||
frappe.ui.form.on("Journal Entry", {
|
||||
refresh: function(frm) {
|
||||
frm.set_query('company_address', function(doc) {
|
||||
if(!doc.company) {
|
||||
frappe.throw(__('Please set Company'));
|
||||
}
|
||||
|
||||
return {
|
||||
query: 'frappe.contacts.doctype.address.address.address_query',
|
||||
filters: {
|
||||
link_doctype: 'Company',
|
||||
link_name: doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
@ -1,29 +0,0 @@
|
||||
frappe.ui.form.on("Payment Entry", {
|
||||
company: function(frm) {
|
||||
frappe.call({
|
||||
'method': 'frappe.contacts.doctype.address.address.get_default_address',
|
||||
'args': {
|
||||
'doctype': 'Company',
|
||||
'name': frm.doc.company
|
||||
},
|
||||
'callback': function(r) {
|
||||
frm.set_value('company_address', r.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
party: function(frm) {
|
||||
if (frm.doc.party_type == "Customer" && frm.doc.party) {
|
||||
frappe.call({
|
||||
'method': 'frappe.contacts.doctype.address.address.get_default_address',
|
||||
'args': {
|
||||
'doctype': 'Customer',
|
||||
'name': frm.doc.party
|
||||
},
|
||||
'callback': function(r) {
|
||||
frm.set_value('customer_address', r.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
@ -164,8 +164,6 @@
|
||||
"debit_to",
|
||||
"party_account_currency",
|
||||
"is_opening",
|
||||
"c_form_applicable",
|
||||
"c_form_no",
|
||||
"column_break8",
|
||||
"remarks",
|
||||
"sales_team_section_break",
|
||||
@ -1400,23 +1398,6 @@
|
||||
"options": "No\nYes",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "c_form_applicable",
|
||||
"fieldtype": "Select",
|
||||
"label": "C-Form Applicable",
|
||||
"no_copy": 1,
|
||||
"options": "No\nYes",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "c_form_no",
|
||||
"fieldtype": "Link",
|
||||
"label": "C-Form No",
|
||||
"no_copy": 1,
|
||||
"options": "C-Form",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break8",
|
||||
"fieldtype": "Column Break",
|
||||
@ -1573,7 +1554,7 @@
|
||||
"icon": "fa fa-file-text",
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-10-05 12:11:53.871828",
|
||||
"modified": "2022-02-19 06:25:00.983936",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Invoice",
|
||||
@ -1623,6 +1604,7 @@
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"timeline_field": "customer",
|
||||
"title_field": "title",
|
||||
"track_changes": 1,
|
||||
|
@ -1,3 +0,0 @@
|
||||
{% include "erpnext/regional/india/taxes.js" %}
|
||||
|
||||
erpnext.setup_auto_gst_taxation('Purchase Invoice');
|
@ -1,53 +0,0 @@
|
||||
{% include "erpnext/regional/india/taxes.js" %}
|
||||
{% include "erpnext/regional/india/e_invoice/einvoice.js" %}
|
||||
|
||||
erpnext.setup_auto_gst_taxation('Sales Invoice');
|
||||
erpnext.setup_einvoice_actions('Sales Invoice')
|
||||
|
||||
frappe.ui.form.on("Sales Invoice", {
|
||||
setup: function(frm) {
|
||||
frm.set_query('transporter', function() {
|
||||
return {
|
||||
filters: {
|
||||
'is_transporter': 1
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('driver', function(doc) {
|
||||
return {
|
||||
filters: {
|
||||
'transporter': doc.transporter
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
if(frm.doc.docstatus == 1 && !frm.is_dirty()
|
||||
&& !frm.doc.is_return && !frm.doc.ewaybill) {
|
||||
|
||||
frm.add_custom_button('E-Way Bill JSON', () => {
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.utils.generate_ewb_json',
|
||||
args: {
|
||||
'dt': frm.doc.doctype,
|
||||
'dn': [frm.doc.name]
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
const args = {
|
||||
cmd: 'erpnext.regional.india.utils.download_ewb_json',
|
||||
data: r.message,
|
||||
docname: frm.doc.name
|
||||
};
|
||||
open_url_post(frappe.request.url, args);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}, __("Create"));
|
||||
}
|
||||
}
|
||||
|
||||
});
|
@ -1,174 +0,0 @@
|
||||
var globalOnload = frappe.listview_settings['Sales Invoice'].onload;
|
||||
frappe.listview_settings['Sales Invoice'].onload = function (list_view) {
|
||||
|
||||
// Provision in case onload event is added to sales_invoice.js in future
|
||||
if (globalOnload) {
|
||||
globalOnload(list_view);
|
||||
}
|
||||
|
||||
const action = () => {
|
||||
const selected_docs = list_view.get_checked_items();
|
||||
const docnames = list_view.get_checked_items(true);
|
||||
|
||||
for (let doc of selected_docs) {
|
||||
if (doc.docstatus !== 1) {
|
||||
frappe.throw(__("E-Way Bill JSON can only be generated from a submitted document"));
|
||||
}
|
||||
}
|
||||
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.utils.generate_ewb_json',
|
||||
args: {
|
||||
'dt': list_view.doctype,
|
||||
'dn': docnames
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
const args = {
|
||||
cmd: 'erpnext.regional.india.utils.download_ewb_json',
|
||||
data: r.message,
|
||||
docname: docnames
|
||||
};
|
||||
open_url_post(frappe.request.url, args);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
list_view.page.add_actions_menu_item(__('Generate E-Way Bill JSON'), action, false);
|
||||
|
||||
const generate_irns = () => {
|
||||
const docnames = list_view.get_checked_items(true);
|
||||
if (docnames && docnames.length) {
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.e_invoice.utils.generate_einvoices',
|
||||
args: { docnames },
|
||||
freeze: true,
|
||||
freeze_message: __('Generating E-Invoices...')
|
||||
});
|
||||
} else {
|
||||
frappe.msgprint({
|
||||
message: __('Please select at least one sales invoice to generate IRN'),
|
||||
title: __('No Invoice Selected'),
|
||||
indicator: 'red'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const cancel_irns = () => {
|
||||
const docnames = list_view.get_checked_items(true);
|
||||
|
||||
const fields = [
|
||||
{
|
||||
"label": "Reason",
|
||||
"fieldname": "reason",
|
||||
"fieldtype": "Select",
|
||||
"reqd": 1,
|
||||
"default": "1-Duplicate",
|
||||
"options": ["1-Duplicate", "2-Data Entry Error", "3-Order Cancelled", "4-Other"]
|
||||
},
|
||||
{
|
||||
"label": "Remark",
|
||||
"fieldname": "remark",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1
|
||||
}
|
||||
];
|
||||
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __("Cancel IRN"),
|
||||
fields: fields,
|
||||
primary_action: function() {
|
||||
const data = d.get_values();
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.e_invoice.utils.cancel_irns',
|
||||
args: {
|
||||
doctype: list_view.doctype,
|
||||
docnames,
|
||||
reason: data.reason.split('-')[0],
|
||||
remark: data.remark
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: __('Cancelling E-Invoices...'),
|
||||
});
|
||||
d.hide();
|
||||
},
|
||||
primary_action_label: __('Submit')
|
||||
});
|
||||
d.show();
|
||||
};
|
||||
|
||||
let einvoicing_enabled = false;
|
||||
frappe.db.get_single_value("E Invoice Settings", "enable").then(enabled => {
|
||||
einvoicing_enabled = enabled;
|
||||
});
|
||||
|
||||
list_view.$result.on("change", "input[type=checkbox]", () => {
|
||||
if (einvoicing_enabled) {
|
||||
const docnames = list_view.get_checked_items(true);
|
||||
// show/hide e-invoicing actions when no sales invoices are checked
|
||||
if (docnames && docnames.length) {
|
||||
// prevent adding actions twice if e-invoicing action group already exists
|
||||
if (list_view.page.get_inner_group_button(__('E-Invoicing')).length == 0) {
|
||||
list_view.page.add_inner_button(__('Generate IRNs'), generate_irns, __('E-Invoicing'));
|
||||
list_view.page.add_inner_button(__('Cancel IRNs'), cancel_irns, __('E-Invoicing'));
|
||||
}
|
||||
} else {
|
||||
list_view.page.remove_inner_button(__('Generate IRNs'), __('E-Invoicing'));
|
||||
list_view.page.remove_inner_button(__('Cancel IRNs'), __('E-Invoicing'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frappe.realtime.on("bulk_einvoice_generation_complete", (data) => {
|
||||
const { failures, user, invoices } = data;
|
||||
|
||||
if (invoices.length != failures.length) {
|
||||
frappe.msgprint({
|
||||
message: __('{0} e-invoices generated successfully', [invoices.length]),
|
||||
title: __('Bulk E-Invoice Generation Complete'),
|
||||
indicator: 'orange'
|
||||
});
|
||||
}
|
||||
|
||||
if (failures && failures.length && user == frappe.session.user) {
|
||||
let message = `
|
||||
Failed to generate IRNs for following ${failures.length} sales invoices:
|
||||
<ul style="padding-left: 20px; padding-top: 5px;">
|
||||
${failures.map(d => `<li>${d.docname}</li>`).join('')}
|
||||
</ul>
|
||||
`;
|
||||
frappe.msgprint({
|
||||
message: message,
|
||||
title: __('Bulk E-Invoice Generation Complete'),
|
||||
indicator: 'orange'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
frappe.realtime.on("bulk_einvoice_cancellation_complete", (data) => {
|
||||
const { failures, user, invoices } = data;
|
||||
|
||||
if (invoices.length != failures.length) {
|
||||
frappe.msgprint({
|
||||
message: __('{0} e-invoices cancelled successfully', [invoices.length]),
|
||||
title: __('Bulk E-Invoice Cancellation Complete'),
|
||||
indicator: 'orange'
|
||||
});
|
||||
}
|
||||
|
||||
if (failures && failures.length && user == frappe.session.user) {
|
||||
let message = `
|
||||
Failed to cancel IRNs for following ${failures.length} sales invoices:
|
||||
<ul style="padding-left: 20px; padding-top: 5px;">
|
||||
${failures.map(d => `<li>${d.docname}</li>`).join('')}
|
||||
</ul>
|
||||
`;
|
||||
frappe.msgprint({
|
||||
message: message,
|
||||
title: __('Bulk E-Invoice Cancellation Complete'),
|
||||
indicator: 'orange'
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
@ -779,10 +779,6 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
}
|
||||
}
|
||||
|
||||
// India related fields
|
||||
if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
|
||||
else hide_field(['c_form_applicable', 'c_form_no']);
|
||||
|
||||
frm.refresh_fields();
|
||||
},
|
||||
|
||||
|
@ -174,8 +174,6 @@
|
||||
"debit_to",
|
||||
"party_account_currency",
|
||||
"is_opening",
|
||||
"c_form_applicable",
|
||||
"c_form_no",
|
||||
"column_break8",
|
||||
"unrealized_profit_loss_account",
|
||||
"remarks",
|
||||
@ -651,7 +649,6 @@
|
||||
"hide_seconds": 1,
|
||||
"label": "Ignore Pricing Rule",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
@ -1717,28 +1714,6 @@
|
||||
"options": "No\nYes",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "c_form_applicable",
|
||||
"fieldtype": "Select",
|
||||
"hide_days": 1,
|
||||
"hide_seconds": 1,
|
||||
"label": "C-Form Applicable",
|
||||
"length": 4,
|
||||
"no_copy": 1,
|
||||
"options": "No\nYes",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "c_form_no",
|
||||
"fieldtype": "Link",
|
||||
"hide_days": 1,
|
||||
"hide_seconds": 1,
|
||||
"label": "C-Form No",
|
||||
"no_copy": 1,
|
||||
"options": "C-Form",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break8",
|
||||
"fieldtype": "Column Break",
|
||||
@ -2038,7 +2013,7 @@
|
||||
"link_fieldname": "consolidated_invoice"
|
||||
}
|
||||
],
|
||||
"modified": "2021-12-23 20:19:38.667508",
|
||||
"modified": "2022-02-19 06:25:10.079943",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
@ -2089,6 +2064,7 @@
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"timeline_field": "customer",
|
||||
"title_field": "title",
|
||||
"track_changes": 1,
|
||||
|
@ -135,7 +135,6 @@ class SalesInvoice(SellingController):
|
||||
self.loyalty_redemption_cost_center = lp.cost_center if not self.loyalty_redemption_cost_center else self.loyalty_redemption_cost_center
|
||||
|
||||
self.set_against_income_account()
|
||||
self.validate_c_form()
|
||||
self.validate_time_sheets_are_submitted()
|
||||
self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items")
|
||||
if not self.is_return:
|
||||
@ -318,8 +317,6 @@ class SalesInvoice(SellingController):
|
||||
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
||||
self.update_serial_no(in_cancel=True)
|
||||
|
||||
self.validate_c_form_on_cancel()
|
||||
|
||||
# Updating stock ledger should always be called after updating prevdoc status,
|
||||
# because updating reserved qty in bin depends upon updated delivered qty in SO
|
||||
if self.update_stock == 1:
|
||||
@ -701,20 +698,6 @@ class SalesInvoice(SellingController):
|
||||
if flt(self.change_amount) and not self.account_for_change_amount:
|
||||
msgprint(_("Please enter Account for Change Amount"), raise_exception=1)
|
||||
|
||||
def validate_c_form(self):
|
||||
""" Blank C-form no if C-form applicable marked as 'No'"""
|
||||
if self.amended_from and self.c_form_applicable == 'No' and self.c_form_no:
|
||||
frappe.db.sql("""delete from `tabC-Form Invoice Detail` where invoice_no = %s
|
||||
and parent = %s""", (self.amended_from, self.c_form_no))
|
||||
|
||||
frappe.db.set(self, 'c_form_no', '')
|
||||
|
||||
def validate_c_form_on_cancel(self):
|
||||
""" Display message if C-Form no exists on cancellation of Sales Invoice"""
|
||||
if self.c_form_applicable == 'Yes' and self.c_form_no:
|
||||
msgprint(_("Please remove this Invoice {0} from C-Form {1}")
|
||||
.format(self.name, self.c_form_no), raise_exception = 1)
|
||||
|
||||
def validate_dropship_item(self):
|
||||
for item in self.items:
|
||||
if item.sales_order:
|
||||
@ -1265,9 +1248,7 @@ class SalesInvoice(SellingController):
|
||||
frappe.get_doc("Delivery Note", dn).update_billing_percentage(update_modified=update_modified)
|
||||
|
||||
def on_recurring(self, reference_doc, auto_repeat_doc):
|
||||
for fieldname in ("c_form_applicable", "c_form_no", "write_off_amount"):
|
||||
self.set(fieldname, reference_doc.get(fieldname))
|
||||
|
||||
self.set("write_off_amount", reference_doc.get("write_off_amount"))
|
||||
self.due_date = None
|
||||
|
||||
def update_serial_no(self, in_cancel=False):
|
||||
|
@ -23,7 +23,6 @@ from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_d
|
||||
from erpnext.controllers.accounts_controller import update_invoice_status
|
||||
from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data
|
||||
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
|
||||
from erpnext.regional.india.utils import get_ewb_data
|
||||
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||
@ -1412,37 +1411,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
for i, k in enumerate(expected_values["keys"]):
|
||||
self.assertEqual(d.get(k), expected_values[d.item_code][i])
|
||||
|
||||
def test_item_wise_tax_breakup_india(self):
|
||||
frappe.flags.country = "India"
|
||||
|
||||
si = self.create_si_to_test_tax_breakup()
|
||||
itemised_tax, itemised_taxable_amount = get_itemised_tax_breakup_data(si)
|
||||
|
||||
expected_itemised_tax = {
|
||||
"_Test Item": {
|
||||
"Service Tax": {
|
||||
"tax_rate": 10.0,
|
||||
"tax_amount": 1000.0
|
||||
}
|
||||
},
|
||||
"_Test Item 2": {
|
||||
"Service Tax": {
|
||||
"tax_rate": 10.0,
|
||||
"tax_amount": 500.0
|
||||
}
|
||||
}
|
||||
}
|
||||
expected_itemised_taxable_amount = {
|
||||
"_Test Item": 10000.0,
|
||||
"_Test Item 2": 5000.0
|
||||
}
|
||||
|
||||
self.assertEqual(itemised_tax, expected_itemised_tax)
|
||||
self.assertEqual(itemised_taxable_amount, expected_itemised_taxable_amount)
|
||||
|
||||
frappe.flags.country = None
|
||||
|
||||
def test_item_wise_tax_breakup_outside_india(self):
|
||||
def test_item_wise_tax_breakup(self):
|
||||
frappe.flags.country = "United States"
|
||||
|
||||
si = self.create_si_to_test_tax_breakup()
|
||||
@ -1477,7 +1446,6 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si = create_sales_invoice(qty=100, rate=50, do_not_save=True)
|
||||
si.append("items", {
|
||||
"item_code": "_Test Item",
|
||||
"gst_hsn_code": "999800",
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"qty": 100,
|
||||
"rate": 50,
|
||||
@ -1487,7 +1455,6 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
})
|
||||
si.append("items", {
|
||||
"item_code": "_Test Item 2",
|
||||
"gst_hsn_code": "999800",
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"qty": 100,
|
||||
"rate": 50,
|
||||
@ -1556,7 +1523,6 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
for rate in [400, 600, 100]:
|
||||
si.append("items", {
|
||||
"item_code": "_Test Item",
|
||||
"gst_hsn_code": "999800",
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"qty": 1,
|
||||
"rate": rate,
|
||||
@ -2080,74 +2046,6 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
check_gl_entries(self, target_doc.name, pi_gl_entries, add_days(nowdate(), -1))
|
||||
|
||||
def test_eway_bill_json(self):
|
||||
si = make_sales_invoice_for_ewaybill()
|
||||
|
||||
si.submit()
|
||||
|
||||
data = get_ewb_data("Sales Invoice", [si.name])
|
||||
|
||||
self.assertEqual(data['version'], '1.0.0421')
|
||||
self.assertEqual(data['billLists'][0]['fromGstin'], '27AAECE4835E1ZR')
|
||||
self.assertEqual(data['billLists'][0]['fromTrdName'], '_Test Company')
|
||||
self.assertEqual(data['billLists'][0]['toTrdName'], '_Test Customer')
|
||||
self.assertEqual(data['billLists'][0]['vehicleType'], 'R')
|
||||
self.assertEqual(data['billLists'][0]['totalValue'], 60000)
|
||||
self.assertEqual(data['billLists'][0]['cgstValue'], 5400)
|
||||
self.assertEqual(data['billLists'][0]['sgstValue'], 5400)
|
||||
self.assertEqual(data['billLists'][0]['vehicleNo'], 'KA12KA1234')
|
||||
self.assertEqual(data['billLists'][0]['itemList'][0]['taxableAmount'], 60000)
|
||||
self.assertEqual(data['billLists'][0]['actualFromStateCode'],7)
|
||||
self.assertEqual(data['billLists'][0]['fromStateCode'],27)
|
||||
|
||||
def test_einvoice_submission_without_irn(self):
|
||||
# init
|
||||
einvoice_settings = frappe.get_doc('E Invoice Settings')
|
||||
einvoice_settings.enable = 1
|
||||
einvoice_settings.applicable_from = nowdate()
|
||||
einvoice_settings.append('credentials', {
|
||||
'company': '_Test Company',
|
||||
'gstin': '27AAECE4835E1ZR',
|
||||
'username': 'test',
|
||||
'password': 'test'
|
||||
})
|
||||
einvoice_settings.save()
|
||||
|
||||
country = frappe.flags.country
|
||||
frappe.flags.country = 'India'
|
||||
|
||||
si = make_sales_invoice_for_ewaybill()
|
||||
self.assertRaises(frappe.ValidationError, si.submit)
|
||||
|
||||
si.irn = 'test_irn'
|
||||
si.submit()
|
||||
|
||||
# reset
|
||||
einvoice_settings = frappe.get_doc('E Invoice Settings')
|
||||
einvoice_settings.enable = 0
|
||||
frappe.flags.country = country
|
||||
|
||||
def test_einvoice_json(self):
|
||||
from erpnext.regional.india.e_invoice.utils import make_einvoice, validate_totals
|
||||
|
||||
si = get_sales_invoice_for_e_invoice()
|
||||
si.discount_amount = 100
|
||||
si.save()
|
||||
|
||||
einvoice = make_einvoice(si)
|
||||
self.assertTrue(einvoice['EwbDtls'])
|
||||
validate_totals(einvoice)
|
||||
|
||||
si.apply_discount_on = 'Net Total'
|
||||
si.save()
|
||||
einvoice = make_einvoice(si)
|
||||
validate_totals(einvoice)
|
||||
|
||||
[d.set('included_in_print_rate', 1) for d in si.taxes]
|
||||
si.save()
|
||||
einvoice = make_einvoice(si)
|
||||
validate_totals(einvoice)
|
||||
|
||||
def test_item_tax_net_range(self):
|
||||
item = create_item("T Shirt")
|
||||
|
||||
@ -2585,164 +2483,6 @@ def get_sales_invoice_for_e_invoice():
|
||||
|
||||
return si
|
||||
|
||||
def make_test_address_for_ewaybill():
|
||||
if not frappe.db.exists('Address', '_Test Address for Eway bill-Billing'):
|
||||
address = frappe.get_doc({
|
||||
"address_line1": "_Test Address Line 1",
|
||||
"address_line2": "_Test Address Line 2",
|
||||
"address_title": "_Test Address for Eway bill",
|
||||
"address_type": "Billing",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 1,
|
||||
"phone": "+910000000000",
|
||||
"gstin": "27AAECE4835E1ZR",
|
||||
"gst_state": "Maharashtra",
|
||||
"gst_state_number": "27",
|
||||
"pincode": "401108"
|
||||
}).insert()
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Company",
|
||||
"link_name": "_Test Company"
|
||||
})
|
||||
|
||||
address.save()
|
||||
|
||||
if not frappe.db.exists('Address', '_Test Customer-Address for Eway bill-Billing'):
|
||||
address = frappe.get_doc({
|
||||
"address_line1": "_Test Address Line 1",
|
||||
"address_line2": "_Test Address Line 2",
|
||||
"address_title": "_Test Customer-Address for Eway bill",
|
||||
"address_type": "Billing",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 1,
|
||||
"phone": "+910000000000",
|
||||
"gstin": "27AACCM7806M1Z3",
|
||||
"gst_state": "Maharashtra",
|
||||
"gst_state_number": "27",
|
||||
"pincode": "410038"
|
||||
}).insert()
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Customer",
|
||||
"link_name": "_Test Customer"
|
||||
})
|
||||
|
||||
address.save()
|
||||
|
||||
if not frappe.db.exists('Address', '_Test Customer-Address for Eway bill-Shipping'):
|
||||
address = frappe.get_doc({
|
||||
"address_line1": "_Test Address Line 1",
|
||||
"address_line2": "_Test Address Line 2",
|
||||
"address_title": "_Test Customer-Address for Eway bill",
|
||||
"address_type": "Shipping",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 1,
|
||||
"phone": "+910000000000",
|
||||
"gst_state": "Maharashtra",
|
||||
"gst_state_number": "27",
|
||||
"pincode": "410098"
|
||||
}).insert()
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Customer",
|
||||
"link_name": "_Test Customer"
|
||||
})
|
||||
|
||||
address.save()
|
||||
|
||||
if not frappe.db.exists('Address', '_Test Dispatch-Address for Eway bill-Shipping'):
|
||||
address = frappe.get_doc({
|
||||
"address_line1": "_Test Dispatch Address Line 1",
|
||||
"address_line2": "_Test Dispatch Address Line 2",
|
||||
"address_title": "_Test Dispatch-Address for Eway bill",
|
||||
"address_type": "Shipping",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 0,
|
||||
"phone": "+910000000000",
|
||||
"gstin": "07AAACC1206D1ZI",
|
||||
"gst_state": "Delhi",
|
||||
"gst_state_number": "07",
|
||||
"pincode": "1100101"
|
||||
}).insert()
|
||||
|
||||
address.save()
|
||||
|
||||
def make_test_transporter_for_ewaybill():
|
||||
if not frappe.db.exists('Supplier', '_Test Transporter'):
|
||||
frappe.get_doc({
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Transporter",
|
||||
"country": "India",
|
||||
"supplier_group": "_Test Supplier Group",
|
||||
"supplier_type": "Company",
|
||||
"is_transporter": 1
|
||||
}).insert()
|
||||
|
||||
def make_sales_invoice_for_ewaybill():
|
||||
make_test_address_for_ewaybill()
|
||||
make_test_transporter_for_ewaybill()
|
||||
|
||||
gst_settings = frappe.get_doc("GST Settings")
|
||||
|
||||
gst_account = frappe.get_all(
|
||||
"GST Account",
|
||||
fields=["cgst_account", "sgst_account", "igst_account"],
|
||||
filters = {"company": "_Test Company"}
|
||||
)
|
||||
|
||||
if not gst_account:
|
||||
gst_settings.append("gst_accounts", {
|
||||
"company": "_Test Company",
|
||||
"cgst_account": "Output Tax CGST - _TC",
|
||||
"sgst_account": "Output Tax SGST - _TC",
|
||||
"igst_account": "Output Tax IGST - _TC",
|
||||
})
|
||||
|
||||
gst_settings.save()
|
||||
|
||||
si = create_sales_invoice(do_not_save=1, rate='60000')
|
||||
|
||||
si.distance = 2000
|
||||
si.company_address = "_Test Address for Eway bill-Billing"
|
||||
si.customer_address = "_Test Customer-Address for Eway bill-Billing"
|
||||
si.shipping_address_name = "_Test Customer-Address for Eway bill-Shipping"
|
||||
si.dispatch_address_name = "_Test Dispatch-Address for Eway bill-Shipping"
|
||||
si.vehicle_no = "KA12KA1234"
|
||||
si.gst_category = "Registered Regular"
|
||||
si.mode_of_transport = 'Road'
|
||||
si.transporter = '_Test Transporter'
|
||||
|
||||
si.append("taxes", {
|
||||
"charge_type": "On Net Total",
|
||||
"account_head": "Output Tax CGST - _TC",
|
||||
"cost_center": "Main - _TC",
|
||||
"description": "CGST @ 9.0",
|
||||
"rate": 9
|
||||
})
|
||||
|
||||
si.append("taxes", {
|
||||
"charge_type": "On Net Total",
|
||||
"account_head": "Output Tax SGST - _TC",
|
||||
"cost_center": "Main - _TC",
|
||||
"description": "SGST @ 9.0",
|
||||
"rate": 9
|
||||
})
|
||||
|
||||
return si
|
||||
|
||||
def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
|
||||
gl_entries = frappe.db.sql("""select account, debit, credit, posting_date
|
||||
from `tabGL Entry`
|
||||
@ -2778,7 +2518,6 @@ def create_sales_invoice(**args):
|
||||
"item_code": args.item or args.item_code or "_Test Item",
|
||||
"item_name": args.item_name or "_Test Item",
|
||||
"description": args.description or "_Test Item",
|
||||
"gst_hsn_code": "999800",
|
||||
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
||||
"qty": args.qty or 1,
|
||||
"uom": args.uom or "Nos",
|
||||
@ -2827,7 +2566,6 @@ def create_sales_invoice_against_cost_center(**args):
|
||||
|
||||
si.append("items", {
|
||||
"item_code": args.item or args.item_code or "_Test Item",
|
||||
"gst_hsn_code": "999800",
|
||||
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
||||
"qty": args.qty or 1,
|
||||
"rate": args.rate or 100,
|
||||
|
@ -1,173 +0,0 @@
|
||||
{%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value -%}
|
||||
{%- set einvoice = json.loads(doc.signed_einvoice) -%}
|
||||
|
||||
<div class="page-break">
|
||||
<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
|
||||
{% if letter_head and not no_letterhead %}
|
||||
<div class="letter-head">{{ letter_head }}</div>
|
||||
{% endif %}
|
||||
<div class="print-heading">
|
||||
<h2>E Invoice<br><small>{{ doc.name }}</small></h2>
|
||||
</div>
|
||||
</div>
|
||||
{% if print_settings.repeat_header_footer %}
|
||||
<div id="footer-html" class="visible-pdf">
|
||||
{% if not no_letterhead and footer %}
|
||||
<div class="letter-head-footer">
|
||||
{{ footer }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<p class="text-center small page-number visible-pdf">
|
||||
{{ _("Page {0} of {1}").format('<span class="page"></span>', '<span class="topage"></span>') }}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
<h5 class="font-bold" style="margin-top: 0px;">1. Transaction Details</h5>
|
||||
<div class="row section-break" style="border-bottom: 1px solid #d1d8dd; padding-bottom: 10px;">
|
||||
<div class="col-xs-8 column-break">
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-4"><label>IRN</label></div>
|
||||
<div class="col-xs-8 value">{{ einvoice.Irn }}</div>
|
||||
</div>
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-4"><label>Ack. No</label></div>
|
||||
<div class="col-xs-8 value">{{ einvoice.AckNo }}</div>
|
||||
</div>
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-4"><label>Ack. Date</label></div>
|
||||
<div class="col-xs-8 value">{{ frappe.utils.format_datetime(einvoice.AckDt, "dd/MM/yyyy hh:mm:ss") }}</div>
|
||||
</div>
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-4"><label>Category</label></div>
|
||||
<div class="col-xs-8 value">{{ einvoice.TranDtls.SupTyp }}</div>
|
||||
</div>
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-4"><label>Document Type</label></div>
|
||||
<div class="col-xs-8 value">{{ einvoice.DocDtls.Typ }}</div>
|
||||
</div>
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-4"><label>Document No</label></div>
|
||||
<div class="col-xs-8 value">{{ einvoice.DocDtls.No }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4 column-break">
|
||||
<img src="{{ doc.qrcode_image }}" width="175px" style="float: right;">
|
||||
</div>
|
||||
</div>
|
||||
<h5 class="font-bold" style="margin-top: 15px; margin-bottom: 10px;">2. Party Details</h5>
|
||||
<div class="row section-break" style="border-bottom: 1px solid #d1d8dd; padding-bottom: 10px;">
|
||||
{%- set seller = einvoice.SellerDtls -%}
|
||||
<div class="col-xs-6 column-break">
|
||||
<h5 style="margin-bottom: 5px;">Seller</h5>
|
||||
<p>{{ seller.Gstin }}</p>
|
||||
<p>{{ seller.LglNm }}</p>
|
||||
<p>{{ seller.Addr1 }}</p>
|
||||
{%- if seller.Addr2 -%} <p>{{ seller.Addr2 }}</p> {% endif %}
|
||||
<p>{{ seller.Loc }}</p>
|
||||
<p>{{ frappe.db.get_value("Address", doc.company_address, "gst_state") }} - {{ seller.Pin }}</p>
|
||||
|
||||
{%- if einvoice.ShipDtls -%}
|
||||
{%- set shipping = einvoice.ShipDtls -%}
|
||||
<h5 style="margin-bottom: 5px;">Shipped From</h5>
|
||||
<p>{{ shipping.Gstin }}</p>
|
||||
<p>{{ shipping.LglNm }}</p>
|
||||
<p>{{ shipping.Addr1 }}</p>
|
||||
{%- if shipping.Addr2 -%} <p>{{ shipping.Addr2 }}</p> {% endif %}
|
||||
<p>{{ shipping.Loc }}</p>
|
||||
<p>{{ frappe.db.get_value("Address", doc.shipping_address_name, "gst_state") }} - {{ shipping.Pin }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{%- set buyer = einvoice.BuyerDtls -%}
|
||||
<div class="col-xs-6 column-break">
|
||||
<h5 style="margin-bottom: 5px;">Buyer</h5>
|
||||
<p>{{ buyer.Gstin }}</p>
|
||||
<p>{{ buyer.LglNm }}</p>
|
||||
<p>{{ buyer.Addr1 }}</p>
|
||||
{%- if buyer.Addr2 -%} <p>{{ buyer.Addr2 }}</p> {% endif %}
|
||||
<p>{{ buyer.Loc }}</p>
|
||||
<p>{{ frappe.db.get_value("Address", doc.customer_address, "gst_state") }} - {{ buyer.Pin }}</p>
|
||||
|
||||
{%- if einvoice.DispDtls -%}
|
||||
{%- set dispatch = einvoice.DispDtls -%}
|
||||
<h5 style="margin-bottom: 5px;">Dispatched From</h5>
|
||||
{%- if dispatch.Gstin -%} <p>{{ dispatch.Gstin }}</p> {% endif %}
|
||||
<p>{{ dispatch.LglNm }}</p>
|
||||
<p>{{ dispatch.Addr1 }}</p>
|
||||
{%- if dispatch.Addr2 -%} <p>{{ dispatch.Addr2 }}</p> {% endif %}
|
||||
<p>{{ dispatch.Loc }}</p>
|
||||
<p>{{ frappe.db.get_value("Address", doc.dispatch_address_name, "gst_state") }} - {{ dispatch.Pin }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div style="overflow-x: auto;">
|
||||
<h5 class="font-bold" style="margin-top: 15px; margin-bottom: 10px;">3. Item Details</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left" style="width: 3%;">Sr. No.</th>
|
||||
<th class="text-left">Item</th>
|
||||
<th class="text-left" style="width: 10%;">HSN Code</th>
|
||||
<th class="text-left" style="width: 5%;">Qty</th>
|
||||
<th class="text-left" style="width: 5%;">UOM</th>
|
||||
<th class="text-left">Rate</th>
|
||||
<th class="text-left" style="width: 5%;">Discount</th>
|
||||
<th class="text-left">Taxable Amount</th>
|
||||
<th class="text-left" style="width: 7%;">Tax Rate</th>
|
||||
<th class="text-left" style="width: 5%;">Other Charges</th>
|
||||
<th class="text-left">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in einvoice.ItemList %}
|
||||
<tr>
|
||||
<td class="text-left" style="width: 3%;">{{ item.SlNo }}</td>
|
||||
<td class="text-left">{{ item.PrdDesc }}</td>
|
||||
<td class="text-left" style="width: 10%;">{{ item.HsnCd }}</td>
|
||||
<td class="text-right" style="width: 5%;">{{ item.Qty }}</td>
|
||||
<td class="text-left" style="width: 5%;">{{ item.Unit }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(item.UnitPrice, None, "INR") }}</td>
|
||||
<td class="text-right" style="width: 5%;">{{ frappe.utils.fmt_money(item.Discount, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(item.AssAmt, None, "INR") }}</td>
|
||||
<td class="text-right" style="width: 7%;">{{ item.GstRt + item.CesRt }} %</td>
|
||||
<td class="text-right" style="width: 5%;">{{ frappe.utils.fmt_money(0, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(item.TotItemVal, None, "INR") }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div style="overflow-x: auto;">
|
||||
<h5 class="font-bold" style="margin-bottom: 0px;">4. Value Details</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left">Taxable Amount</th>
|
||||
<th class="text-left">CGST</th>
|
||||
<th class="text-left"">SGST</th>
|
||||
<th class="text-left">IGST</th>
|
||||
<th class="text-left">CESS</th>
|
||||
<th class="text-left" style="width: 10%;">State CESS</th>
|
||||
<th class="text-left">Discount</th>
|
||||
<th class="text-left" style="width: 10%;">Other Charges</th>
|
||||
<th class="text-left" style="width: 10%;">Round Off</th>
|
||||
<th class="text-left">Total Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- set value_details = einvoice.ValDtls -%}
|
||||
<tr>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(value_details.AssVal, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(value_details.CgstVal, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(value_details.SgstVal, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(value_details.IgstVal, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(value_details.CesVal, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(0, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(value_details.Discount, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(value_details.OthChrg, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(value_details.RndOffAmt, None, "INR") }}</td>
|
||||
<td class="text-right">{{ frappe.utils.fmt_money(value_details.TotInvVal, None, "INR") }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
@ -1,24 +0,0 @@
|
||||
{
|
||||
"align_labels_right": 1,
|
||||
"creation": "2020-10-10 18:01:21.032914",
|
||||
"custom_format": 0,
|
||||
"default_print_language": "en-US",
|
||||
"disabled": 1,
|
||||
"doc_type": "Sales Invoice",
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Format",
|
||||
"font": "Default",
|
||||
"html": "",
|
||||
"idx": 0,
|
||||
"line_breaks": 1,
|
||||
"modified": "2020-10-23 19:54:40.634936",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GST E-Invoice",
|
||||
"owner": "Administrator",
|
||||
"print_format_builder": 0,
|
||||
"print_format_type": "Jinja",
|
||||
"raw_printing": 0,
|
||||
"show_section_headings": 1,
|
||||
"standard": "Yes"
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -5,7 +5,7 @@
|
||||
"label": "Profit and Loss"
|
||||
}
|
||||
],
|
||||
"content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"General Ledger\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Receivable\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Payable\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Bank Statement\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Goods and Services Tax (GST India)\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Taxes\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}}]",
|
||||
"content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"General Ledger\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Receivable\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Payable\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Bank Statement\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Taxes\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}}]",
|
||||
"creation": "2020-03-02 15:41:59.515192",
|
||||
"docstatus": 0,
|
||||
"doctype": "Workspace",
|
||||
@ -789,147 +789,6 @@
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Goods and Services Tax (GST India)",
|
||||
"link_count": 0,
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "GST Settings",
|
||||
"link_count": 0,
|
||||
"link_to": "GST Settings",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "GST HSN Code",
|
||||
"link_count": 0,
|
||||
"link_to": "GST HSN Code",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "GSTR-1",
|
||||
"link_count": 0,
|
||||
"link_to": "GSTR-1",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "GSTR-2",
|
||||
"link_count": 0,
|
||||
"link_to": "GSTR-2",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "GSTR 3B Report",
|
||||
"link_count": 0,
|
||||
"link_to": "GSTR 3B Report",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "GST Sales Register",
|
||||
"link_count": 0,
|
||||
"link_to": "GST Sales Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "GST Purchase Register",
|
||||
"link_count": 0,
|
||||
"link_to": "GST Purchase Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "GST Itemised Sales Register",
|
||||
"link_count": 0,
|
||||
"link_to": "GST Itemised Sales Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "GST Itemised Purchase Register",
|
||||
"link_count": 0,
|
||||
"link_to": "GST Itemised Purchase Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "C-Form",
|
||||
"link_count": 0,
|
||||
"link_to": "C-Form",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Lower Deduction Certificate",
|
||||
"link_count": 0,
|
||||
"link_to": "Lower Deduction Certificate",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"only_for": "India",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
@ -1235,7 +1094,7 @@
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2022-01-13 17:25:09.835345",
|
||||
"modified": "2022-02-19 06:22:18.091827",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting",
|
||||
|
@ -629,45 +629,6 @@ class TestDepreciationMethods(AssetSetup):
|
||||
|
||||
self.assertEqual(schedules, expected_schedules)
|
||||
|
||||
def test_discounted_wdv_depreciation_rate_for_indian_region(self):
|
||||
# set indian company
|
||||
company_flag = frappe.flags.company
|
||||
frappe.flags.company = "_Test Company"
|
||||
|
||||
finance_book = frappe.new_doc("Finance Book")
|
||||
finance_book.finance_book_name = "Income Tax"
|
||||
finance_book.for_income_tax = 1
|
||||
finance_book.insert(ignore_if_duplicate = True)
|
||||
|
||||
asset = create_asset(
|
||||
calculate_depreciation = 1,
|
||||
available_for_use_date = "2030-07-12",
|
||||
purchase_date = "2030-01-01",
|
||||
finance_book = finance_book.name,
|
||||
depreciation_method = "Written Down Value",
|
||||
expected_value_after_useful_life = 12500,
|
||||
depreciation_start_date = "2030-12-31",
|
||||
total_number_of_depreciations = 3,
|
||||
frequency_of_depreciation = 12
|
||||
)
|
||||
|
||||
self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0)
|
||||
|
||||
expected_schedules = [
|
||||
["2030-12-31", 11849.32, 11849.32],
|
||||
["2031-12-31", 44075.34, 55924.66],
|
||||
["2032-12-31", 22037.67, 77962.33],
|
||||
["2033-07-12", 9537.67, 87500.0]
|
||||
]
|
||||
|
||||
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
|
||||
for d in asset.get("schedules")]
|
||||
|
||||
self.assertEqual(schedules, expected_schedules)
|
||||
|
||||
# reset indian company
|
||||
frappe.flags.company = company_flag
|
||||
|
||||
class TestDepreciationBasics(AssetSetup):
|
||||
def test_depreciation_without_pro_rata(self):
|
||||
asset = create_asset(
|
||||
|
@ -12,9 +12,6 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
)
|
||||
from erpnext.assets.doctype.asset.asset import get_depreciation_amount
|
||||
from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
|
||||
from erpnext.regional.india.utils import (
|
||||
get_depreciation_amount as get_depreciation_amount_for_india,
|
||||
)
|
||||
|
||||
|
||||
class AssetValueAdjustment(Document):
|
||||
@ -115,9 +112,6 @@ class AssetValueAdjustment(Document):
|
||||
days = date_diff(data.schedule_date, from_date)
|
||||
depreciation_amount = days * rate_per_day
|
||||
from_date = data.schedule_date
|
||||
else:
|
||||
if country == "India":
|
||||
depreciation_amount = get_depreciation_amount_for_india(asset, value_after_depreciation, d)
|
||||
else:
|
||||
depreciation_amount = get_depreciation_amount(asset, value_after_depreciation, d)
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
{% include "erpnext/regional/india/taxes.js" %}
|
||||
|
||||
erpnext.setup_auto_gst_taxation('Purchase Order');
|
@ -1,3 +0,0 @@
|
||||
{% include "erpnext/regional/india/party.js" %}
|
||||
|
||||
erpnext.setup_gst_reminder_button('Supplier');
|
@ -239,9 +239,6 @@ doc_events = {
|
||||
"Sales Taxes and Charges Template": {
|
||||
"on_update": "erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings.validate_cart_settings"
|
||||
},
|
||||
"Tax Category": {
|
||||
"validate": "erpnext.regional.india.utils.validate_tax_category"
|
||||
},
|
||||
"Sales Invoice": {
|
||||
"on_submit": [
|
||||
"erpnext.regional.create_transaction_log",
|
||||
@ -255,41 +252,25 @@ doc_events = {
|
||||
"erpnext.regional.saudi_arabia.utils.delete_qr_code_file"
|
||||
],
|
||||
"on_trash": "erpnext.regional.check_deletion_permission",
|
||||
"validate": [
|
||||
"erpnext.regional.india.utils.validate_document_name",
|
||||
"erpnext.regional.india.utils.update_taxable_values"
|
||||
]
|
||||
},
|
||||
"POS Invoice": {
|
||||
"on_submit": ["erpnext.regional.saudi_arabia.utils.create_qr_code"]
|
||||
},
|
||||
"Purchase Invoice": {
|
||||
"validate": [
|
||||
"erpnext.regional.india.utils.validate_reverse_charge_transaction",
|
||||
"erpnext.regional.india.utils.update_itc_availed_fields",
|
||||
"erpnext.regional.united_arab_emirates.utils.update_grand_total_for_rcm",
|
||||
"erpnext.regional.united_arab_emirates.utils.validate_returns",
|
||||
"erpnext.regional.india.utils.update_taxable_values"
|
||||
]
|
||||
},
|
||||
"Payment Entry": {
|
||||
"validate": "erpnext.regional.india.utils.update_place_of_supply",
|
||||
"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status", "erpnext.accounts.doctype.dunning.dunning.resolve_dunning"],
|
||||
"on_trash": "erpnext.regional.check_deletion_permission"
|
||||
},
|
||||
'Address': {
|
||||
'validate': [
|
||||
'erpnext.regional.india.utils.validate_gstin_for_india',
|
||||
'erpnext.regional.italy.utils.set_state_code',
|
||||
'erpnext.regional.india.utils.update_gst_category',
|
||||
],
|
||||
},
|
||||
'Supplier': {
|
||||
'validate': 'erpnext.regional.india.utils.validate_pan_for_india'
|
||||
},
|
||||
('Sales Invoice', 'Sales Order', 'Delivery Note', 'Purchase Invoice', 'Purchase Order', 'Purchase Receipt'): {
|
||||
'validate': ['erpnext.regional.india.utils.set_place_of_supply']
|
||||
},
|
||||
"Contact": {
|
||||
"on_trash": "erpnext.support.doctype.issue.issue.update_issue",
|
||||
"after_insert": "erpnext.telephony.doctype.call_log.call_log.link_existing_conversations",
|
||||
@ -302,8 +283,7 @@ doc_events = {
|
||||
'validate': ["erpnext.erpnext_integrations.taxjar_integration.set_sales_tax"]
|
||||
},
|
||||
"Company": {
|
||||
"on_trash": ["erpnext.regional.india.utils.delete_gst_settings_for_company",
|
||||
"erpnext.regional.saudi_arabia.utils.delete_vat_settings_for_company"]
|
||||
"on_trash": ["erpnext.regional.saudi_arabia.utils.delete_vat_settings_for_company"]
|
||||
},
|
||||
"Integration Request": {
|
||||
"validate": "erpnext.accounts.doctype.payment_request.payment_request.validate_payment"
|
||||
@ -432,18 +412,6 @@ regional_overrides = {
|
||||
'France': {
|
||||
'erpnext.tests.test_regional.test_method': 'erpnext.regional.france.utils.test_method'
|
||||
},
|
||||
'India': {
|
||||
'erpnext.tests.test_regional.test_method': 'erpnext.regional.india.utils.test_method',
|
||||
'erpnext.controllers.taxes_and_totals.get_itemised_tax_breakup_header': 'erpnext.regional.india.utils.get_itemised_tax_breakup_header',
|
||||
'erpnext.controllers.taxes_and_totals.get_itemised_tax_breakup_data': 'erpnext.regional.india.utils.get_itemised_tax_breakup_data',
|
||||
'erpnext.accounts.party.get_regional_address_details': 'erpnext.regional.india.utils.get_regional_address_details',
|
||||
'erpnext.controllers.taxes_and_totals.get_regional_round_off_accounts': 'erpnext.regional.india.utils.get_regional_round_off_accounts',
|
||||
'erpnext.hr.utils.calculate_annual_eligible_hra_exemption': 'erpnext.regional.india.utils.calculate_annual_eligible_hra_exemption',
|
||||
'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period',
|
||||
'erpnext.controllers.accounts_controller.validate_einvoice_fields': 'erpnext.regional.india.e_invoice.utils.validate_einvoice_fields',
|
||||
'erpnext.assets.doctype.asset.asset.get_depreciation_amount': 'erpnext.regional.india.utils.get_depreciation_amount',
|
||||
'erpnext.stock.doctype.item.item.set_item_tax_from_hsn_code': 'erpnext.regional.india.utils.set_item_tax_from_hsn_code'
|
||||
},
|
||||
'United Arab Emirates': {
|
||||
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data',
|
||||
'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_regional_gl_entries': 'erpnext.regional.united_arab_emirates.utils.make_regional_gl_entries',
|
||||
|
@ -12,7 +12,6 @@ doctype_series_map = {
|
||||
'Attendance': 'HR-ATT-.YYYY.-',
|
||||
'Auto Repeat': 'SYS-ARP-.YYYY.-',
|
||||
'Blanket Order': 'MFG-BLR-.YYYY.-',
|
||||
'C-Form': 'ACC-CF-.YYYY.-',
|
||||
'Campaign': 'SAL-CAM-.YYYY.-',
|
||||
'Course Schedule': 'EDU-CSH-.YYYY.-',
|
||||
'Customer': 'CUST-.YYYY.-',
|
||||
|
@ -5,8 +5,6 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
import erpnext
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
data = get_data(filters)
|
||||
@ -31,14 +29,6 @@ def get_columns(filters):
|
||||
"width": 160
|
||||
}]
|
||||
|
||||
if erpnext.get_region() == "India":
|
||||
columns.append({
|
||||
"label": _("PAN Number"),
|
||||
"fieldname": "pan_number",
|
||||
"fieldtype": "Data",
|
||||
"width": 140
|
||||
})
|
||||
|
||||
columns += [{
|
||||
"label": _("Income Tax Component"),
|
||||
"fieldname": "it_comp",
|
||||
@ -94,9 +84,6 @@ def get_data(filters):
|
||||
|
||||
data = []
|
||||
|
||||
if erpnext.get_region() == "India":
|
||||
employee_pan_dict = frappe._dict(frappe.db.sql(""" select employee, pan_number from `tabEmployee`"""))
|
||||
|
||||
component_types = frappe.db.sql(""" select name from `tabSalary Component`
|
||||
where is_income_tax_component = 1 """)
|
||||
|
||||
@ -117,20 +104,13 @@ def get_data(filters):
|
||||
""" % (conditions , ", ".join(['%s']*len(component_types))), tuple(component_types), as_dict=1)
|
||||
|
||||
for d in entry:
|
||||
|
||||
employee = {
|
||||
data.append({
|
||||
"employee": d.employee,
|
||||
"employee_name": d.employee_name,
|
||||
"it_comp": d.salary_component,
|
||||
"posting_date": d.posting_date,
|
||||
# "pan_number": employee_pan_dict.get(d.employee),
|
||||
"it_amount": d.amount,
|
||||
"gross_pay": d.gross_pay
|
||||
}
|
||||
|
||||
if erpnext.get_region() == "India":
|
||||
employee["pan_number"] = employee_pan_dict.get(d.employee)
|
||||
|
||||
data.append(employee)
|
||||
})
|
||||
|
||||
return data
|
||||
|
@ -1,8 +0,0 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('E Invoice Request Log', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
@ -1,102 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "EINV-REQ-.#####",
|
||||
"creation": "2020-12-08 12:54:08.175992",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"user",
|
||||
"url",
|
||||
"headers",
|
||||
"response",
|
||||
"column_break_7",
|
||||
"timestamp",
|
||||
"reference_invoice",
|
||||
"data"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"label": "User",
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"fieldname": "reference_invoice",
|
||||
"fieldtype": "Data",
|
||||
"label": "Reference Invoice"
|
||||
},
|
||||
{
|
||||
"fieldname": "headers",
|
||||
"fieldtype": "Code",
|
||||
"label": "Headers",
|
||||
"options": "JSON"
|
||||
},
|
||||
{
|
||||
"fieldname": "data",
|
||||
"fieldtype": "Code",
|
||||
"label": "Data",
|
||||
"options": "JSON"
|
||||
},
|
||||
{
|
||||
"default": "Now",
|
||||
"fieldname": "timestamp",
|
||||
"fieldtype": "Datetime",
|
||||
"label": "Timestamp"
|
||||
},
|
||||
{
|
||||
"fieldname": "response",
|
||||
"fieldtype": "Code",
|
||||
"label": "Response",
|
||||
"options": "JSON"
|
||||
},
|
||||
{
|
||||
"fieldname": "url",
|
||||
"fieldtype": "Data",
|
||||
"label": "URL"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-01-13 12:06:57.253111",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "E Invoice Request Log",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"share": 1
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"share": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class EInvoiceRequestLog(Document):
|
||||
pass
|
@ -1,11 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
|
||||
class TestEInvoiceRequestLog(unittest.TestCase):
|
||||
pass
|
@ -1,11 +0,0 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('E Invoice Settings', {
|
||||
refresh(frm) {
|
||||
const docs_link = 'https://docs.erpnext.com/docs/v13/user/manual/en/regional/india/setup-e-invoicing';
|
||||
frm.dashboard.set_headline(
|
||||
__("Read {0} for more information on E Invoicing features.", [`<a href='${docs_link}'>documentation</a>`])
|
||||
);
|
||||
}
|
||||
});
|
@ -1,97 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-09-24 16:23:16.235722",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"enable",
|
||||
"section_break_2",
|
||||
"sandbox_mode",
|
||||
"applicable_from",
|
||||
"credentials",
|
||||
"advanced_settings_section",
|
||||
"client_id",
|
||||
"column_break_8",
|
||||
"client_secret",
|
||||
"auth_token",
|
||||
"token_expiry"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "enable",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable"
|
||||
},
|
||||
{
|
||||
"depends_on": "enable",
|
||||
"fieldname": "section_break_2",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "auth_token",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "token_expiry",
|
||||
"fieldtype": "Datetime",
|
||||
"hidden": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "credentials",
|
||||
"fieldtype": "Table",
|
||||
"label": "Credentials",
|
||||
"mandatory_depends_on": "enable",
|
||||
"options": "E Invoice User"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "sandbox_mode",
|
||||
"fieldtype": "Check",
|
||||
"label": "Sandbox Mode"
|
||||
},
|
||||
{
|
||||
"fieldname": "applicable_from",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Applicable From",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "advanced_settings_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Advanced Settings"
|
||||
},
|
||||
{
|
||||
"fieldname": "client_id",
|
||||
"fieldtype": "Data",
|
||||
"label": "Client ID"
|
||||
},
|
||||
{
|
||||
"fieldname": "client_secret",
|
||||
"fieldtype": "Password",
|
||||
"label": "Client Secret"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_8",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-11-16 19:50:28.029517",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "E Invoice Settings",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class EInvoiceSettings(Document):
|
||||
def validate(self):
|
||||
if self.enable and not self.credentials:
|
||||
frappe.throw(_('You must add atleast one credentials to be able to use E Invoicing.'))
|
@ -1,11 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
|
||||
class TestEInvoiceSettings(unittest.TestCase):
|
||||
pass
|
@ -1,57 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-12-22 15:02:46.229474",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"company",
|
||||
"gstin",
|
||||
"username",
|
||||
"password"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "gstin",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "GSTIN",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "username",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Username",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "password",
|
||||
"fieldtype": "Password",
|
||||
"in_list_view": 1,
|
||||
"label": "Password",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-03-22 12:16:56.365616",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "E Invoice User",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class EInvoiceUser(Document):
|
||||
pass
|
@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('GST HSN Code', {
|
||||
refresh: function(frm) {
|
||||
if(! frm.doc.__islocal && frm.doc.taxes.length){
|
||||
frm.add_custom_button(__('Update Taxes for Items'), function(){
|
||||
frappe.confirm(
|
||||
'Are you sure? It will overwrite taxes for all items with HSN Code <b>'+frm.doc.name+'</b>.',
|
||||
function(){
|
||||
frappe.call({
|
||||
args:{
|
||||
taxes: frm.doc.taxes,
|
||||
hsn_code: frm.doc.name
|
||||
},
|
||||
method: 'erpnext.regional.doctype.gst_hsn_code.gst_hsn_code.update_taxes_in_item_master',
|
||||
callback: function(r) {
|
||||
if(r.message){
|
||||
frappe.show_alert(__('Item taxes updated'));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
@ -1,46 +0,0 @@
|
||||
{
|
||||
"autoname": "field:hsn_code",
|
||||
"creation": "2017-06-21 10:48:56.422086",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"hsn_code",
|
||||
"description",
|
||||
"taxes"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "hsn_code",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "HSN Code",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Description"
|
||||
},
|
||||
{
|
||||
"fieldname": "taxes",
|
||||
"fieldtype": "Table",
|
||||
"label": "Taxes",
|
||||
"options": "Item Tax"
|
||||
}
|
||||
],
|
||||
"modified": "2019-11-01 11:18:59.556931",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "GST HSN Code",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"search_fields": "hsn_code, description",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "hsn_code",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class GSTHSNCode(Document):
|
||||
pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_taxes_in_item_master(taxes, hsn_code):
|
||||
items = frappe.get_list("Item", filters={
|
||||
'gst_hsn_code': hsn_code
|
||||
})
|
||||
|
||||
taxes = frappe.parse_json(taxes)
|
||||
frappe.enqueue(update_item_document, items=items, taxes=taxes)
|
||||
return 1
|
||||
|
||||
def update_item_document(items, taxes):
|
||||
for item in items:
|
||||
item_to_be_updated=frappe.get_doc("Item", item.name)
|
||||
item_to_be_updated.taxes = []
|
||||
for tax in taxes:
|
||||
tax = frappe._dict(tax)
|
||||
item_to_be_updated.append("taxes", {
|
||||
'item_tax_template': tax.item_tax_template,
|
||||
'tax_category': tax.tax_category,
|
||||
'valid_from': tax.valid_from
|
||||
})
|
||||
item_to_be_updated.save()
|
@ -1,8 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class TestGSTHSNCode(unittest.TestCase):
|
||||
pass
|
@ -1,44 +0,0 @@
|
||||
// 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>`
|
||||
);
|
||||
},
|
||||
|
||||
setup: function(frm) {
|
||||
$.each(["cgst_account", "sgst_account", "igst_account", "cess_account"], function(i, field) {
|
||||
frm.events.filter_accounts(frm, field);
|
||||
});
|
||||
},
|
||||
|
||||
filter_accounts: function(frm, account_field) {
|
||||
frm.set_query(account_field, "gst_accounts", function(doc, cdt, cdn) {
|
||||
var row = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
company: row.company,
|
||||
account_type: "Tax",
|
||||
is_group: 0
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
@ -1,85 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2017-06-27 15:09:01.318003",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"gst_summary",
|
||||
"gst_tax_settings_section",
|
||||
"round_off_gst_values",
|
||||
"column_break_4",
|
||||
"hsn_wise_tax_breakup",
|
||||
"gstin_email_sent_on",
|
||||
"section_break_4",
|
||||
"gst_accounts",
|
||||
"b2c_limit"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "gst_summary",
|
||||
"fieldtype": "HTML",
|
||||
"label": "GST Summary"
|
||||
},
|
||||
{
|
||||
"fieldname": "gstin_email_sent_on",
|
||||
"fieldtype": "Date",
|
||||
"label": "GSTIN Email Sent On",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "gst_accounts",
|
||||
"fieldtype": "Table",
|
||||
"label": "GST Accounts",
|
||||
"options": "GST Account"
|
||||
},
|
||||
{
|
||||
"default": "250000",
|
||||
"description": "Set Invoice Value for B2C. B2CL and B2CS calculated based on this invoice value.",
|
||||
"fieldname": "b2c_limit",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "B2C Limit",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Enabling this option will round off individual GST components in all the Invoices",
|
||||
"fieldname": "round_off_gst_values",
|
||||
"fieldtype": "Check",
|
||||
"label": "Round Off GST Values"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "hsn_wise_tax_breakup",
|
||||
"fieldtype": "Check",
|
||||
"label": "Tax Breakup Table Based On HSN Code"
|
||||
},
|
||||
{
|
||||
"fieldname": "gst_tax_settings_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "GST Tax Settings"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-10-11 18:10:14.242614",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "GST Settings",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
import os
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.contacts.doctype.contact.contact import get_default_contact
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import date_diff, get_url, nowdate
|
||||
|
||||
|
||||
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)
|
||||
|
||||
def validate(self):
|
||||
# Validate duplicate accounts
|
||||
self.validate_duplicate_accounts()
|
||||
|
||||
def validate_duplicate_accounts(self):
|
||||
account_list = []
|
||||
for account in self.get('gst_accounts'):
|
||||
for fieldname in ['cgst_account', 'sgst_account', 'igst_account', 'cess_account']:
|
||||
if account.get(fieldname) in account_list:
|
||||
frappe.throw(_("Account {0} appears multiple times").format(
|
||||
frappe.bold(account.get(fieldname))))
|
||||
|
||||
if account.get(fieldname):
|
||||
account_list.append(account.get(fieldname))
|
||||
|
||||
@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'), exc=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 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
|
@ -1,8 +0,0 @@
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class TestGSTSettings(unittest.TestCase):
|
||||
pass
|
@ -1,297 +0,0 @@
|
||||
<style>
|
||||
.print-format {
|
||||
padding: 15mm;
|
||||
font-size: 8.0pt !important;
|
||||
font-family: Tahoma, sans-serif;
|
||||
}
|
||||
.disabled {
|
||||
background-color: #d9d9d9;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div>
|
||||
<h3 class="text-center">{{ __("GSTR3B-Form")}}</h3>
|
||||
<h5>{{__("GSTIN")}}:   {{ data.gstin }}</h5>
|
||||
<h5>{{__("Period")}}:   {{ data.ret_period }}</h5>
|
||||
</div>
|
||||
|
||||
<h5>3.1  {{__("Details of Outward Supplies and inward supplies liable to reverse charge")}}</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{__("Nature Of Supplies")}}</th>
|
||||
<th>{{__("Total Taxable value")}}</th>
|
||||
<th>{{__("Integrated Tax")}}</th>
|
||||
<th>{{__("Central Tax")}}</th>
|
||||
<th>{{__("State/UT Tax")}}</th>
|
||||
<th>{{__("Cess")}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>(a) {{__("Outward taxable supplies(other than zero rated, nil rated and exempted)")}}</td>
|
||||
<td class="right">{{ flt(data.sup_details.osup_det.txval, 2) }}</td>
|
||||
<td class="right">{{ flt(data.sup_details.osup_det.iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.sup_details.osup_det.camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.sup_details.osup_det.samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.sup_details.osup_det.csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(b) {{__("Outward taxable supplies(zero rated)")}}</td>
|
||||
<td class="right">{{ flt(data.sup_details.osup_zero.txval, 2) }}</td>
|
||||
<td class="right">{{ flt(data.sup_details.osup_zero.iamt, 2) }}</td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<td class="right">{{ flt(data.sup_details.osup_zero.csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(b) {{__("Other outward supplies(Nil rated,Exempted)")}}</td>
|
||||
<td class="right">{{ data.sup_details.osup_nil_exmp.txval }}</td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<tr>
|
||||
<td>(d) {{__("Inward Supplies(liable to reverse charge)")}}</td>
|
||||
<td class="right">{{ flt(data.sup_details.isup_rev.txval, 2) }}</td>
|
||||
<td class="right">{{ flt(data.sup_details.isup_rev.iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.sup_details.isup_rev.camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.sup_details.isup_rev.samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.sup_details.isup_rev.csamt,2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(e) {{__("Non-GST outward supplies")}}</td>
|
||||
<td class="right">{{ data.sup_details.osup_nongst.txval }}</td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5>
|
||||
3.2  {{__("Of the supplies shown in 3.1 (a) above, details of inter-State supplies made to unregisterd
|
||||
persons, composition taxable persons and UIN holders")}}
|
||||
</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{{__("Place Of Supply (State/UT)")}}</th>
|
||||
<th>{{__("Total Taxable Value")}}</th>
|
||||
<th>{{__("Amount of Integrated Tax")}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{__("Supplies made to Unregistered Persons")}}</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.unreg_details %}
|
||||
{% if row %}
|
||||
{{ row.pos }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.unreg_details %}
|
||||
{% if row %}
|
||||
{{ flt(row.txval, 2) }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.unreg_details %}
|
||||
{% if row %}
|
||||
{{ flt(row.iamt, 2) }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{__("Supplies made to Composition Taxable Persons")}}</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.comp_details %}
|
||||
{% if row %}
|
||||
{{ row.pos }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.comp_details %}
|
||||
{% if row %}
|
||||
{{ flt(row.txval, 2) }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.comp_details %}
|
||||
{% if row %}
|
||||
{{ flt(row.iamt, 2) }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{__("Supplies made to UIN holders")}}</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.uin_details %}
|
||||
{% if row %}
|
||||
{{ row.pos }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.uin_details %}
|
||||
{% if row %}
|
||||
{{ flt(row.txval, 2) }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.uin_details %}
|
||||
{% if row %}
|
||||
{{ flt(row.iamt, 2) }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5>4.   {{__("Eligible ITC")}}</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<th>Integrated Tax</th>
|
||||
<th>Central Tax</th>
|
||||
<th>State/UT tax</th>
|
||||
<th>Cess</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>(A) {{__("ITC Available (whether in full or part)")}}</b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (1) {{__("Import of goods")}} </td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[0].iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[0].camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[0].samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[0].csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (2) {{__("Import of services")}}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[1].iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[1].camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[1].samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[1].csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (3) {{__("Inward supplies liable to reverse charge (other than 1 & 2 above)")}}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[2].iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[2].camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[2].samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[2].csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (4) {{__("Inward supplies from ISD")}}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[3].iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[3].camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[3].samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[3].csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (5) {{__("All other ITC")}}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[4].iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[4].camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[4].samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_avl[4].csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>(B) {{__("ITC Reversed")}}</b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (1) {{__("As per rules 42 & 43 of CGST Rules")}}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_rev[0].iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_rev[0].camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_rev[0].samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_rev[0].csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (2) {{__("Others")}}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_rev[1].iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_rev[1].camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_rev[1].samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_rev[1].csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>(C) {{__("Net ITC Available(A) - (B)")}}</b></td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_net.iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_net.camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_net.samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_net.csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>(D) {{__("Ineligible ITC")}}</b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (1) {{__("As per section 17(5)")}}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_inelg[0].iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_inelg[0].camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_inelg[0].samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_inelg[0].csamt, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (2) {{__("Others")}}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_inelg[1].iamt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_inelg[1].camt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_inelg[1].samt, 2) }}</td>
|
||||
<td class="right">{{ flt(data.itc_elg.itc_inelg[1].csamt, 2) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5>5.    {{__("Values of exempt, nil rated and non-GST inward supplies")}}</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{__("Nature of Supplies")}}</th>
|
||||
<th>{{__("Inter-State Supplies")}}</th>
|
||||
<th>{{__("Intra-State Supplies")}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{__("From a supplier under composition scheme, Exempt and Nil rated")}}</td>
|
||||
<td class="right">{{ flt(data.inward_sup.isup_details[0].inter, 2) }}</td>
|
||||
<td class="right">{{ flt(data.inward_sup.isup_details[0].intra, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{__("Non GST Inward Supplies")}}</td>
|
||||
<td class="right">{{ flt(data.inward_sup.isup_details[1].inter, 2) }}</td>
|
||||
<td class="right">{{ flt(data.inward_sup.isup_details[1].intra, 2) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<style>
|
||||
|
||||
.right{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
</style>
|
@ -1,64 +0,0 @@
|
||||
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('GSTR 3B Report', {
|
||||
refresh : function(frm) {
|
||||
frm.doc.__unsaved = 1;
|
||||
if(!frm.is_new()) {
|
||||
frm.set_intro(__("Please save the report again to rebuild or update"));
|
||||
frm.add_custom_button(__('Download JSON'), function() {
|
||||
var w = window.open(
|
||||
frappe.urllib.get_full_url(
|
||||
"/api/method/erpnext.regional.doctype.gstr_3b_report.gstr_3b_report.make_json?"
|
||||
+"name="+encodeURIComponent(frm.doc.name)));
|
||||
|
||||
if(!w) {
|
||||
frappe.msgprint(__("Please enable pop-ups")); return;
|
||||
}
|
||||
});
|
||||
frm.add_custom_button(__('View Form'), function() {
|
||||
frappe.call({
|
||||
"method" : "erpnext.regional.doctype.gstr_3b_report.gstr_3b_report.view_report",
|
||||
"args" : {
|
||||
name : frm.doc.name,
|
||||
},
|
||||
"callback" : function(r){
|
||||
|
||||
let data = r.message;
|
||||
|
||||
frappe.ui.get_print_settings(false, print_settings => {
|
||||
|
||||
frappe.render_grid({
|
||||
template: 'gstr_3b_report',
|
||||
title: __(this.doctype),
|
||||
print_settings: print_settings,
|
||||
data: data,
|
||||
columns:[]
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let current_year = new Date().getFullYear();
|
||||
let options = [current_year, current_year-1, current_year-2];
|
||||
frm.set_df_property('year', 'options', options);
|
||||
},
|
||||
|
||||
setup: function(frm) {
|
||||
frm.set_query('company_address', function(doc) {
|
||||
if(!doc.company) {
|
||||
frappe.throw(__('Please set Company'));
|
||||
}
|
||||
|
||||
return {
|
||||
query: 'frappe.contacts.doctype.address.address.address_query',
|
||||
filters: {
|
||||
link_doctype: 'Company',
|
||||
link_name: doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
@ -1,62 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "format:GSTR3B-{month}-{year}-{company_address}",
|
||||
"creation": "2019-02-04 11:35:55.964639",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"company",
|
||||
"company_address",
|
||||
"year",
|
||||
"month",
|
||||
"json_output",
|
||||
"missing_field_invoices"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company"
|
||||
},
|
||||
{
|
||||
"fieldname": "company_address",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company Address",
|
||||
"options": "Address"
|
||||
},
|
||||
{
|
||||
"fieldname": "year",
|
||||
"fieldtype": "Select",
|
||||
"label": "Year"
|
||||
},
|
||||
{
|
||||
"fieldname": "month",
|
||||
"fieldtype": "Select",
|
||||
"label": "Month",
|
||||
"options": "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember"
|
||||
},
|
||||
{
|
||||
"fieldname": "json_output",
|
||||
"fieldtype": "Code",
|
||||
"label": "JSON Output"
|
||||
},
|
||||
{
|
||||
"fieldname": "missing_field_invoices",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Invoices with no Place Of Supply",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-04-04 19:32:30.772908",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "GSTR 3B Report",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,465 +0,0 @@
|
||||
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cstr, flt
|
||||
|
||||
from erpnext.regional.india import state_numbers
|
||||
|
||||
|
||||
class GSTR3BReport(Document):
|
||||
def validate(self):
|
||||
self.get_data()
|
||||
|
||||
def get_data(self):
|
||||
self.report_dict = json.loads(get_json('gstr_3b_report_template'))
|
||||
|
||||
self.gst_details = self.get_company_gst_details()
|
||||
self.report_dict["gstin"] = self.gst_details.get("gstin")
|
||||
self.report_dict["ret_period"] = get_period(self.month, self.year)
|
||||
self.month_no = get_period(self.month)
|
||||
self.account_heads = self.get_account_heads()
|
||||
|
||||
self.get_outward_supply_details("Sales Invoice")
|
||||
self.set_outward_taxable_supplies()
|
||||
|
||||
self.get_outward_supply_details("Purchase Invoice", reverse_charge=True)
|
||||
self.set_supplies_liable_to_reverse_charge()
|
||||
|
||||
itc_details = self.get_itc_details()
|
||||
self.set_itc_details(itc_details)
|
||||
self.get_itc_reversal_entries()
|
||||
inward_nil_exempt = self.get_inward_nil_exempt(self.gst_details.get("gst_state"))
|
||||
self.set_inward_nil_exempt(inward_nil_exempt)
|
||||
|
||||
self.missing_field_invoices = self.get_missing_field_invoices()
|
||||
self.json_output = frappe.as_json(self.report_dict)
|
||||
|
||||
def set_inward_nil_exempt(self, inward_nil_exempt):
|
||||
self.report_dict["inward_sup"]["isup_details"][0]["inter"] = flt(inward_nil_exempt.get("gst").get("inter"), 2)
|
||||
self.report_dict["inward_sup"]["isup_details"][0]["intra"] = flt(inward_nil_exempt.get("gst").get("intra"), 2)
|
||||
self.report_dict["inward_sup"]["isup_details"][1]["inter"] = flt(inward_nil_exempt.get("non_gst").get("inter"), 2)
|
||||
self.report_dict["inward_sup"]["isup_details"][1]["intra"] = flt(inward_nil_exempt.get("non_gst").get("intra"), 2)
|
||||
|
||||
def set_itc_details(self, itc_details):
|
||||
itc_eligible_type_map = {
|
||||
'IMPG': 'Import Of Capital Goods',
|
||||
'IMPS': 'Import Of Service',
|
||||
'ISRC': 'ITC on Reverse Charge',
|
||||
'ISD': 'Input Service Distributor',
|
||||
'OTH': 'All Other ITC'
|
||||
}
|
||||
|
||||
itc_ineligible_map = {
|
||||
'RUL': 'Ineligible As Per Section 17(5)',
|
||||
'OTH': 'Ineligible Others'
|
||||
}
|
||||
|
||||
net_itc = self.report_dict["itc_elg"]["itc_net"]
|
||||
|
||||
for d in self.report_dict["itc_elg"]["itc_avl"]:
|
||||
itc_type = itc_eligible_type_map.get(d["ty"])
|
||||
for key in ['iamt', 'camt', 'samt', 'csamt']:
|
||||
d[key] = flt(itc_details.get(itc_type, {}).get(key))
|
||||
net_itc[key] += flt(d[key], 2)
|
||||
|
||||
for d in self.report_dict["itc_elg"]["itc_inelg"]:
|
||||
itc_type = itc_ineligible_map.get(d["ty"])
|
||||
for key in ['iamt', 'camt', 'samt', 'csamt']:
|
||||
d[key] = flt(itc_details.get(itc_type, {}).get(key))
|
||||
|
||||
def get_itc_reversal_entries(self):
|
||||
reversal_entries = frappe.db.sql("""
|
||||
SELECT ja.account, j.reversal_type, sum(credit_in_account_currency) as amount
|
||||
FROM `tabJournal Entry` j, `tabJournal Entry Account` ja
|
||||
where j.docstatus = 1
|
||||
and j.is_opening = 'No'
|
||||
and ja.parent = j.name
|
||||
and j.voucher_type = 'Reversal Of ITC'
|
||||
and month(j.posting_date) = %s and year(j.posting_date) = %s
|
||||
and j.company = %s and j.company_gstin = %s
|
||||
GROUP BY ja.account, j.reversal_type""", (self.month_no, self.year, self.company,
|
||||
self.gst_details.get("gstin")), as_dict=1)
|
||||
|
||||
net_itc = self.report_dict["itc_elg"]["itc_net"]
|
||||
|
||||
for entry in reversal_entries:
|
||||
if entry.reversal_type == 'As per rules 42 & 43 of CGST Rules':
|
||||
index = 0
|
||||
else:
|
||||
index = 1
|
||||
|
||||
for key in ['camt', 'samt', 'iamt', 'csamt']:
|
||||
if entry.account in self.account_heads.get(key):
|
||||
self.report_dict["itc_elg"]["itc_rev"][index][key] += flt(entry.amount)
|
||||
net_itc[key] -= flt(entry.amount)
|
||||
|
||||
def get_itc_details(self):
|
||||
itc_amounts = frappe.db.sql("""
|
||||
SELECT eligibility_for_itc, sum(itc_integrated_tax) as itc_integrated_tax,
|
||||
sum(itc_central_tax) as itc_central_tax,
|
||||
sum(itc_state_tax) as itc_state_tax,
|
||||
sum(itc_cess_amount) as itc_cess_amount
|
||||
FROM `tabPurchase Invoice`
|
||||
WHERE docstatus = 1
|
||||
and is_opening = 'No'
|
||||
and month(posting_date) = %s and year(posting_date) = %s and company = %s
|
||||
and company_gstin = %s
|
||||
GROUP BY eligibility_for_itc
|
||||
""", (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
|
||||
|
||||
itc_details = {}
|
||||
for d in itc_amounts:
|
||||
itc_details.setdefault(d.eligibility_for_itc, {
|
||||
'iamt': d.itc_integrated_tax,
|
||||
'camt': d.itc_central_tax,
|
||||
'samt': d.itc_state_tax,
|
||||
'csamt': d.itc_cess_amount
|
||||
})
|
||||
|
||||
return itc_details
|
||||
|
||||
def get_inward_nil_exempt(self, state):
|
||||
inward_nil_exempt = frappe.db.sql("""
|
||||
SELECT p.place_of_supply, sum(i.base_amount) as base_amount, i.is_nil_exempt, i.is_non_gst
|
||||
FROM `tabPurchase Invoice` p , `tabPurchase Invoice Item` i
|
||||
WHERE p.docstatus = 1 and p.name = i.parent
|
||||
and p.is_opening = 'No'
|
||||
and p.gst_category != 'Registered Composition'
|
||||
and (i.is_nil_exempt = 1 or i.is_non_gst = 1 or p.gst_category = 'Registered Composition') and
|
||||
month(p.posting_date) = %s and year(p.posting_date) = %s
|
||||
and p.company = %s and p.company_gstin = %s
|
||||
GROUP BY p.place_of_supply, i.is_nil_exempt, i.is_non_gst""",
|
||||
(self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
|
||||
|
||||
inward_nil_exempt_details = {
|
||||
"gst": {
|
||||
"intra": 0.0,
|
||||
"inter": 0.0
|
||||
},
|
||||
"non_gst": {
|
||||
"intra": 0.0,
|
||||
"inter": 0.0
|
||||
}
|
||||
}
|
||||
|
||||
for d in inward_nil_exempt:
|
||||
if d.place_of_supply:
|
||||
if (d.is_nil_exempt == 1 or d.get('gst_category') == 'Registered Composition') \
|
||||
and state == d.place_of_supply.split("-")[1]:
|
||||
inward_nil_exempt_details["gst"]["intra"] += d.base_amount
|
||||
elif (d.is_nil_exempt == 1 or d.get('gst_category') == 'Registered Composition') \
|
||||
and state != d.place_of_supply.split("-")[1]:
|
||||
inward_nil_exempt_details["gst"]["inter"] += d.base_amount
|
||||
elif d.is_non_gst == 1 and state == d.place_of_supply.split("-")[1]:
|
||||
inward_nil_exempt_details["non_gst"]["intra"] += d.base_amount
|
||||
elif d.is_non_gst == 1 and state != d.place_of_supply.split("-")[1]:
|
||||
inward_nil_exempt_details["non_gst"]["inter"] += d.base_amount
|
||||
|
||||
return inward_nil_exempt_details
|
||||
|
||||
def get_outward_supply_details(self, doctype, reverse_charge=None):
|
||||
self.get_outward_tax_invoices(doctype, reverse_charge=reverse_charge)
|
||||
self.get_outward_items(doctype)
|
||||
self.get_outward_tax_details(doctype)
|
||||
|
||||
def get_outward_tax_invoices(self, doctype, reverse_charge=None):
|
||||
self.invoices = []
|
||||
self.invoice_detail_map = {}
|
||||
condition = ''
|
||||
|
||||
if reverse_charge:
|
||||
condition += "AND reverse_charge = 'Y'"
|
||||
|
||||
invoice_details = frappe.db.sql("""
|
||||
SELECT
|
||||
name, gst_category, export_type, place_of_supply
|
||||
FROM
|
||||
`tab{doctype}`
|
||||
WHERE
|
||||
docstatus = 1
|
||||
AND month(posting_date) = %s
|
||||
AND year(posting_date) = %s
|
||||
AND company = %s
|
||||
AND company_gstin = %s
|
||||
AND is_opening = 'No'
|
||||
{reverse_charge}
|
||||
ORDER BY name
|
||||
""".format(doctype=doctype, reverse_charge=condition), (self.month_no, self.year,
|
||||
self.company, self.gst_details.get("gstin")), as_dict=1)
|
||||
|
||||
for d in invoice_details:
|
||||
self.invoice_detail_map.setdefault(d.name, d)
|
||||
self.invoices.append(d.name)
|
||||
|
||||
def get_outward_items(self, doctype):
|
||||
self.invoice_items = frappe._dict()
|
||||
self.is_nil_exempt = []
|
||||
self.is_non_gst = []
|
||||
|
||||
if self.get('invoices'):
|
||||
item_details = frappe.db.sql("""
|
||||
SELECT
|
||||
item_code, parent, taxable_value, base_net_amount, item_tax_rate,
|
||||
is_nil_exempt, is_non_gst
|
||||
FROM
|
||||
`tab%s Item`
|
||||
WHERE parent in (%s)
|
||||
""" % (doctype, ', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1)
|
||||
|
||||
for d in item_details:
|
||||
if d.item_code not in self.invoice_items.get(d.parent, {}):
|
||||
self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code, 0.0)
|
||||
self.invoice_items[d.parent][d.item_code] += d.get('taxable_value', 0) or d.get('base_net_amount', 0)
|
||||
|
||||
if d.is_nil_exempt and d.item_code not in self.is_nil_exempt:
|
||||
self.is_nil_exempt.append(d.item_code)
|
||||
|
||||
if d.is_non_gst and d.item_code not in self.is_non_gst:
|
||||
self.is_non_gst.append(d.item_code)
|
||||
|
||||
def get_outward_tax_details(self, doctype):
|
||||
if doctype == "Sales Invoice":
|
||||
tax_template = 'Sales Taxes and Charges'
|
||||
elif doctype == "Purchase Invoice":
|
||||
tax_template = 'Purchase Taxes and Charges'
|
||||
|
||||
self.items_based_on_tax_rate = {}
|
||||
self.invoice_cess = frappe._dict()
|
||||
self.cgst_sgst_invoices = []
|
||||
|
||||
if self.get('invoices'):
|
||||
tax_details = frappe.db.sql("""
|
||||
SELECT
|
||||
parent, account_head, item_wise_tax_detail, base_tax_amount_after_discount_amount
|
||||
FROM `tab%s`
|
||||
WHERE
|
||||
parenttype = %s and docstatus = 1
|
||||
and parent in (%s)
|
||||
ORDER BY account_head
|
||||
""" % (tax_template, '%s', ', '.join(['%s']*len(self.invoices))),
|
||||
tuple([doctype] + list(self.invoices)))
|
||||
|
||||
for parent, account, item_wise_tax_detail, tax_amount in tax_details:
|
||||
if account in self.account_heads.get('csamt'):
|
||||
self.invoice_cess.setdefault(parent, tax_amount)
|
||||
else:
|
||||
if item_wise_tax_detail:
|
||||
try:
|
||||
item_wise_tax_detail = json.loads(item_wise_tax_detail)
|
||||
cgst_or_sgst = False
|
||||
if account in self.account_heads.get('camt') \
|
||||
or account in self.account_heads.get('samt'):
|
||||
cgst_or_sgst = True
|
||||
|
||||
for item_code, tax_amounts in item_wise_tax_detail.items():
|
||||
if not (cgst_or_sgst or account in self.account_heads.get('iamt') or
|
||||
(item_code in self.is_non_gst + self.is_nil_exempt)):
|
||||
continue
|
||||
|
||||
tax_rate = tax_amounts[0]
|
||||
if tax_rate:
|
||||
if cgst_or_sgst:
|
||||
tax_rate *= 2
|
||||
if parent not in self.cgst_sgst_invoices:
|
||||
self.cgst_sgst_invoices.append(parent)
|
||||
|
||||
rate_based_dict = self.items_based_on_tax_rate\
|
||||
.setdefault(parent, {}).setdefault(tax_rate, [])
|
||||
if item_code not in rate_based_dict:
|
||||
rate_based_dict.append(item_code)
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
|
||||
if self.get('invoice_items'):
|
||||
# Build itemised tax for export invoices, nil and exempted where tax table is blank
|
||||
for invoice, items in self.invoice_items.items():
|
||||
if invoice not in self.items_based_on_tax_rate and self.invoice_detail_map.get(invoice, {}).get('export_type') \
|
||||
== "Without Payment of Tax" and self.invoice_detail_map.get(invoice, {}).get('gst_category') == "Overseas":
|
||||
self.items_based_on_tax_rate.setdefault(invoice, {}).setdefault(0, items.keys())
|
||||
else:
|
||||
for item in items.keys():
|
||||
if item in self.is_nil_exempt + self.is_non_gst and \
|
||||
item not in self.items_based_on_tax_rate.get(invoice, {}).get(0, []):
|
||||
self.items_based_on_tax_rate.setdefault(invoice, {}).setdefault(0, [])
|
||||
self.items_based_on_tax_rate[invoice][0].append(item)
|
||||
|
||||
def set_outward_taxable_supplies(self):
|
||||
inter_state_supply_details = {}
|
||||
|
||||
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
|
||||
gst_category = self.invoice_detail_map.get(inv, {}).get('gst_category')
|
||||
place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply') or '00-Other Territory'
|
||||
export_type = self.invoice_detail_map.get(inv, {}).get('export_type')
|
||||
|
||||
for rate, items in items_based_on_rate.items():
|
||||
for item_code, taxable_value in self.invoice_items.get(inv).items():
|
||||
if item_code in items:
|
||||
if item_code in self.is_nil_exempt:
|
||||
self.report_dict['sup_details']['osup_nil_exmp']['txval'] += taxable_value
|
||||
elif item_code in self.is_non_gst:
|
||||
self.report_dict['sup_details']['osup_nongst']['txval'] += taxable_value
|
||||
elif rate == 0 or (gst_category == 'Overseas' and export_type == 'Without Payment of Tax'):
|
||||
self.report_dict['sup_details']['osup_zero']['txval'] += taxable_value
|
||||
else:
|
||||
if inv in self.cgst_sgst_invoices:
|
||||
tax_rate = rate/2
|
||||
self.report_dict['sup_details']['osup_det']['camt'] += (taxable_value * tax_rate /100)
|
||||
self.report_dict['sup_details']['osup_det']['samt'] += (taxable_value * tax_rate /100)
|
||||
self.report_dict['sup_details']['osup_det']['txval'] += taxable_value
|
||||
else:
|
||||
self.report_dict['sup_details']['osup_det']['iamt'] += (taxable_value * rate /100)
|
||||
self.report_dict['sup_details']['osup_det']['txval'] += taxable_value
|
||||
|
||||
if gst_category in ['Unregistered', 'Registered Composition', 'UIN Holders'] and \
|
||||
self.gst_details.get("gst_state") != place_of_supply.split("-")[1]:
|
||||
inter_state_supply_details.setdefault((gst_category, place_of_supply), {
|
||||
"txval": 0.0,
|
||||
"pos": place_of_supply.split("-")[0],
|
||||
"iamt": 0.0
|
||||
})
|
||||
inter_state_supply_details[(gst_category, place_of_supply)]['txval'] += taxable_value
|
||||
inter_state_supply_details[(gst_category, place_of_supply)]['iamt'] += (taxable_value * rate /100)
|
||||
|
||||
if self.invoice_cess.get(inv):
|
||||
self.report_dict['sup_details']['osup_det']['csamt'] += flt(self.invoice_cess.get(inv), 2)
|
||||
|
||||
self.set_inter_state_supply(inter_state_supply_details)
|
||||
|
||||
def set_supplies_liable_to_reverse_charge(self):
|
||||
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
|
||||
for rate, items in items_based_on_rate.items():
|
||||
for item_code, taxable_value in self.invoice_items.get(inv).items():
|
||||
if item_code in items:
|
||||
if inv in self.cgst_sgst_invoices:
|
||||
tax_rate = rate/2
|
||||
self.report_dict['sup_details']['isup_rev']['camt'] += (taxable_value * tax_rate /100)
|
||||
self.report_dict['sup_details']['isup_rev']['samt'] += (taxable_value * tax_rate /100)
|
||||
self.report_dict['sup_details']['isup_rev']['txval'] += taxable_value
|
||||
else:
|
||||
self.report_dict['sup_details']['isup_rev']['iamt'] += (taxable_value * rate /100)
|
||||
self.report_dict['sup_details']['isup_rev']['txval'] += taxable_value
|
||||
|
||||
def set_inter_state_supply(self, inter_state_supply):
|
||||
for key, value in inter_state_supply.items():
|
||||
if key[0] == "Unregistered":
|
||||
self.report_dict["inter_sup"]["unreg_details"].append(value)
|
||||
|
||||
if key[0] == "Registered Composition":
|
||||
self.report_dict["inter_sup"]["comp_details"].append(value)
|
||||
|
||||
if key[0] == "UIN Holders":
|
||||
self.report_dict["inter_sup"]["uin_details"].append(value)
|
||||
|
||||
def get_company_gst_details(self):
|
||||
gst_details = frappe.get_all("Address",
|
||||
fields=["gstin", "gst_state", "gst_state_number"],
|
||||
filters={
|
||||
"name":self.company_address
|
||||
})
|
||||
|
||||
if gst_details:
|
||||
return gst_details[0]
|
||||
else:
|
||||
frappe.throw(_("Please enter GSTIN and state for the Company Address {0}").format(self.company_address))
|
||||
|
||||
def get_account_heads(self):
|
||||
account_map = {
|
||||
'sgst_account': 'samt',
|
||||
'cess_account': 'csamt',
|
||||
'cgst_account': 'camt',
|
||||
'igst_account': 'iamt'
|
||||
}
|
||||
|
||||
account_heads = {}
|
||||
gst_settings_accounts = frappe.get_all("GST Account",
|
||||
filters={'company': self.company, 'is_reverse_charge_account': 0},
|
||||
fields=["cgst_account", "sgst_account", "igst_account", "cess_account"])
|
||||
|
||||
if not gst_settings_accounts:
|
||||
frappe.throw(_("Please set GST Accounts in GST Settings"))
|
||||
|
||||
for d in gst_settings_accounts:
|
||||
for acc, val in d.items():
|
||||
account_heads.setdefault(account_map.get(acc), []).append(val)
|
||||
|
||||
return account_heads
|
||||
|
||||
def get_missing_field_invoices(self):
|
||||
missing_field_invoices = []
|
||||
|
||||
for doctype in ["Sales Invoice", "Purchase Invoice"]:
|
||||
|
||||
if doctype == "Sales Invoice":
|
||||
party_type = 'Customer'
|
||||
party = 'customer'
|
||||
else:
|
||||
party_type = 'Supplier'
|
||||
party = 'supplier'
|
||||
|
||||
docnames = frappe.db.sql(
|
||||
"""
|
||||
SELECT t1.name FROM `tab{doctype}` t1, `tab{party_type}` t2
|
||||
WHERE t1.docstatus = 1 and t1.is_opening = 'No'
|
||||
and month(t1.posting_date) = %s and year(t1.posting_date) = %s
|
||||
and t1.company = %s and t1.place_of_supply IS NULL and t1.{party} = t2.name and
|
||||
t2.gst_category != 'Overseas'
|
||||
""".format(doctype = doctype, party_type = party_type,
|
||||
party=party) ,(self.month_no, self.year, self.company), as_dict=1) #nosec
|
||||
|
||||
for d in docnames:
|
||||
missing_field_invoices.append(d.name)
|
||||
|
||||
return ",".join(missing_field_invoices)
|
||||
|
||||
def get_json(template):
|
||||
file_path = os.path.join(os.path.dirname(__file__), '{template}.json'.format(template=template))
|
||||
with open(file_path, 'r') as f:
|
||||
return cstr(f.read())
|
||||
|
||||
def get_state_code(state):
|
||||
state_code = state_numbers.get(state)
|
||||
|
||||
return state_code
|
||||
|
||||
def get_period(month, year=None):
|
||||
month_no = {
|
||||
"January": 1,
|
||||
"February": 2,
|
||||
"March": 3,
|
||||
"April": 4,
|
||||
"May": 5,
|
||||
"June": 6,
|
||||
"July": 7,
|
||||
"August": 8,
|
||||
"September": 9,
|
||||
"October": 10,
|
||||
"November": 11,
|
||||
"December": 12
|
||||
}.get(month)
|
||||
|
||||
if year:
|
||||
return str(month_no).zfill(2) + str(year)
|
||||
else:
|
||||
return month_no
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def view_report(name):
|
||||
json_data = frappe.get_value("GSTR 3B Report", name, 'json_output')
|
||||
return json.loads(json_data)
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_json(name):
|
||||
json_data = frappe.get_value("GSTR 3B Report", name, 'json_output')
|
||||
file_name = "GST3B.json"
|
||||
frappe.local.response.filename = file_name
|
||||
frappe.local.response.filecontent = json_data
|
||||
frappe.local.response.type = "download"
|
@ -1,127 +0,0 @@
|
||||
{
|
||||
"gstin": "",
|
||||
"ret_period": "",
|
||||
"inward_sup": {
|
||||
"isup_details": [
|
||||
{
|
||||
"ty": "GST",
|
||||
"intra": 0,
|
||||
"inter": 0
|
||||
},
|
||||
{
|
||||
"ty": "NONGST",
|
||||
"inter": 0,
|
||||
"intra": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"sup_details": {
|
||||
"osup_zero": {
|
||||
"csamt": 0,
|
||||
"txval": 0,
|
||||
"iamt": 0
|
||||
},
|
||||
"osup_nil_exmp": {
|
||||
"txval": 0
|
||||
},
|
||||
"osup_det": {
|
||||
"samt": 0,
|
||||
"csamt": 0,
|
||||
"txval": 0,
|
||||
"camt": 0,
|
||||
"iamt": 0
|
||||
},
|
||||
"isup_rev": {
|
||||
"samt": 0,
|
||||
"csamt": 0,
|
||||
"txval": 0,
|
||||
"camt": 0,
|
||||
"iamt": 0
|
||||
},
|
||||
"osup_nongst": {
|
||||
"txval": 0
|
||||
}
|
||||
},
|
||||
"inter_sup": {
|
||||
"unreg_details": [],
|
||||
"comp_details": [],
|
||||
"uin_details": []
|
||||
},
|
||||
"itc_elg": {
|
||||
"itc_avl": [
|
||||
{
|
||||
"csamt": 0,
|
||||
"samt": 0,
|
||||
"ty": "IMPG",
|
||||
"camt": 0,
|
||||
"iamt": 0
|
||||
},
|
||||
{
|
||||
"csamt": 0,
|
||||
"samt": 0,
|
||||
"ty": "IMPS",
|
||||
"camt": 0,
|
||||
"iamt": 0
|
||||
},
|
||||
{
|
||||
"samt": 0,
|
||||
"csamt": 0,
|
||||
"ty": "ISRC",
|
||||
"camt": 0,
|
||||
"iamt": 0
|
||||
},
|
||||
{
|
||||
"ty": "ISD",
|
||||
"iamt": 0,
|
||||
"camt": 0,
|
||||
"samt": 0,
|
||||
"csamt": 0
|
||||
},
|
||||
{
|
||||
"samt": 0,
|
||||
"csamt": 0,
|
||||
"ty": "OTH",
|
||||
"camt": 0,
|
||||
"iamt": 0
|
||||
}
|
||||
],
|
||||
"itc_rev": [
|
||||
{
|
||||
"ty": "RUL",
|
||||
"iamt": 0,
|
||||
"camt": 0,
|
||||
"samt": 0,
|
||||
"csamt": 0
|
||||
},
|
||||
{
|
||||
"ty": "OTH",
|
||||
"iamt": 0,
|
||||
"camt": 0,
|
||||
"samt": 0,
|
||||
"csamt": 0
|
||||
}
|
||||
],
|
||||
"itc_net": {
|
||||
"samt": 0,
|
||||
"csamt": 0,
|
||||
"camt": 0,
|
||||
"iamt": 0
|
||||
},
|
||||
"itc_inelg": [
|
||||
{
|
||||
"ty": "RUL",
|
||||
"iamt": 0,
|
||||
"camt": 0,
|
||||
"samt": 0,
|
||||
"csamt": 0
|
||||
},
|
||||
{
|
||||
"ty": "OTH",
|
||||
"iamt": 0,
|
||||
"camt": 0,
|
||||
"samt": 0,
|
||||
"csamt": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -1,491 +0,0 @@
|
||||
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
import json
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.utils import getdate
|
||||
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
|
||||
test_dependencies = ["Territory", "Customer Group", "Supplier Group", "Item"]
|
||||
|
||||
class TestGSTR3BReport(unittest.TestCase):
|
||||
def setUp(self):
|
||||
frappe.set_user("Administrator")
|
||||
|
||||
frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company GST'")
|
||||
frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company GST'")
|
||||
frappe.db.sql("delete from `tabGSTR 3B Report` where company='_Test Company GST'")
|
||||
|
||||
make_company()
|
||||
make_item("Milk", properties = {"is_nil_exempt": 1, "standard_rate": 0.000000})
|
||||
set_account_heads()
|
||||
make_customers()
|
||||
make_suppliers()
|
||||
|
||||
def test_gstr_3b_report(self):
|
||||
month_number_mapping = {
|
||||
1: "January",
|
||||
2: "February",
|
||||
3: "March",
|
||||
4: "April",
|
||||
5: "May",
|
||||
6: "June",
|
||||
7: "July",
|
||||
8: "August",
|
||||
9: "September",
|
||||
10: "October",
|
||||
11: "November",
|
||||
12: "December"
|
||||
}
|
||||
|
||||
make_sales_invoice()
|
||||
create_purchase_invoices()
|
||||
|
||||
if frappe.db.exists("GSTR 3B Report", "GSTR3B-March-2019-_Test Address GST-Billing"):
|
||||
report = frappe.get_doc("GSTR 3B Report", "GSTR3B-March-2019-_Test Address GST-Billing")
|
||||
report.save()
|
||||
else:
|
||||
report = frappe.get_doc({
|
||||
"doctype": "GSTR 3B Report",
|
||||
"company": "_Test Company GST",
|
||||
"company_address": "_Test Address GST-Billing",
|
||||
"year": getdate().year,
|
||||
"month": month_number_mapping.get(getdate().month)
|
||||
}).insert()
|
||||
|
||||
output = json.loads(report.json_output)
|
||||
|
||||
self.assertEqual(output["sup_details"]["osup_det"]["iamt"], 54)
|
||||
self.assertEqual(output["inter_sup"]["unreg_details"][0]["iamt"], 18),
|
||||
self.assertEqual(output["sup_details"]["osup_nil_exmp"]["txval"], 100),
|
||||
self.assertEqual(output["inward_sup"]["isup_details"][0]["intra"], 250)
|
||||
self.assertEqual(output["itc_elg"]["itc_avl"][4]["samt"], 22.50)
|
||||
self.assertEqual(output["itc_elg"]["itc_avl"][4]["camt"], 22.50)
|
||||
|
||||
def test_gst_rounding(self):
|
||||
gst_settings = frappe.get_doc('GST Settings')
|
||||
gst_settings.round_off_gst_values = 1
|
||||
gst_settings.save()
|
||||
|
||||
current_country = frappe.flags.country
|
||||
frappe.flags.country = 'India'
|
||||
|
||||
si = create_sales_invoice(company="_Test Company GST",
|
||||
customer = '_Test GST Customer',
|
||||
currency = 'INR',
|
||||
warehouse = 'Finished Goods - _GST',
|
||||
debit_to = 'Debtors - _GST',
|
||||
income_account = 'Sales - _GST',
|
||||
expense_account = 'Cost of Goods Sold - _GST',
|
||||
cost_center = 'Main - _GST',
|
||||
rate=216,
|
||||
do_not_save=1
|
||||
)
|
||||
|
||||
si.append("taxes", {
|
||||
"charge_type": "On Net Total",
|
||||
"account_head": "Output Tax IGST - _GST",
|
||||
"cost_center": "Main - _GST",
|
||||
"description": "IGST @ 18.0",
|
||||
"rate": 18
|
||||
})
|
||||
|
||||
si.save()
|
||||
# Check for 39 instead of 38.88
|
||||
self.assertEqual(si.taxes[0].base_tax_amount_after_discount_amount, 39)
|
||||
|
||||
frappe.flags.country = current_country
|
||||
gst_settings.round_off_gst_values = 1
|
||||
gst_settings.save()
|
||||
|
||||
def test_gst_category_auto_update(self):
|
||||
if not frappe.db.exists("Customer", "_Test GST Customer With GSTIN"):
|
||||
customer = frappe.get_doc({
|
||||
"customer_group": "_Test Customer Group",
|
||||
"customer_name": "_Test GST Customer With GSTIN",
|
||||
"customer_type": "Individual",
|
||||
"doctype": "Customer",
|
||||
"territory": "_Test Territory"
|
||||
}).insert()
|
||||
|
||||
self.assertEqual(customer.gst_category, 'Unregistered')
|
||||
|
||||
if not frappe.db.exists('Address', '_Test GST Category-1-Billing'):
|
||||
address = frappe.get_doc({
|
||||
"address_line1": "_Test Address Line 1",
|
||||
"address_title": "_Test GST Category-1",
|
||||
"address_type": "Billing",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 1,
|
||||
"phone": "+91 0000000000",
|
||||
"gstin": "29AZWPS7135H1ZG",
|
||||
"gst_state": "Karnataka",
|
||||
"gst_state_number": "29"
|
||||
}).insert()
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Customer",
|
||||
"link_name": "_Test GST Customer With GSTIN"
|
||||
})
|
||||
|
||||
address.save()
|
||||
|
||||
customer.load_from_db()
|
||||
self.assertEqual(customer.gst_category, 'Registered Regular')
|
||||
|
||||
|
||||
def make_sales_invoice():
|
||||
si = create_sales_invoice(company="_Test Company GST",
|
||||
customer = '_Test GST Customer',
|
||||
currency = 'INR',
|
||||
warehouse = 'Finished Goods - _GST',
|
||||
debit_to = 'Debtors - _GST',
|
||||
income_account = 'Sales - _GST',
|
||||
expense_account = 'Cost of Goods Sold - _GST',
|
||||
cost_center = 'Main - _GST',
|
||||
do_not_save=1
|
||||
)
|
||||
|
||||
si.append("taxes", {
|
||||
"charge_type": "On Net Total",
|
||||
"account_head": "Output Tax IGST - _GST",
|
||||
"cost_center": "Main - _GST",
|
||||
"description": "IGST @ 18.0",
|
||||
"rate": 18
|
||||
})
|
||||
|
||||
si.submit()
|
||||
|
||||
si1 = create_sales_invoice(company="_Test Company GST",
|
||||
customer = '_Test GST SEZ Customer',
|
||||
currency = 'INR',
|
||||
warehouse = 'Finished Goods - _GST',
|
||||
debit_to = 'Debtors - _GST',
|
||||
income_account = 'Sales - _GST',
|
||||
expense_account = 'Cost of Goods Sold - _GST',
|
||||
cost_center = 'Main - _GST',
|
||||
do_not_save=1
|
||||
)
|
||||
|
||||
si1.append("taxes", {
|
||||
"charge_type": "On Net Total",
|
||||
"account_head": "Output Tax IGST - _GST",
|
||||
"cost_center": "Main - _GST",
|
||||
"description": "IGST @ 18.0",
|
||||
"rate": 18
|
||||
})
|
||||
|
||||
si1.submit()
|
||||
|
||||
si2 = create_sales_invoice(company="_Test Company GST",
|
||||
customer = '_Test Unregistered Customer',
|
||||
currency = 'INR',
|
||||
warehouse = 'Finished Goods - _GST',
|
||||
debit_to = 'Debtors - _GST',
|
||||
income_account = 'Sales - _GST',
|
||||
expense_account = 'Cost of Goods Sold - _GST',
|
||||
cost_center = 'Main - _GST',
|
||||
do_not_save=1
|
||||
)
|
||||
|
||||
si2.append("taxes", {
|
||||
"charge_type": "On Net Total",
|
||||
"account_head": "Output Tax IGST - _GST",
|
||||
"cost_center": "Main - _GST",
|
||||
"description": "IGST @ 18.0",
|
||||
"rate": 18
|
||||
})
|
||||
|
||||
si2.submit()
|
||||
|
||||
si3 = create_sales_invoice(company="_Test Company GST",
|
||||
customer = '_Test GST Customer',
|
||||
currency = 'INR',
|
||||
item = 'Milk',
|
||||
warehouse = 'Finished Goods - _GST',
|
||||
debit_to = 'Debtors - _GST',
|
||||
income_account = 'Sales - _GST',
|
||||
expense_account = 'Cost of Goods Sold - _GST',
|
||||
cost_center = 'Main - _GST',
|
||||
do_not_save=1
|
||||
)
|
||||
si3.submit()
|
||||
|
||||
def create_purchase_invoices():
|
||||
pi = make_purchase_invoice(
|
||||
company="_Test Company GST",
|
||||
supplier = '_Test Registered Supplier',
|
||||
currency = 'INR',
|
||||
warehouse = 'Finished Goods - _GST',
|
||||
cost_center = 'Main - _GST',
|
||||
expense_account = 'Cost of Goods Sold - _GST',
|
||||
do_not_save=1,
|
||||
)
|
||||
|
||||
pi.eligibility_for_itc = "All Other ITC"
|
||||
|
||||
pi.append("taxes", {
|
||||
"charge_type": "On Net Total",
|
||||
"account_head": "Input Tax CGST - _GST",
|
||||
"cost_center": "Main - _GST",
|
||||
"description": "CGST @ 9.0",
|
||||
"rate": 9
|
||||
})
|
||||
|
||||
pi.append("taxes", {
|
||||
"charge_type": "On Net Total",
|
||||
"account_head": "Input Tax SGST - _GST",
|
||||
"cost_center": "Main - _GST",
|
||||
"description": "SGST @ 9.0",
|
||||
"rate": 9
|
||||
})
|
||||
|
||||
pi.submit()
|
||||
|
||||
pi1 = make_purchase_invoice(
|
||||
company="_Test Company GST",
|
||||
supplier = '_Test Registered Supplier',
|
||||
currency = 'INR',
|
||||
warehouse = 'Finished Goods - _GST',
|
||||
cost_center = 'Main - _GST',
|
||||
expense_account = 'Cost of Goods Sold - _GST',
|
||||
item = "Milk",
|
||||
do_not_save=1
|
||||
)
|
||||
|
||||
pi1.shipping_address = "_Test Supplier GST-1-Billing"
|
||||
pi1.save()
|
||||
|
||||
pi1.submit()
|
||||
|
||||
pi2 = make_purchase_invoice(company="_Test Company GST",
|
||||
customer = '_Test Registered Supplier',
|
||||
currency = 'INR',
|
||||
item = 'Milk',
|
||||
warehouse = 'Finished Goods - _GST',
|
||||
expense_account = 'Cost of Goods Sold - _GST',
|
||||
cost_center = 'Main - _GST',
|
||||
rate=250,
|
||||
qty=1,
|
||||
do_not_save=1
|
||||
)
|
||||
pi2.submit()
|
||||
|
||||
def make_suppliers():
|
||||
if not frappe.db.exists("Supplier", "_Test Registered Supplier"):
|
||||
frappe.get_doc({
|
||||
"supplier_group": "_Test Supplier Group",
|
||||
"supplier_name": "_Test Registered Supplier",
|
||||
"gst_category": "Registered Regular",
|
||||
"supplier_type": "Individual",
|
||||
"doctype": "Supplier",
|
||||
}).insert()
|
||||
|
||||
if not frappe.db.exists("Supplier", "_Test Unregistered Supplier"):
|
||||
frappe.get_doc({
|
||||
"supplier_group": "_Test Supplier Group",
|
||||
"supplier_name": "_Test Unregistered Supplier",
|
||||
"gst_category": "Unregistered",
|
||||
"supplier_type": "Individual",
|
||||
"doctype": "Supplier",
|
||||
}).insert()
|
||||
|
||||
if not frappe.db.exists('Address', '_Test Supplier GST-1-Billing'):
|
||||
address = frappe.get_doc({
|
||||
"address_line1": "_Test Address Line 1",
|
||||
"address_title": "_Test Supplier GST-1",
|
||||
"address_type": "Billing",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 1,
|
||||
"phone": "+91 0000000000",
|
||||
"gstin": "29AACCV0498C1Z9",
|
||||
"gst_state": "Karnataka",
|
||||
}).insert()
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Supplier",
|
||||
"link_name": "_Test Registered Supplier"
|
||||
})
|
||||
|
||||
address.is_shipping_address = 1
|
||||
address.save()
|
||||
|
||||
if not frappe.db.exists('Address', '_Test Supplier GST-2-Billing'):
|
||||
address = frappe.get_doc({
|
||||
"address_line1": "_Test Address Line 1",
|
||||
"address_title": "_Test Supplier GST-2",
|
||||
"address_type": "Billing",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 1,
|
||||
"phone": "+91 0000000000",
|
||||
"gst_state": "Karnataka",
|
||||
}).insert()
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Supplier",
|
||||
"link_name": "_Test Unregistered Supplier"
|
||||
})
|
||||
|
||||
address.save()
|
||||
|
||||
def make_customers():
|
||||
if not frappe.db.exists("Customer", "_Test GST Customer"):
|
||||
frappe.get_doc({
|
||||
"customer_group": "_Test Customer Group",
|
||||
"customer_name": "_Test GST Customer",
|
||||
"gst_category": "Registered Regular",
|
||||
"customer_type": "Individual",
|
||||
"doctype": "Customer",
|
||||
"territory": "_Test Territory"
|
||||
}).insert()
|
||||
|
||||
if not frappe.db.exists("Customer", "_Test GST SEZ Customer"):
|
||||
frappe.get_doc({
|
||||
"customer_group": "_Test Customer Group",
|
||||
"customer_name": "_Test GST SEZ Customer",
|
||||
"gst_category": "SEZ",
|
||||
"customer_type": "Individual",
|
||||
"doctype": "Customer",
|
||||
"territory": "_Test Territory"
|
||||
}).insert()
|
||||
|
||||
if not frappe.db.exists("Customer", "_Test Unregistered Customer"):
|
||||
frappe.get_doc({
|
||||
"customer_group": "_Test Customer Group",
|
||||
"customer_name": "_Test Unregistered Customer",
|
||||
"gst_category": "Unregistered",
|
||||
"customer_type": "Individual",
|
||||
"doctype": "Customer",
|
||||
"territory": "_Test Territory"
|
||||
}).insert()
|
||||
|
||||
if not frappe.db.exists('Address', '_Test GST-1-Billing'):
|
||||
address = frappe.get_doc({
|
||||
"address_line1": "_Test Address Line 1",
|
||||
"address_title": "_Test GST-1",
|
||||
"address_type": "Billing",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 1,
|
||||
"phone": "+91 0000000000",
|
||||
"gstin": "29AZWPS7135H1ZG",
|
||||
"gst_state": "Karnataka",
|
||||
"gst_state_number": "29"
|
||||
}).insert()
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Customer",
|
||||
"link_name": "_Test GST Customer"
|
||||
})
|
||||
|
||||
address.save()
|
||||
|
||||
if not frappe.db.exists('Address', '_Test GST-2-Billing'):
|
||||
address = frappe.get_doc({
|
||||
"address_line1": "_Test Address Line 1",
|
||||
"address_title": "_Test GST-2",
|
||||
"address_type": "Billing",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 1,
|
||||
"phone": "+91 0000000000",
|
||||
"gst_state": "Haryana",
|
||||
}).insert()
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Customer",
|
||||
"link_name": "_Test Unregistered Customer"
|
||||
})
|
||||
|
||||
address.save()
|
||||
|
||||
if not frappe.db.exists('Address', '_Test GST-3-Billing'):
|
||||
address = frappe.get_doc({
|
||||
"address_line1": "_Test Address Line 1",
|
||||
"address_title": "_Test GST-3",
|
||||
"address_type": "Billing",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 1,
|
||||
"phone": "+91 0000000000",
|
||||
"gst_state": "Gujarat",
|
||||
}).insert()
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Customer",
|
||||
"link_name": "_Test GST SEZ Customer"
|
||||
})
|
||||
|
||||
address.save()
|
||||
|
||||
def make_company():
|
||||
if frappe.db.exists("Company", "_Test Company GST"):
|
||||
return
|
||||
|
||||
company = frappe.new_doc("Company")
|
||||
company.company_name = "_Test Company GST"
|
||||
company.abbr = "_GST"
|
||||
company.default_currency = "INR"
|
||||
company.country = "India"
|
||||
company.insert()
|
||||
|
||||
if not frappe.db.exists('Address', '_Test Address GST-Billing'):
|
||||
address = frappe.get_doc({
|
||||
"address_title": "_Test Address GST",
|
||||
"address_line1": "_Test Address Line 1",
|
||||
"address_type": "Billing",
|
||||
"city": "_Test City",
|
||||
"state": "Test State",
|
||||
"country": "India",
|
||||
"doctype": "Address",
|
||||
"is_primary_address": 1,
|
||||
"phone": "+91 0000000000",
|
||||
"gstin": "27AAECE4835E1ZR",
|
||||
"gst_state": "Maharashtra",
|
||||
"gst_state_number": "27"
|
||||
}).insert()
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Company",
|
||||
"link_name": "_Test Company GST"
|
||||
})
|
||||
|
||||
address.save()
|
||||
|
||||
def set_account_heads():
|
||||
gst_settings = frappe.get_doc("GST Settings")
|
||||
|
||||
gst_account = frappe.get_all(
|
||||
"GST Account",
|
||||
fields=["cgst_account", "sgst_account", "igst_account"],
|
||||
filters = {"company": "_Test Company GST"})
|
||||
|
||||
if not gst_account:
|
||||
gst_settings.append("gst_accounts", {
|
||||
"company": "_Test Company GST",
|
||||
"cgst_account": "Output Tax CGST - _GST",
|
||||
"sgst_account": "Output Tax SGST - _GST",
|
||||
"igst_account": "Output Tax IGST - _GST"
|
||||
})
|
||||
|
||||
gst_settings.save()
|
@ -1,8 +0,0 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Lower Deduction Certificate', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
@ -1,140 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "field:certificate_no",
|
||||
"creation": "2020-03-10 23:12:10.072631",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"certificate_details_section",
|
||||
"tax_withholding_category",
|
||||
"fiscal_year",
|
||||
"column_break_3",
|
||||
"certificate_no",
|
||||
"section_break_3",
|
||||
"supplier",
|
||||
"column_break_7",
|
||||
"pan_no",
|
||||
"validity_details_section",
|
||||
"valid_from",
|
||||
"column_break_10",
|
||||
"valid_upto",
|
||||
"section_break_9",
|
||||
"rate",
|
||||
"column_break_14",
|
||||
"certificate_limit"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "certificate_no",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Certificate No",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_3",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Deductee Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "supplier",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Supplier",
|
||||
"options": "Supplier",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "supplier.pan",
|
||||
"fetch_if_empty": 1,
|
||||
"fieldname": "pan_no",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "PAN No",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "validity_details_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Validity Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "valid_upto",
|
||||
"fieldtype": "Date",
|
||||
"label": "Valid Upto",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_9",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Percent",
|
||||
"label": "Rate Of TDS As Per Certificate",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "certificate_limit",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Certificate Limit",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "certificate_details_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Certificate Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_10",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_14",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "valid_from",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Valid From",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"label": "Fiscal Year",
|
||||
"options": "Fiscal Year",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "tax_withholding_category",
|
||||
"fieldtype": "Link",
|
||||
"label": "Tax Withholding Category",
|
||||
"options": "Tax Withholding Category",
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-10-23 18:33:38.962622",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "Lower Deduction Certificate",
|
||||
"naming_rule": "By fieldname",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import get_link_to_form, getdate
|
||||
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
|
||||
|
||||
class LowerDeductionCertificate(Document):
|
||||
def validate(self):
|
||||
self.validate_dates()
|
||||
self.validate_supplier_against_tax_category()
|
||||
|
||||
def validate_dates(self):
|
||||
if getdate(self.valid_upto) < getdate(self.valid_from):
|
||||
frappe.throw(_("Valid Upto date cannot be before Valid From date"))
|
||||
|
||||
fiscal_year = get_fiscal_year(fiscal_year=self.fiscal_year, as_dict=True)
|
||||
|
||||
if not (fiscal_year.year_start_date <= getdate(self.valid_from) \
|
||||
<= fiscal_year.year_end_date):
|
||||
frappe.throw(_("Valid From date not in Fiscal Year {0}").format(frappe.bold(self.fiscal_year)))
|
||||
|
||||
if not (fiscal_year.year_start_date <= getdate(self.valid_upto) \
|
||||
<= fiscal_year.year_end_date):
|
||||
frappe.throw(_("Valid Upto date not in Fiscal Year {0}").format(frappe.bold(self.fiscal_year)))
|
||||
|
||||
def validate_supplier_against_tax_category(self):
|
||||
duplicate_certificate = frappe.db.get_value('Lower Deduction Certificate',
|
||||
{'supplier': self.supplier, 'tax_withholding_category': self.tax_withholding_category, 'name': ("!=", self.name)},
|
||||
['name', 'valid_from', 'valid_upto'], as_dict=True)
|
||||
if duplicate_certificate and self.are_dates_overlapping(duplicate_certificate):
|
||||
certificate_link = get_link_to_form('Lower Deduction Certificate', duplicate_certificate.name)
|
||||
frappe.throw(_("There is already a valid Lower Deduction Certificate {0} for Supplier {1} against category {2} for this time period.")
|
||||
.format(certificate_link, frappe.bold(self.supplier), frappe.bold(self.tax_withholding_category)))
|
||||
|
||||
def are_dates_overlapping(self,duplicate_certificate):
|
||||
valid_from = duplicate_certificate.valid_from
|
||||
valid_upto = duplicate_certificate.valid_upto
|
||||
if valid_from <= getdate(self.valid_from) <= valid_upto:
|
||||
return True
|
||||
elif valid_from <= getdate(self.valid_upto) <= valid_upto:
|
||||
return True
|
||||
elif getdate(self.valid_from) <= valid_from and valid_upto <= getdate(self.valid_upto):
|
||||
return True
|
||||
return False
|
@ -1,9 +0,0 @@
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
|
||||
class TestLowerDeductionCertificate(unittest.TestCase):
|
||||
pass
|
@ -1,67 +0,0 @@
|
||||
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Tax Exemption 80G Certificate', {
|
||||
refresh: function(frm) {
|
||||
if (frm.doc.donor) {
|
||||
frm.set_query('donation', function() {
|
||||
return {
|
||||
filters: {
|
||||
docstatus: 1,
|
||||
donor: frm.doc.donor
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
recipient: function(frm) {
|
||||
if (frm.doc.recipient === 'Donor') {
|
||||
frm.set_value({
|
||||
'member': '',
|
||||
'member_name': '',
|
||||
'member_email': '',
|
||||
'member_pan_number': '',
|
||||
'fiscal_year': '',
|
||||
'total': 0,
|
||||
'payments': []
|
||||
});
|
||||
} else {
|
||||
frm.set_value({
|
||||
'donor': '',
|
||||
'donor_name': '',
|
||||
'donor_email': '',
|
||||
'donor_pan_number': '',
|
||||
'donation': '',
|
||||
'date_of_donation': '',
|
||||
'amount': 0,
|
||||
'mode_of_payment': '',
|
||||
'razorpay_payment_id': ''
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
get_payments: function(frm) {
|
||||
frm.call({
|
||||
doc: frm.doc,
|
||||
method: 'get_payments',
|
||||
freeze: true
|
||||
});
|
||||
},
|
||||
|
||||
company: function(frm) {
|
||||
if ((frm.doc.member || frm.doc.donor) && frm.doc.company) {
|
||||
frm.call({
|
||||
doc: frm.doc,
|
||||
method: 'set_company_address',
|
||||
freeze: true
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
donation: function(frm) {
|
||||
if (frm.doc.recipient === 'Donor' && !frm.doc.donor) {
|
||||
frappe.msgprint(__('Please select donor first'));
|
||||
}
|
||||
}
|
||||
});
|
@ -1,297 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2021-02-15 12:37:21.577042",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"naming_series",
|
||||
"recipient",
|
||||
"member",
|
||||
"member_name",
|
||||
"member_email",
|
||||
"member_pan_number",
|
||||
"donor",
|
||||
"donor_name",
|
||||
"donor_email",
|
||||
"donor_pan_number",
|
||||
"column_break_4",
|
||||
"date",
|
||||
"fiscal_year",
|
||||
"section_break_11",
|
||||
"company",
|
||||
"company_address",
|
||||
"company_address_display",
|
||||
"column_break_14",
|
||||
"company_pan_number",
|
||||
"company_80g_number",
|
||||
"company_80g_wef",
|
||||
"title",
|
||||
"section_break_6",
|
||||
"get_payments",
|
||||
"payments",
|
||||
"total",
|
||||
"donation_details_section",
|
||||
"donation",
|
||||
"date_of_donation",
|
||||
"amount",
|
||||
"column_break_27",
|
||||
"mode_of_payment",
|
||||
"razorpay_payment_id"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "recipient",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Certificate Recipient",
|
||||
"options": "Member\nDonor",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Member\";",
|
||||
"fieldname": "member",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Member",
|
||||
"mandatory_depends_on": "eval:doc.recipient === \"Member\";",
|
||||
"options": "Member"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Member\";",
|
||||
"fetch_from": "member.member_name",
|
||||
"fieldname": "member_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Member Name",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Donor\";",
|
||||
"fieldname": "donor",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Donor",
|
||||
"mandatory_depends_on": "eval:doc.recipient === \"Donor\";",
|
||||
"options": "Donor"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Member\";",
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "payments",
|
||||
"fieldtype": "Table",
|
||||
"label": "Payments",
|
||||
"options": "Tax Exemption 80G Certificate Detail"
|
||||
},
|
||||
{
|
||||
"fieldname": "total",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Total",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Member\";",
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Fiscal Year",
|
||||
"options": "Fiscal Year"
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "get_payments",
|
||||
"fieldtype": "Button",
|
||||
"label": "Get Memberships"
|
||||
},
|
||||
{
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Naming Series",
|
||||
"options": "NPO-80G-.YYYY.-"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_11",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Company Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "company_address",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company Address",
|
||||
"options": "Address"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_14",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fetch_from": "company.pan_details",
|
||||
"fieldname": "company_pan_number",
|
||||
"fieldtype": "Data",
|
||||
"label": "PAN Number",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "company_address_display",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 1,
|
||||
"label": "Company Address Display",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "company.company_80g_number",
|
||||
"fieldname": "company_80g_number",
|
||||
"fieldtype": "Data",
|
||||
"label": "80G Number",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "company.with_effect_from",
|
||||
"fieldname": "company_80g_wef",
|
||||
"fieldtype": "Date",
|
||||
"label": "80G With Effect From",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Donor\";",
|
||||
"fieldname": "donation_details_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Donation Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "donation",
|
||||
"fieldtype": "Link",
|
||||
"label": "Donation",
|
||||
"mandatory_depends_on": "eval:doc.recipient === \"Donor\";",
|
||||
"options": "Donation"
|
||||
},
|
||||
{
|
||||
"fetch_from": "donation.amount",
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Amount",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "donation.mode_of_payment",
|
||||
"fieldname": "mode_of_payment",
|
||||
"fieldtype": "Link",
|
||||
"label": "Mode of Payment",
|
||||
"options": "Mode of Payment",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "donation.razorpay_payment_id",
|
||||
"fieldname": "razorpay_payment_id",
|
||||
"fieldtype": "Data",
|
||||
"label": "RazorPay Payment ID",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "donation.date",
|
||||
"fieldname": "date_of_donation",
|
||||
"fieldtype": "Date",
|
||||
"label": "Date of Donation",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_27",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Donor\";",
|
||||
"fetch_from": "donor.donor_name",
|
||||
"fieldname": "donor_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Donor Name",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Donor\";",
|
||||
"fetch_from": "donor.email",
|
||||
"fieldname": "donor_email",
|
||||
"fieldtype": "Data",
|
||||
"label": "Email",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Member\";",
|
||||
"fetch_from": "member.email_id",
|
||||
"fieldname": "member_email",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Email",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Member\";",
|
||||
"fetch_from": "member.pan_number",
|
||||
"fieldname": "member_pan_number",
|
||||
"fieldtype": "Data",
|
||||
"label": "PAN Details",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.recipient === \"Donor\";",
|
||||
"fetch_from": "donor.pan_number",
|
||||
"fieldname": "donor_pan_number",
|
||||
"fieldtype": "Data",
|
||||
"label": "PAN Details",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Title",
|
||||
"print_hide": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-02-22 00:03:34.215633",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "Tax Exemption 80G Certificate",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"search_fields": "member, member_name",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "title",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.contacts.doctype.address.address import get_company_address
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt, get_link_to_form, getdate
|
||||
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
|
||||
|
||||
class TaxExemption80GCertificate(Document):
|
||||
def validate(self):
|
||||
self.validate_date()
|
||||
self.validate_duplicates()
|
||||
self.validate_company_details()
|
||||
self.set_company_address()
|
||||
self.calculate_total()
|
||||
self.set_title()
|
||||
|
||||
def validate_date(self):
|
||||
if self.recipient == 'Member':
|
||||
if getdate(self.date):
|
||||
fiscal_year = get_fiscal_year(fiscal_year=self.fiscal_year, as_dict=True)
|
||||
|
||||
if not (fiscal_year.year_start_date <= getdate(self.date) \
|
||||
<= fiscal_year.year_end_date):
|
||||
frappe.throw(_('The Certificate Date is not in the Fiscal Year {0}').format(frappe.bold(self.fiscal_year)))
|
||||
|
||||
def validate_duplicates(self):
|
||||
if self.recipient == 'Donor':
|
||||
certificate = frappe.db.exists(self.doctype, {
|
||||
'donation': self.donation,
|
||||
'name': ('!=', self.name)
|
||||
})
|
||||
if certificate:
|
||||
frappe.throw(_('An 80G Certificate {0} already exists for the donation {1}').format(
|
||||
get_link_to_form(self.doctype, certificate), frappe.bold(self.donation)
|
||||
), title=_('Duplicate Certificate'))
|
||||
|
||||
def validate_company_details(self):
|
||||
fields = ['company_80g_number', 'with_effect_from', 'pan_details']
|
||||
company_details = frappe.db.get_value('Company', self.company, fields, as_dict=True)
|
||||
if not company_details.company_80g_number:
|
||||
frappe.throw(_('Please set the {0} for company {1}').format(frappe.bold('80G Number'),
|
||||
get_link_to_form('Company', self.company)))
|
||||
|
||||
if not company_details.pan_details:
|
||||
frappe.throw(_('Please set the {0} for company {1}').format(frappe.bold('PAN Number'),
|
||||
get_link_to_form('Company', self.company)))
|
||||
|
||||
@frappe.whitelist()
|
||||
def set_company_address(self):
|
||||
address = get_company_address(self.company)
|
||||
self.company_address = address.company_address
|
||||
self.company_address_display = address.company_address_display
|
||||
|
||||
def calculate_total(self):
|
||||
if self.recipient == 'Donor':
|
||||
return
|
||||
|
||||
total = 0
|
||||
for entry in self.payments:
|
||||
total += flt(entry.amount)
|
||||
self.total = total
|
||||
|
||||
def set_title(self):
|
||||
if self.recipient == 'Member':
|
||||
self.title = self.member_name
|
||||
else:
|
||||
self.title = self.donor_name
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_payments(self):
|
||||
if not self.member:
|
||||
frappe.throw(_('Please select a Member first.'))
|
||||
|
||||
fiscal_year = get_fiscal_year(fiscal_year=self.fiscal_year, as_dict=True)
|
||||
|
||||
memberships = frappe.db.get_all('Membership', {
|
||||
'member': self.member,
|
||||
'from_date': ['between', (fiscal_year.year_start_date, fiscal_year.year_end_date)],
|
||||
'membership_status': ('!=', 'Cancelled')
|
||||
}, ['from_date', 'amount', 'name', 'invoice', 'payment_id'], order_by='from_date')
|
||||
|
||||
if not memberships:
|
||||
frappe.msgprint(_('No Membership Payments found against the Member {0}').format(self.member))
|
||||
|
||||
total = 0
|
||||
self.payments = []
|
||||
|
||||
for doc in memberships:
|
||||
self.append('payments', {
|
||||
'date': doc.from_date,
|
||||
'amount': doc.amount,
|
||||
'invoice_id': doc.invoice,
|
||||
'razorpay_payment_id': doc.payment_id,
|
||||
'membership': doc.name
|
||||
})
|
||||
total += flt(doc.amount)
|
||||
|
||||
self.total = total
|
@ -1,106 +0,0 @@
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.utils import getdate
|
||||
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext.non_profit.doctype.donation.donation import create_donation
|
||||
from erpnext.non_profit.doctype.donation.test_donation import (
|
||||
create_donor,
|
||||
create_donor_type,
|
||||
create_mode_of_payment,
|
||||
)
|
||||
from erpnext.non_profit.doctype.member.member import create_member
|
||||
from erpnext.non_profit.doctype.membership.test_membership import make_membership, setup_membership
|
||||
|
||||
|
||||
class TestTaxExemption80GCertificate(unittest.TestCase):
|
||||
def setUp(self):
|
||||
frappe.db.sql('delete from `tabTax Exemption 80G Certificate`')
|
||||
frappe.db.sql('delete from `tabMembership`')
|
||||
create_donor_type()
|
||||
settings = frappe.get_doc('Non Profit Settings')
|
||||
settings.company = '_Test Company'
|
||||
settings.donation_company = '_Test Company'
|
||||
settings.default_donor_type = '_Test Donor'
|
||||
settings.creation_user = 'Administrator'
|
||||
settings.save()
|
||||
|
||||
company = frappe.get_doc('Company', '_Test Company')
|
||||
company.pan_details = 'BBBTI3374C'
|
||||
company.company_80g_number = 'NQ.CIT(E)I2018-19/DEL-IE28615-27062018/10087'
|
||||
company.with_effect_from = getdate()
|
||||
company.save()
|
||||
|
||||
def test_duplicate_donation_certificate(self):
|
||||
donor = create_donor()
|
||||
create_mode_of_payment()
|
||||
payment = frappe._dict({
|
||||
'amount': 100,
|
||||
'method': 'Debit Card',
|
||||
'id': 'pay_MeXAmsgeKOhq7O'
|
||||
})
|
||||
donation = create_donation(donor, payment)
|
||||
|
||||
args = frappe._dict({
|
||||
'recipient': 'Donor',
|
||||
'donor': donor.name,
|
||||
'donation': donation.name
|
||||
})
|
||||
certificate = create_80g_certificate(args)
|
||||
certificate.insert()
|
||||
|
||||
# check company details
|
||||
self.assertEqual(certificate.company_pan_number, 'BBBTI3374C')
|
||||
self.assertEqual(certificate.company_80g_number, 'NQ.CIT(E)I2018-19/DEL-IE28615-27062018/10087')
|
||||
|
||||
# check donation details
|
||||
self.assertEqual(certificate.amount, donation.amount)
|
||||
|
||||
duplicate_certificate = create_80g_certificate(args)
|
||||
# duplicate validation
|
||||
self.assertRaises(frappe.ValidationError, duplicate_certificate.insert)
|
||||
|
||||
def test_membership_80g_certificate(self):
|
||||
plan = setup_membership()
|
||||
|
||||
# make test member
|
||||
member_doc = create_member(frappe._dict({
|
||||
'fullname': "_Test_Member",
|
||||
'email': "_test_member_erpnext@example.com",
|
||||
'plan_id': plan.name
|
||||
}))
|
||||
member_doc.make_customer_and_link()
|
||||
member = member_doc.name
|
||||
|
||||
membership = make_membership(member, { "from_date": getdate() })
|
||||
invoice = membership.generate_invoice(save=True)
|
||||
|
||||
args = frappe._dict({
|
||||
'recipient': 'Member',
|
||||
'member': member,
|
||||
'fiscal_year': get_fiscal_year(getdate(), as_dict=True).get('name')
|
||||
})
|
||||
certificate = create_80g_certificate(args)
|
||||
certificate.get_payments()
|
||||
certificate.insert()
|
||||
|
||||
self.assertEqual(len(certificate.payments), 1)
|
||||
self.assertEqual(certificate.payments[0].amount, membership.amount)
|
||||
self.assertEqual(certificate.payments[0].invoice_id, invoice.name)
|
||||
|
||||
|
||||
def create_80g_certificate(args):
|
||||
certificate = frappe.get_doc({
|
||||
'doctype': 'Tax Exemption 80G Certificate',
|
||||
'recipient': args.recipient,
|
||||
'date': getdate(),
|
||||
'company': '_Test Company'
|
||||
})
|
||||
|
||||
certificate.update(args)
|
||||
|
||||
return certificate
|
@ -1,66 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2021-02-15 12:43:52.754124",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"date",
|
||||
"amount",
|
||||
"invoice_id",
|
||||
"column_break_4",
|
||||
"razorpay_payment_id",
|
||||
"membership"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "invoice_id",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice ID",
|
||||
"options": "Sales Invoice",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "razorpay_payment_id",
|
||||
"fieldtype": "Data",
|
||||
"label": "Razorpay Payment ID"
|
||||
},
|
||||
{
|
||||
"fieldname": "membership",
|
||||
"fieldtype": "Link",
|
||||
"label": "Membership",
|
||||
"options": "Membership"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-02-15 16:35:10.777587",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "Tax Exemption 80G Certificate Detail",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class TaxExemption80GCertificateDetail(Document):
|
||||
pass
|
@ -1,83 +0,0 @@
|
||||
|
||||
states = [
|
||||
'',
|
||||
'Andaman and Nicobar Islands',
|
||||
'Andhra Pradesh',
|
||||
'Arunachal Pradesh',
|
||||
'Assam',
|
||||
'Bihar',
|
||||
'Chandigarh',
|
||||
'Chhattisgarh',
|
||||
'Dadra and Nagar Haveli and Daman and Diu',
|
||||
'Delhi',
|
||||
'Goa',
|
||||
'Gujarat',
|
||||
'Haryana',
|
||||
'Himachal Pradesh',
|
||||
'Jammu and Kashmir',
|
||||
'Jharkhand',
|
||||
'Karnataka',
|
||||
'Kerala',
|
||||
'Ladakh',
|
||||
'Lakshadweep Islands',
|
||||
'Madhya Pradesh',
|
||||
'Maharashtra',
|
||||
'Manipur',
|
||||
'Meghalaya',
|
||||
'Mizoram',
|
||||
'Nagaland',
|
||||
'Odisha',
|
||||
'Other Territory',
|
||||
'Pondicherry',
|
||||
'Punjab',
|
||||
'Rajasthan',
|
||||
'Sikkim',
|
||||
'Tamil Nadu',
|
||||
'Telangana',
|
||||
'Tripura',
|
||||
'Uttar Pradesh',
|
||||
'Uttarakhand',
|
||||
'West Bengal',
|
||||
]
|
||||
|
||||
state_numbers = {
|
||||
"Andaman and Nicobar Islands": "35",
|
||||
"Andhra Pradesh": "37",
|
||||
"Arunachal Pradesh": "12",
|
||||
"Assam": "18",
|
||||
"Bihar": "10",
|
||||
"Chandigarh": "04",
|
||||
"Chhattisgarh": "22",
|
||||
"Dadra and Nagar Haveli and Daman and Diu": "26",
|
||||
"Delhi": "07",
|
||||
"Goa": "30",
|
||||
"Gujarat": "24",
|
||||
"Haryana": "06",
|
||||
"Himachal Pradesh": "02",
|
||||
"Jammu and Kashmir": "01",
|
||||
"Jharkhand": "20",
|
||||
"Karnataka": "29",
|
||||
"Kerala": "32",
|
||||
"Ladakh": "38",
|
||||
"Lakshadweep Islands": "31",
|
||||
"Madhya Pradesh": "23",
|
||||
"Maharashtra": "27",
|
||||
"Manipur": "14",
|
||||
"Meghalaya": "17",
|
||||
"Mizoram": "15",
|
||||
"Nagaland": "13",
|
||||
"Odisha": "21",
|
||||
"Other Territory": "97",
|
||||
"Pondicherry": "34",
|
||||
"Punjab": "03",
|
||||
"Rajasthan": "08",
|
||||
"Sikkim": "11",
|
||||
"Tamil Nadu": "33",
|
||||
"Telangana": "36",
|
||||
"Tripura": "16",
|
||||
"Uttar Pradesh": "09",
|
||||
"Uttarakhand": "05",
|
||||
"West Bengal": "19",
|
||||
}
|
||||
|
||||
number_state_mapping = {v: k for k, v in state_numbers.items()}
|
@ -1,31 +0,0 @@
|
||||
{{
|
||||
"SlNo": "{item.sr_no}",
|
||||
"PrdDesc": "{item.description}",
|
||||
"IsServc": "{item.is_service_item}",
|
||||
"HsnCd": "{item.gst_hsn_code}",
|
||||
"Barcde": "{item.barcode}",
|
||||
"Unit": "{item.uom}",
|
||||
"Qty": "{item.qty}",
|
||||
"FreeQty": "{item.free_qty}",
|
||||
"UnitPrice": "{item.unit_rate}",
|
||||
"TotAmt": "{item.gross_amount}",
|
||||
"Discount": "{item.discount_amount}",
|
||||
"AssAmt": "{item.taxable_value}",
|
||||
"PrdSlNo": "{item.serial_no}",
|
||||
"GstRt": "{item.tax_rate}",
|
||||
"IgstAmt": "{item.igst_amount}",
|
||||
"CgstAmt": "{item.cgst_amount}",
|
||||
"SgstAmt": "{item.sgst_amount}",
|
||||
"CesRt": "{item.cess_rate}",
|
||||
"CesAmt": "{item.cess_amount}",
|
||||
"CesNonAdvlAmt": "{item.cess_nadv_amount}",
|
||||
"StateCesRt": "{item.state_cess_rate}",
|
||||
"StateCesAmt": "{item.state_cess_amount}",
|
||||
"StateCesNonAdvlAmt": "{item.state_cess_nadv_amount}",
|
||||
"OthChrg": "{item.other_charges}",
|
||||
"TotItemVal": "{item.total_value}",
|
||||
"BchDtls": {{
|
||||
"Nm": "{item.batch_no}",
|
||||
"ExpDt": "{item.batch_expiry_date}"
|
||||
}}
|
||||
}}
|
@ -1,110 +0,0 @@
|
||||
{{
|
||||
"Version": "1.1",
|
||||
"TranDtls": {{
|
||||
"TaxSch": "{transaction_details.tax_scheme}",
|
||||
"SupTyp": "{transaction_details.supply_type}",
|
||||
"RegRev": "{transaction_details.reverse_charge}",
|
||||
"EcmGstin": "{transaction_details.ecom_gstin}",
|
||||
"IgstOnIntra": "{transaction_details.igst_on_intra}"
|
||||
}},
|
||||
"DocDtls": {{
|
||||
"Typ": "{doc_details.invoice_type}",
|
||||
"No": "{doc_details.invoice_name}",
|
||||
"Dt": "{doc_details.invoice_date}"
|
||||
}},
|
||||
"SellerDtls": {{
|
||||
"Gstin": "{seller_details.gstin}",
|
||||
"LglNm": "{seller_details.legal_name}",
|
||||
"TrdNm": "{seller_details.trade_name}",
|
||||
"Loc": "{seller_details.location}",
|
||||
"Pin": "{seller_details.pincode}",
|
||||
"Stcd": "{seller_details.state_code}",
|
||||
"Addr1": "{seller_details.address_line1}",
|
||||
"Addr2": "{seller_details.address_line2}",
|
||||
"Ph": "{seller_details.phone}",
|
||||
"Em": "{seller_details.email}"
|
||||
}},
|
||||
"BuyerDtls": {{
|
||||
"Gstin": "{buyer_details.gstin}",
|
||||
"LglNm": "{buyer_details.legal_name}",
|
||||
"TrdNm": "{buyer_details.trade_name}",
|
||||
"Addr1": "{buyer_details.address_line1}",
|
||||
"Addr2": "{buyer_details.address_line2}",
|
||||
"Loc": "{buyer_details.location}",
|
||||
"Pin": "{buyer_details.pincode}",
|
||||
"Stcd": "{buyer_details.state_code}",
|
||||
"Ph": "{buyer_details.phone}",
|
||||
"Em": "{buyer_details.email}",
|
||||
"Pos": "{buyer_details.place_of_supply}"
|
||||
}},
|
||||
"DispDtls": {{
|
||||
"Nm": "{dispatch_details.legal_name}",
|
||||
"Addr1": "{dispatch_details.address_line1}",
|
||||
"Addr2": "{dispatch_details.address_line2}",
|
||||
"Loc": "{dispatch_details.location}",
|
||||
"Pin": "{dispatch_details.pincode}",
|
||||
"Stcd": "{dispatch_details.state_code}"
|
||||
}},
|
||||
"ShipDtls": {{
|
||||
"Gstin": "{shipping_details.gstin}",
|
||||
"LglNm": "{shipping_details.legal_name}",
|
||||
"TrdNm": "{shipping_details.trader_name}",
|
||||
"Addr1": "{shipping_details.address_line1}",
|
||||
"Addr2": "{shipping_details.address_line2}",
|
||||
"Loc": "{shipping_details.location}",
|
||||
"Pin": "{shipping_details.pincode}",
|
||||
"Stcd": "{shipping_details.state_code}"
|
||||
}},
|
||||
"ItemList": [
|
||||
{item_list}
|
||||
],
|
||||
"ValDtls": {{
|
||||
"AssVal": "{invoice_value_details.base_total}",
|
||||
"CgstVal": "{invoice_value_details.total_cgst_amt}",
|
||||
"SgstVal": "{invoice_value_details.total_sgst_amt}",
|
||||
"IgstVal": "{invoice_value_details.total_igst_amt}",
|
||||
"CesVal": "{invoice_value_details.total_cess_amt}",
|
||||
"Discount": "{invoice_value_details.invoice_discount_amt}",
|
||||
"RndOffAmt": "{invoice_value_details.round_off}",
|
||||
"OthChrg": "{invoice_value_details.total_other_charges}",
|
||||
"TotInvVal": "{invoice_value_details.base_grand_total}",
|
||||
"TotInvValFc": "{invoice_value_details.grand_total}"
|
||||
}},
|
||||
"PayDtls": {{
|
||||
"Nm": "{payment_details.payee_name}",
|
||||
"AccDet": "{payment_details.account_no}",
|
||||
"Mode": "{payment_details.mode_of_payment}",
|
||||
"FinInsBr": "{payment_details.ifsc_code}",
|
||||
"PayTerm": "{payment_details.terms}",
|
||||
"PaidAmt": "{payment_details.paid_amount}",
|
||||
"PaymtDue": "{payment_details.outstanding_amount}"
|
||||
}},
|
||||
"RefDtls": {{
|
||||
"DocPerdDtls": {{
|
||||
"InvStDt": "{period_details.start_date}",
|
||||
"InvEndDt": "{period_details.end_date}"
|
||||
}},
|
||||
"PrecDocDtls": [{{
|
||||
"InvNo": "{prev_doc_details.invoice_name}",
|
||||
"InvDt": "{prev_doc_details.invoice_date}"
|
||||
}}]
|
||||
}},
|
||||
"ExpDtls": {{
|
||||
"ShipBNo": "{export_details.bill_no}",
|
||||
"ShipBDt": "{export_details.bill_date}",
|
||||
"Port": "{export_details.port}",
|
||||
"ForCur": "{export_details.foreign_curr_code}",
|
||||
"CntCode": "{export_details.country_code}",
|
||||
"ExpDuty": "{export_details.export_duty}"
|
||||
}},
|
||||
"EwbDtls": {{
|
||||
"TransId": "{eway_bill_details.gstin}",
|
||||
"TransName": "{eway_bill_details.name}",
|
||||
"TransMode": "{eway_bill_details.mode_of_transport}",
|
||||
"Distance": "{eway_bill_details.distance}",
|
||||
"TransDocNo": "{eway_bill_details.document_name}",
|
||||
"TransDocDt": "{eway_bill_details.document_date}",
|
||||
"VehNo": "{eway_bill_details.vehicle_no}",
|
||||
"VehType": "{eway_bill_details.vehicle_type}"
|
||||
}}
|
||||
}}
|
@ -1,957 +0,0 @@
|
||||
{
|
||||
"Version": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 6,
|
||||
"description": "Version of the schema"
|
||||
},
|
||||
"Irn": {
|
||||
"type": "string",
|
||||
"minLength": 64,
|
||||
"maxLength": 64,
|
||||
"description": "Invoice Reference Number"
|
||||
},
|
||||
"TranDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"TaxSch": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 10,
|
||||
"enum": ["GST"],
|
||||
"description": "GST- Goods and Services Tax Scheme"
|
||||
},
|
||||
"SupTyp": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 10,
|
||||
"enum": ["B2B", "SEZWP", "SEZWOP", "EXPWP", "EXPWOP", "DEXP"],
|
||||
"description": "Type of Supply: B2B-Business to Business, SEZWP - SEZ with payment, SEZWOP - SEZ without payment, EXPWP - Export with Payment, EXPWOP - Export without payment,DEXP - Deemed Export"
|
||||
},
|
||||
"RegRev": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 1,
|
||||
"enum": ["Y", "N"],
|
||||
"description": "Y- whether the tax liability is payable under reverse charge"
|
||||
},
|
||||
"EcmGstin": {
|
||||
"type": "string",
|
||||
"minLength": 15,
|
||||
"maxLength": 15,
|
||||
"pattern": "([0-9]{2}[0-9A-Z]{13})",
|
||||
"description": "E-Commerce GSTIN",
|
||||
"validationMsg": "E-Commerce GSTIN is invalid"
|
||||
},
|
||||
"IgstOnIntra": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 1,
|
||||
"enum": ["Y", "N"],
|
||||
"description": "Y- indicates the supply is intra state but chargeable to IGST"
|
||||
}
|
||||
},
|
||||
"required": ["TaxSch", "SupTyp"]
|
||||
},
|
||||
"DocDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Typ": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 3,
|
||||
"enum": ["INV", "CRN", "DBN"],
|
||||
"description": "Document Type"
|
||||
},
|
||||
"No": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 16,
|
||||
"pattern": "^([A-Z1-9]{1}[A-Z0-9/-]{0,15})$",
|
||||
"description": "Document Number",
|
||||
"validationMsg": "Document Number should not be starting with 0, / and -"
|
||||
},
|
||||
"Dt": {
|
||||
"type": "string",
|
||||
"minLength": 10,
|
||||
"maxLength": 10,
|
||||
"pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]",
|
||||
"description": "Document Date"
|
||||
}
|
||||
},
|
||||
"required": ["Typ", "No", "Dt"]
|
||||
},
|
||||
"SellerDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Gstin": {
|
||||
"type": "string",
|
||||
"minLength": 15,
|
||||
"maxLength": 15,
|
||||
"pattern": "([0-9]{2}[0-9A-Z]{13})",
|
||||
"description": "Supplier GSTIN",
|
||||
"validationMsg": "Company GSTIN is invalid"
|
||||
},
|
||||
"LglNm": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Legal Name"
|
||||
},
|
||||
"TrdNm": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Tradename"
|
||||
},
|
||||
"Addr1": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Address Line 1"
|
||||
},
|
||||
"Addr2": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Address Line 2"
|
||||
},
|
||||
"Loc": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 50,
|
||||
"description": "Location"
|
||||
},
|
||||
"Pin": {
|
||||
"type": "number",
|
||||
"minimum": 100000,
|
||||
"maximum": 999999,
|
||||
"description": "Pincode"
|
||||
},
|
||||
"Stcd": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 2,
|
||||
"description": "Supplier State Code"
|
||||
},
|
||||
"Ph": {
|
||||
"type": "string",
|
||||
"minLength": 6,
|
||||
"maxLength": 12,
|
||||
"description": "Phone"
|
||||
},
|
||||
"Em": {
|
||||
"type": "string",
|
||||
"minLength": 6,
|
||||
"maxLength": 100,
|
||||
"description": "Email-Id"
|
||||
}
|
||||
},
|
||||
"required": ["Gstin", "LglNm", "Addr1", "Loc", "Pin", "Stcd"]
|
||||
},
|
||||
"BuyerDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Gstin": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 15,
|
||||
"pattern": "^(([0-9]{2}[0-9A-Z]{13})|URP)$",
|
||||
"description": "Buyer GSTIN",
|
||||
"validationMsg": "Customer GSTIN is invalid"
|
||||
},
|
||||
"LglNm": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Legal Name"
|
||||
},
|
||||
"TrdNm": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Trade Name"
|
||||
},
|
||||
"Pos": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 2,
|
||||
"description": "Place of Supply State code"
|
||||
},
|
||||
"Addr1": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Address Line 1"
|
||||
},
|
||||
"Addr2": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Address Line 2"
|
||||
},
|
||||
"Loc": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Location"
|
||||
},
|
||||
"Pin": {
|
||||
"type": "number",
|
||||
"minimum": 100000,
|
||||
"maximum": 999999,
|
||||
"description": "Pincode"
|
||||
},
|
||||
"Stcd": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 2,
|
||||
"description": "Buyer State Code"
|
||||
},
|
||||
"Ph": {
|
||||
"type": "string",
|
||||
"minLength": 6,
|
||||
"maxLength": 12,
|
||||
"description": "Phone"
|
||||
},
|
||||
"Em": {
|
||||
"type": "string",
|
||||
"minLength": 6,
|
||||
"maxLength": 100,
|
||||
"description": "Email-Id"
|
||||
}
|
||||
},
|
||||
"required": ["Gstin", "LglNm", "Pos", "Addr1", "Loc", "Stcd"]
|
||||
},
|
||||
"DispDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Nm": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Dispatch Address Name"
|
||||
},
|
||||
"Addr1": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Address Line 1"
|
||||
},
|
||||
"Addr2": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Address Line 2"
|
||||
},
|
||||
"Loc": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Location"
|
||||
},
|
||||
"Pin": {
|
||||
"type": "number",
|
||||
"minimum": 100000,
|
||||
"maximum": 999999,
|
||||
"description": "Pincode"
|
||||
},
|
||||
"Stcd": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 2,
|
||||
"description": "State Code"
|
||||
}
|
||||
},
|
||||
"required": ["Nm", "Addr1", "Loc", "Pin", "Stcd"]
|
||||
},
|
||||
"ShipDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Gstin": {
|
||||
"type": "string",
|
||||
"maxLength": 15,
|
||||
"minLength": 3,
|
||||
"pattern": "^(([0-9]{2}[0-9A-Z]{13})|URP)$",
|
||||
"description": "Shipping Address GSTIN",
|
||||
"validationMsg": "Shipping Address GSTIN is invalid"
|
||||
},
|
||||
"LglNm": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Legal Name"
|
||||
},
|
||||
"TrdNm": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Trade Name"
|
||||
},
|
||||
"Addr1": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Address Line 1"
|
||||
},
|
||||
"Addr2": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Address Line 2"
|
||||
},
|
||||
"Loc": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Location"
|
||||
},
|
||||
"Pin": {
|
||||
"type": "number",
|
||||
"minimum": 100000,
|
||||
"maximum": 999999,
|
||||
"description": "Pincode"
|
||||
},
|
||||
"Stcd": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 2,
|
||||
"description": "State Code"
|
||||
}
|
||||
},
|
||||
"required": ["LglNm", "Addr1", "Loc", "Pin", "Stcd"]
|
||||
},
|
||||
"ItemList": {
|
||||
"type": "Array",
|
||||
"properties": {
|
||||
"SlNo": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 6,
|
||||
"description": "Serial No. of Item"
|
||||
},
|
||||
"PrdDesc": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 300,
|
||||
"description": "Item Name"
|
||||
},
|
||||
"IsServc": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 1,
|
||||
"enum": ["Y", "N"],
|
||||
"description": "Is Service Item"
|
||||
},
|
||||
"HsnCd": {
|
||||
"type": "string",
|
||||
"minLength": 4,
|
||||
"maxLength": 8,
|
||||
"description": "HSN Code"
|
||||
},
|
||||
"Barcde": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 30,
|
||||
"description": "Barcode"
|
||||
},
|
||||
"Qty": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 9999999999.999,
|
||||
"description": "Quantity"
|
||||
},
|
||||
"FreeQty": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 9999999999.999,
|
||||
"description": "Free Quantity"
|
||||
},
|
||||
"Unit": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 8,
|
||||
"description": "UOM"
|
||||
},
|
||||
"UnitPrice": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.999,
|
||||
"description": "Rate"
|
||||
},
|
||||
"TotAmt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "Gross Amount"
|
||||
},
|
||||
"Discount": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "Discount"
|
||||
},
|
||||
"PreTaxVal": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "Pre tax value"
|
||||
},
|
||||
"AssAmt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "Taxable Value"
|
||||
},
|
||||
"GstRt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999.999,
|
||||
"description": "GST Rate"
|
||||
},
|
||||
"IgstAmt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "IGST Amount"
|
||||
},
|
||||
"CgstAmt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "CGST Amount"
|
||||
},
|
||||
"SgstAmt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "SGST Amount"
|
||||
},
|
||||
"CesRt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999.999,
|
||||
"description": "Cess Rate"
|
||||
},
|
||||
"CesAmt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "Cess Amount (Advalorem)"
|
||||
},
|
||||
"CesNonAdvlAmt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "Cess Amount (Non-Advalorem)"
|
||||
},
|
||||
"StateCesRt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999.999,
|
||||
"description": "State CESS Rate"
|
||||
},
|
||||
"StateCesAmt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "State CESS Amount"
|
||||
},
|
||||
"StateCesNonAdvlAmt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "State CESS Amount (Non Advalorem)"
|
||||
},
|
||||
"OthChrg": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "Other Charges"
|
||||
},
|
||||
"TotItemVal": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "Total Item Value"
|
||||
},
|
||||
"OrdLineRef": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 50,
|
||||
"description": "Order line reference"
|
||||
},
|
||||
"OrgCntry": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 2,
|
||||
"description": "Origin Country"
|
||||
},
|
||||
"PrdSlNo": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 20,
|
||||
"description": "Serial number"
|
||||
},
|
||||
"BchDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Nm": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 20,
|
||||
"description": "Batch number"
|
||||
},
|
||||
"ExpDt": {
|
||||
"type": "string",
|
||||
"maxLength": 10,
|
||||
"minLength": 10,
|
||||
"pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]",
|
||||
"description": "Batch Expiry Date"
|
||||
},
|
||||
"WrDt": {
|
||||
"type": "string",
|
||||
"maxLength": 10,
|
||||
"minLength": 10,
|
||||
"pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]",
|
||||
"description": "Warranty Date"
|
||||
}
|
||||
},
|
||||
"required": ["Nm"]
|
||||
},
|
||||
"AttribDtls": {
|
||||
"type": "Array",
|
||||
"Attribute": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Nm": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Attribute name of the item"
|
||||
},
|
||||
"Val": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Attribute value of the item"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"SlNo",
|
||||
"IsServc",
|
||||
"HsnCd",
|
||||
"UnitPrice",
|
||||
"TotAmt",
|
||||
"AssAmt",
|
||||
"GstRt",
|
||||
"TotItemVal"
|
||||
]
|
||||
},
|
||||
"ValDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"AssVal": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Total Assessable value of all items"
|
||||
},
|
||||
"CgstVal": {
|
||||
"type": "number",
|
||||
"maximum": 99999999999999.99,
|
||||
"minimum": 0,
|
||||
"description": "Total CGST value of all items"
|
||||
},
|
||||
"SgstVal": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Total SGST value of all items"
|
||||
},
|
||||
"IgstVal": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Total IGST value of all items"
|
||||
},
|
||||
"CesVal": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Total CESS value of all items"
|
||||
},
|
||||
"StCesVal": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Total State CESS value of all items"
|
||||
},
|
||||
"Discount": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Invoice Discount"
|
||||
},
|
||||
"OthChrg": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Other Charges"
|
||||
},
|
||||
"RndOffAmt": {
|
||||
"type": "number",
|
||||
"minimum": -99.99,
|
||||
"maximum": 99.99,
|
||||
"description": "Rounded off Amount"
|
||||
},
|
||||
"TotInvVal": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Final Invoice Value "
|
||||
},
|
||||
"TotInvValFc": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Final Invoice value in Foreign Currency"
|
||||
}
|
||||
},
|
||||
"required": ["AssVal", "TotInvVal"]
|
||||
},
|
||||
"PayDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Nm": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Payee Name"
|
||||
},
|
||||
"AccDet": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 18,
|
||||
"description": "Bank Account Number of Payee"
|
||||
},
|
||||
"Mode": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 18,
|
||||
"description": "Mode of Payment"
|
||||
},
|
||||
"FinInsBr": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 11,
|
||||
"description": "Branch or IFSC code"
|
||||
},
|
||||
"PayTerm": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Terms of Payment"
|
||||
},
|
||||
"PayInstr": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Payment Instruction"
|
||||
},
|
||||
"CrTrn": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Credit Transfer"
|
||||
},
|
||||
"DirDr": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 100,
|
||||
"description": "Direct Debit"
|
||||
},
|
||||
"CrDay": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 9999,
|
||||
"description": "Credit Days"
|
||||
},
|
||||
"PaidAmt": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Advance Amount"
|
||||
},
|
||||
"PaymtDue": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 99999999999999.99,
|
||||
"description": "Outstanding Amount"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RefDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"InvRm": {
|
||||
"type": "string",
|
||||
"maxLength": 100,
|
||||
"minLength": 3,
|
||||
"pattern": "^[0-9A-Za-z/-]{3,100}$",
|
||||
"description": "Remarks/Note"
|
||||
},
|
||||
"DocPerdDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"InvStDt": {
|
||||
"type": "string",
|
||||
"maxLength": 10,
|
||||
"minLength": 10,
|
||||
"pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]",
|
||||
"description": "Invoice Period Start Date"
|
||||
},
|
||||
"InvEndDt": {
|
||||
"type": "string",
|
||||
"maxLength": 10,
|
||||
"minLength": 10,
|
||||
"pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]",
|
||||
"description": "Invoice Period End Date"
|
||||
}
|
||||
},
|
||||
"required": ["InvStDt ", "InvEndDt "]
|
||||
},
|
||||
"PrecDocDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"InvNo": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 16,
|
||||
"pattern": "^[1-9A-Z]{1}[0-9A-Z/-]{1,15}$",
|
||||
"description": "Reference of Original Invoice"
|
||||
},
|
||||
"InvDt": {
|
||||
"type": "string",
|
||||
"maxLength": 10,
|
||||
"minLength": 10,
|
||||
"pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]",
|
||||
"description": "Date of Orginal Invoice"
|
||||
},
|
||||
"OthRefNo": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 20,
|
||||
"description": "Other Reference"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["InvNo", "InvDt"],
|
||||
"ContrDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"RecAdvRefr": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 20,
|
||||
"pattern": "^([0-9A-Za-z/-]){1,20}$",
|
||||
"description": "Receipt Advice No."
|
||||
},
|
||||
"RecAdvDt": {
|
||||
"type": "string",
|
||||
"minLength": 10,
|
||||
"maxLength": 10,
|
||||
"pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]",
|
||||
"description": "Date of receipt advice"
|
||||
},
|
||||
"TendRefr": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 20,
|
||||
"pattern": "^([0-9A-Za-z/-]){1,20}$",
|
||||
"description": "Lot/Batch Reference No."
|
||||
},
|
||||
"ContrRefr": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 20,
|
||||
"pattern": "^([0-9A-Za-z/-]){1,20}$",
|
||||
"description": "Contract Reference Number"
|
||||
},
|
||||
"ExtRefr": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 20,
|
||||
"pattern": "^([0-9A-Za-z/-]){1,20}$",
|
||||
"description": "Any other reference"
|
||||
},
|
||||
"ProjRefr": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 20,
|
||||
"pattern": "^([0-9A-Za-z/-]){1,20}$",
|
||||
"description": "Project Reference Number"
|
||||
},
|
||||
"PORefr": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 16,
|
||||
"pattern": "^([0-9A-Za-z/-]){1,16}$",
|
||||
"description": "PO Reference Number"
|
||||
},
|
||||
"PORefDt": {
|
||||
"type": "string",
|
||||
"minLength": 10,
|
||||
"maxLength": 10,
|
||||
"pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]",
|
||||
"description": "PO Reference date"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"AddlDocDtls": {
|
||||
"type": "Array",
|
||||
"properties": {
|
||||
"Url": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Supporting document URL"
|
||||
},
|
||||
"Docs": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 1000,
|
||||
"description": "Supporting document in Base64 Format"
|
||||
},
|
||||
"Info": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 1000,
|
||||
"description": "Any additional information"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"ExpDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ShipBNo": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 20,
|
||||
"description": "Shipping Bill No."
|
||||
},
|
||||
"ShipBDt": {
|
||||
"type": "string",
|
||||
"minLength": 10,
|
||||
"maxLength": 10,
|
||||
"pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]",
|
||||
"description": "Shipping Bill Date"
|
||||
},
|
||||
"Port": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 10,
|
||||
"pattern": "^[0-9A-Za-z]{2,10}$",
|
||||
"description": "Port Code. Refer the master"
|
||||
},
|
||||
"RefClm": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 1,
|
||||
"description": "Claiming Refund. Y/N"
|
||||
},
|
||||
"ForCur": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 16,
|
||||
"description": "Additional Currency Code. Refer the master"
|
||||
},
|
||||
"CntCode": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 2,
|
||||
"description": "Country Code. Refer the master"
|
||||
},
|
||||
"ExpDuty": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 999999999999.99,
|
||||
"description": "Export Duty"
|
||||
}
|
||||
}
|
||||
},
|
||||
"EwbDtls": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"TransId": {
|
||||
"type": "string",
|
||||
"minLength": 15,
|
||||
"maxLength": 15,
|
||||
"description": "Transporter GSTIN"
|
||||
},
|
||||
"TransName": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "Transporter Name"
|
||||
},
|
||||
"TransMode": {
|
||||
"type": "string",
|
||||
"maxLength": 1,
|
||||
"minLength": 1,
|
||||
"enum": ["1", "2", "3", "4"],
|
||||
"description": "Mode of Transport"
|
||||
},
|
||||
"Distance": {
|
||||
"type": "number",
|
||||
"minimum": 1,
|
||||
"maximum": 9999,
|
||||
"description": "Distance"
|
||||
},
|
||||
"TransDocNo": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 15,
|
||||
"pattern": "^([0-9A-Z/-]){1,15}$",
|
||||
"description": "Tranport Document Number",
|
||||
"validationMsg": "Transport Receipt No is invalid"
|
||||
},
|
||||
"TransDocDt": {
|
||||
"type": "string",
|
||||
"minLength": 10,
|
||||
"maxLength": 10,
|
||||
"pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]",
|
||||
"description": "Transport Document Date"
|
||||
},
|
||||
"VehNo": {
|
||||
"type": "string",
|
||||
"minLength": 4,
|
||||
"maxLength": 20,
|
||||
"description": "Vehicle Number"
|
||||
},
|
||||
"VehType": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 1,
|
||||
"enum": ["O", "R"],
|
||||
"description": "Vehicle Type"
|
||||
}
|
||||
},
|
||||
"required": ["Distance"]
|
||||
},
|
||||
"required": [
|
||||
"Version",
|
||||
"TranDtls",
|
||||
"DocDtls",
|
||||
"SellerDtls",
|
||||
"BuyerDtls",
|
||||
"ItemList",
|
||||
"ValDtls"
|
||||
]
|
||||
}
|
@ -1,292 +0,0 @@
|
||||
erpnext.setup_einvoice_actions = (doctype) => {
|
||||
frappe.ui.form.on(doctype, {
|
||||
async refresh(frm) {
|
||||
if (frm.doc.docstatus == 2) return;
|
||||
|
||||
const res = await frappe.call({
|
||||
method: 'erpnext.regional.india.e_invoice.utils.validate_eligibility',
|
||||
args: { doc: frm.doc }
|
||||
});
|
||||
const invoice_eligible = res.message;
|
||||
|
||||
if (!invoice_eligible) return;
|
||||
|
||||
const { doctype, irn, irn_cancelled, ewaybill, eway_bill_cancelled, name, __unsaved } = frm.doc;
|
||||
|
||||
const add_custom_button = (label, action) => {
|
||||
if (!frm.custom_buttons[label]) {
|
||||
frm.add_custom_button(label, action, __('E Invoicing'));
|
||||
}
|
||||
};
|
||||
|
||||
if (!irn && !__unsaved) {
|
||||
const action = () => {
|
||||
if (frm.doc.__unsaved) {
|
||||
frappe.throw(__('Please save the document to generate IRN.'));
|
||||
}
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.e_invoice.utils.get_einvoice',
|
||||
args: { doctype, docname: name },
|
||||
freeze: true,
|
||||
callback: (res) => {
|
||||
const einvoice = res.message;
|
||||
show_einvoice_preview(frm, einvoice);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
add_custom_button(__("Generate IRN"), action);
|
||||
}
|
||||
|
||||
if (irn && !irn_cancelled && !ewaybill) {
|
||||
const fields = [
|
||||
{
|
||||
"label": "Reason",
|
||||
"fieldname": "reason",
|
||||
"fieldtype": "Select",
|
||||
"reqd": 1,
|
||||
"default": "1-Duplicate",
|
||||
"options": ["1-Duplicate", "2-Data Entry Error", "3-Order Cancelled", "4-Other"]
|
||||
},
|
||||
{
|
||||
"label": "Remark",
|
||||
"fieldname": "remark",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1
|
||||
}
|
||||
];
|
||||
const action = () => {
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __("Cancel IRN"),
|
||||
fields: fields,
|
||||
primary_action: function() {
|
||||
const data = d.get_values();
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.e_invoice.utils.cancel_irn',
|
||||
args: {
|
||||
doctype,
|
||||
docname: name,
|
||||
irn: irn,
|
||||
reason: data.reason.split('-')[0],
|
||||
remark: data.remark
|
||||
},
|
||||
freeze: true,
|
||||
callback: () => frm.reload_doc() || d.hide(),
|
||||
error: () => d.hide()
|
||||
});
|
||||
},
|
||||
primary_action_label: __('Submit')
|
||||
});
|
||||
d.show();
|
||||
};
|
||||
add_custom_button(__("Cancel IRN"), action);
|
||||
}
|
||||
|
||||
if (irn && !irn_cancelled && !ewaybill) {
|
||||
const action = () => {
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Generate E-Way Bill'),
|
||||
size: "large",
|
||||
fields: get_ewaybill_fields(frm),
|
||||
primary_action: function() {
|
||||
const data = d.get_values();
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.e_invoice.utils.generate_eway_bill',
|
||||
args: {
|
||||
doctype,
|
||||
docname: name,
|
||||
irn,
|
||||
...data
|
||||
},
|
||||
freeze: true,
|
||||
callback: () => frm.reload_doc() || d.hide(),
|
||||
error: () => d.hide()
|
||||
});
|
||||
},
|
||||
primary_action_label: __('Submit')
|
||||
});
|
||||
d.show();
|
||||
};
|
||||
|
||||
add_custom_button(__("Generate E-Way Bill"), action);
|
||||
}
|
||||
|
||||
if (irn && ewaybill && !irn_cancelled && !eway_bill_cancelled) {
|
||||
const action = () => {
|
||||
let message = __('Cancellation of e-way bill is currently not supported.') + ' ';
|
||||
message += '<br><br>';
|
||||
message += __('You must first use the portal to cancel the e-way bill and then update the cancelled status in the ERPNext system.');
|
||||
|
||||
const dialog = frappe.msgprint({
|
||||
title: __('Update E-Way Bill Cancelled Status?'),
|
||||
message: message,
|
||||
indicator: 'orange',
|
||||
primary_action: {
|
||||
action: function() {
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.e_invoice.utils.cancel_eway_bill',
|
||||
args: { doctype, docname: name },
|
||||
freeze: true,
|
||||
callback: () => frm.reload_doc() || dialog.hide()
|
||||
});
|
||||
}
|
||||
},
|
||||
primary_action_label: __('Yes')
|
||||
});
|
||||
};
|
||||
add_custom_button(__("Cancel E-Way Bill"), action);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const get_ewaybill_fields = (frm) => {
|
||||
return [
|
||||
{
|
||||
'fieldname': 'transporter',
|
||||
'label': 'Transporter',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Supplier',
|
||||
'default': frm.doc.transporter
|
||||
},
|
||||
{
|
||||
'fieldname': 'gst_transporter_id',
|
||||
'label': 'GST Transporter ID',
|
||||
'fieldtype': 'Data',
|
||||
'fetch_from': 'transporter.gst_transporter_id',
|
||||
'default': frm.doc.gst_transporter_id
|
||||
},
|
||||
{
|
||||
'fieldname': 'driver',
|
||||
'label': 'Driver',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Driver',
|
||||
'default': frm.doc.driver
|
||||
},
|
||||
{
|
||||
'fieldname': 'lr_no',
|
||||
'label': 'Transport Receipt No',
|
||||
'fieldtype': 'Data',
|
||||
'default': frm.doc.lr_no
|
||||
},
|
||||
{
|
||||
'fieldname': 'vehicle_no',
|
||||
'label': 'Vehicle No',
|
||||
'fieldtype': 'Data',
|
||||
'default': frm.doc.vehicle_no
|
||||
},
|
||||
{
|
||||
'fieldname': 'distance',
|
||||
'label': 'Distance (in km)',
|
||||
'fieldtype': 'Float',
|
||||
'default': frm.doc.distance
|
||||
},
|
||||
{
|
||||
'fieldname': 'transporter_col_break',
|
||||
'fieldtype': 'Column Break',
|
||||
},
|
||||
{
|
||||
'fieldname': 'transporter_name',
|
||||
'label': 'Transporter Name',
|
||||
'fieldtype': 'Data',
|
||||
'fetch_from': 'transporter.name',
|
||||
'read_only': 1,
|
||||
'default': frm.doc.transporter_name
|
||||
},
|
||||
{
|
||||
'fieldname': 'mode_of_transport',
|
||||
'label': 'Mode of Transport',
|
||||
'fieldtype': 'Select',
|
||||
'options': `\nRoad\nAir\nRail\nShip`,
|
||||
'default': frm.doc.mode_of_transport
|
||||
},
|
||||
{
|
||||
'fieldname': 'driver_name',
|
||||
'label': 'Driver Name',
|
||||
'fieldtype': 'Data',
|
||||
'fetch_from': 'driver.full_name',
|
||||
'read_only': 1,
|
||||
'default': frm.doc.driver_name
|
||||
},
|
||||
{
|
||||
'fieldname': 'lr_date',
|
||||
'label': 'Transport Receipt Date',
|
||||
'fieldtype': 'Date',
|
||||
'default': frm.doc.lr_date
|
||||
},
|
||||
{
|
||||
'fieldname': 'gst_vehicle_type',
|
||||
'label': 'GST Vehicle Type',
|
||||
'fieldtype': 'Select',
|
||||
'options': `Regular\nOver Dimensional Cargo (ODC)`,
|
||||
'depends_on': 'eval:(doc.mode_of_transport === "Road")',
|
||||
'default': frm.doc.gst_vehicle_type
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
const request_irn_generation = (frm) => {
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.e_invoice.utils.generate_irn',
|
||||
args: { doctype: frm.doc.doctype, docname: frm.doc.name },
|
||||
freeze: true,
|
||||
callback: () => frm.reload_doc()
|
||||
});
|
||||
};
|
||||
|
||||
const get_preview_dialog = (frm, action) => {
|
||||
const dialog = new frappe.ui.Dialog({
|
||||
title: __("Preview"),
|
||||
size: "large",
|
||||
fields: [
|
||||
{
|
||||
"label": "Preview",
|
||||
"fieldname": "preview_html",
|
||||
"fieldtype": "HTML"
|
||||
}
|
||||
],
|
||||
primary_action: () => action(frm) || dialog.hide(),
|
||||
primary_action_label: __('Generate IRN')
|
||||
});
|
||||
return dialog;
|
||||
};
|
||||
|
||||
const show_einvoice_preview = (frm, einvoice) => {
|
||||
const preview_dialog = get_preview_dialog(frm, request_irn_generation);
|
||||
|
||||
// initialize e-invoice fields
|
||||
einvoice["Irn"] = einvoice["AckNo"] = ''; einvoice["AckDt"] = frappe.datetime.nowdate();
|
||||
frm.doc.signed_einvoice = JSON.stringify(einvoice);
|
||||
|
||||
// initialize preview wrapper
|
||||
const $preview_wrapper = preview_dialog.get_field("preview_html").$wrapper;
|
||||
$preview_wrapper.html(
|
||||
`<div>
|
||||
<div class="print-preview">
|
||||
<div class="print-format"></div>
|
||||
</div>
|
||||
<div class="page-break-message text-muted text-center text-medium margin-top"></div>
|
||||
</div>`
|
||||
);
|
||||
|
||||
frappe.call({
|
||||
method: "frappe.www.printview.get_html_and_style",
|
||||
args: {
|
||||
doc: frm.doc,
|
||||
print_format: "GST E-Invoice",
|
||||
no_letterhead: 1
|
||||
},
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
$preview_wrapper.find(".print-format").html(r.message.html);
|
||||
const style = `
|
||||
.print-format { box-shadow: 0px 0px 5px rgba(0,0,0,0.2); padding: 0.30in; min-height: 80vh; }
|
||||
.print-preview { min-height: 0px; }
|
||||
.modal-dialog { width: 720px; }`;
|
||||
|
||||
frappe.dom.set_style(style, "custom-print-style");
|
||||
preview_dialog.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,177 +0,0 @@
|
||||
[
|
||||
{
|
||||
"state_number": "33",
|
||||
"state_code": "TN",
|
||||
"state_name": "Tamil Nadu"
|
||||
},
|
||||
{
|
||||
"state_number": "35",
|
||||
"state_code": "UP",
|
||||
"state_name": "Uttar Pradesh"
|
||||
},
|
||||
{
|
||||
"state_number": "05",
|
||||
"state_code": "UT",
|
||||
"state_name": "Uttarakhand"
|
||||
},
|
||||
{
|
||||
"state_number": "19",
|
||||
"state_code": "WB",
|
||||
"state_name": "West Bengal"
|
||||
},
|
||||
{
|
||||
"state_number": "16",
|
||||
"state_code": "TR",
|
||||
"state_name": "Tripura"
|
||||
},
|
||||
{
|
||||
"state_number": "36",
|
||||
"state_code": "TS",
|
||||
"state_name": "Telangana"
|
||||
},
|
||||
{
|
||||
"state_number": "11",
|
||||
"state_code": "SK",
|
||||
"state_name": "Sikkim"
|
||||
},
|
||||
{
|
||||
"state_number": "08",
|
||||
"state_code": "RJ",
|
||||
"state_name": "Rajasthan"
|
||||
},
|
||||
{
|
||||
"state_number": "03",
|
||||
"state_code": "PB",
|
||||
"state_name": "Punjab"
|
||||
},
|
||||
{
|
||||
"state_number": "34",
|
||||
"state_code": "PY",
|
||||
"state_name": "Pondicherry"
|
||||
},
|
||||
{
|
||||
"state_number": "21",
|
||||
"state_code": "OR",
|
||||
"state_name": "Odisha"
|
||||
},
|
||||
{
|
||||
"state_number": "13",
|
||||
"state_code": "NL",
|
||||
"state_name": "Nagaland"
|
||||
},
|
||||
{
|
||||
"state_number": "15",
|
||||
"state_code": "MI",
|
||||
"state_name": "Mizoram"
|
||||
},
|
||||
{
|
||||
"state_number": "17",
|
||||
"state_code": "ME",
|
||||
"state_name": "Meghalaya"
|
||||
},
|
||||
{
|
||||
"state_number": "14",
|
||||
"state_code": "MN",
|
||||
"state_name": "Manipur"
|
||||
},
|
||||
{
|
||||
"state_number": "27",
|
||||
"state_code": "MH",
|
||||
"state_name": "Maharashtra"
|
||||
},
|
||||
{
|
||||
"state_number": "23",
|
||||
"state_code": "MP",
|
||||
"state_name": "Madhya Pradesh"
|
||||
},
|
||||
{
|
||||
"state_number": "31",
|
||||
"state_code": "LD",
|
||||
"state_name": "Lakshadweep Islands"
|
||||
},
|
||||
{
|
||||
"state_number": "32",
|
||||
"state_code": "KL",
|
||||
"state_name": "Kerala"
|
||||
},
|
||||
{
|
||||
"state_number": "29",
|
||||
"state_code": "KA",
|
||||
"state_name": "Karnataka"
|
||||
},
|
||||
{
|
||||
"state_number": "20",
|
||||
"state_code": "JH",
|
||||
"state_name": "Jharkhand"
|
||||
},
|
||||
{
|
||||
"state_number": "01",
|
||||
"state_code": "JK",
|
||||
"state_name": "Jammu and Kashmir"
|
||||
},
|
||||
{
|
||||
"state_number": "02",
|
||||
"state_code": "HP",
|
||||
"state_name": "Himachal Pradesh"
|
||||
},
|
||||
{
|
||||
"state_number": "06",
|
||||
"state_code": "HR",
|
||||
"state_name": "Haryana"
|
||||
},
|
||||
{
|
||||
"state_number": "24",
|
||||
"state_code": "GJ",
|
||||
"state_name": "Gujarat"
|
||||
},
|
||||
{
|
||||
"state_number": "30",
|
||||
"state_code": "GA",
|
||||
"state_name": "Goa"
|
||||
},
|
||||
{
|
||||
"state_number": "07",
|
||||
"state_code": "DL",
|
||||
"state_name": "Delhi"
|
||||
},
|
||||
{
|
||||
"state_number": "26",
|
||||
"state_code": "DN",
|
||||
"state_name": "Dadra and Nagar Haveli and Daman and Diu"
|
||||
},
|
||||
{
|
||||
"state_number": "22",
|
||||
"state_code": "CT",
|
||||
"state_name": "Chhattisgarh"
|
||||
},
|
||||
{
|
||||
"state_number": "04",
|
||||
"state_code": "CH",
|
||||
"state_name": "Chandigarh"
|
||||
},
|
||||
{
|
||||
"state_number": "10",
|
||||
"state_code": "BH",
|
||||
"state_name": "Bihar"
|
||||
},
|
||||
{
|
||||
"state_number": "18",
|
||||
"state_code": "AS",
|
||||
"state_name": "Assam"
|
||||
},
|
||||
{
|
||||
"state_number": "12",
|
||||
"state_code": "AR",
|
||||
"state_name": "Arunachal Pradesh"
|
||||
},
|
||||
{
|
||||
"state_number": "37",
|
||||
"state_code": "AD",
|
||||
"state_name": "Andhra Pradesh (New)"
|
||||
},
|
||||
{
|
||||
"state_number": "38",
|
||||
"state_code": "LA",
|
||||
"state_name": "Ladakh"
|
||||
}
|
||||
]
|
File diff suppressed because it is too large
Load Diff
@ -1,25 +0,0 @@
|
||||
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(); });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,51 +0,0 @@
|
||||
erpnext.setup_auto_gst_taxation = (doctype) => {
|
||||
frappe.ui.form.on(doctype, {
|
||||
company_address: function(frm) {
|
||||
frm.trigger('get_tax_template');
|
||||
},
|
||||
shipping_address: function(frm) {
|
||||
frm.trigger('get_tax_template');
|
||||
},
|
||||
supplier_address: function(frm) {
|
||||
frm.trigger('get_tax_template');
|
||||
},
|
||||
tax_category: function(frm) {
|
||||
frm.trigger('get_tax_template');
|
||||
},
|
||||
customer_address: function(frm) {
|
||||
frm.trigger('get_tax_template');
|
||||
},
|
||||
get_tax_template: function(frm) {
|
||||
if (!frm.doc.company) return;
|
||||
|
||||
let party_details = {
|
||||
'shipping_address': frm.doc.shipping_address || '',
|
||||
'shipping_address_name': frm.doc.shipping_address_name || '',
|
||||
'customer_address': frm.doc.customer_address || '',
|
||||
'supplier_address': frm.doc.supplier_address,
|
||||
'customer': frm.doc.customer,
|
||||
'supplier': frm.doc.supplier,
|
||||
'supplier_gstin': frm.doc.supplier_gstin,
|
||||
'company_gstin': frm.doc.company_gstin,
|
||||
'tax_category': frm.doc.tax_category
|
||||
};
|
||||
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.utils.get_regional_address_details',
|
||||
args: {
|
||||
party_details: JSON.stringify(party_details),
|
||||
doctype: frm.doc.doctype,
|
||||
company: frm.doc.company
|
||||
},
|
||||
debounce: 2000,
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
frm.set_value('taxes_and_charges', r.message.taxes_and_charges);
|
||||
frm.set_value('taxes', r.message.taxes);
|
||||
frm.set_value('place_of_supply', r.message.place_of_supply);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import frappe
|
||||
|
||||
from erpnext.regional.india.utils import validate_document_name
|
||||
|
||||
|
||||
class TestIndiaUtils(unittest.TestCase):
|
||||
@patch("frappe.get_cached_value")
|
||||
def test_validate_document_name(self, mock_get_cached):
|
||||
mock_get_cached.return_value = "India" # mock country
|
||||
posting_date = "2021-05-01"
|
||||
|
||||
invalid_names = ["SI$1231", "012345678901234567", "SI 2020 05",
|
||||
"SI.2020.0001", "PI2021 - 001"]
|
||||
for name in invalid_names:
|
||||
doc = frappe._dict(name=name, posting_date=posting_date)
|
||||
self.assertRaises(frappe.ValidationError, validate_document_name, doc)
|
||||
|
||||
valid_names = ["012345678901236", "SI/2020/0001", "SI/2020-0001",
|
||||
"2020-PI-0001", "PI2020-0001"]
|
||||
for name in valid_names:
|
||||
doc = frappe._dict(name=name, posting_date=posting_date)
|
||||
try:
|
||||
validate_document_name(doc)
|
||||
except frappe.ValidationError:
|
||||
self.fail("Valid name {} throwing error".format(name))
|
||||
|
||||
@patch("frappe.get_cached_value")
|
||||
def test_validate_document_name_not_india(self, mock_get_cached):
|
||||
mock_get_cached.return_value = "Not India"
|
||||
doc = frappe._dict(name="SI$123", posting_date="2021-05-01")
|
||||
|
||||
try:
|
||||
validate_document_name(doc)
|
||||
except frappe.ValidationError:
|
||||
self.fail("Regional validation related to India are being applied to other countries")
|
@ -1,893 +0,0 @@
|
||||
import json
|
||||
import re
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.utils import get_fetch_values
|
||||
from frappe.utils import cint, cstr, date_diff, flt, getdate, nowdate
|
||||
|
||||
from erpnext.controllers.accounts_controller import get_taxes_and_charges
|
||||
from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount
|
||||
from erpnext.hr.utils import get_salary_assignment
|
||||
from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip
|
||||
from erpnext.regional.india import number_state_mapping, state_numbers, states
|
||||
|
||||
GST_INVOICE_NUMBER_FORMAT = re.compile(r"^[a-zA-Z0-9\-/]+$") #alphanumeric and - /
|
||||
GSTIN_FORMAT = re.compile("^[0-9]{2}[A-Z]{4}[0-9A-Z]{1}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[1-9A-Z]{1}[0-9A-Z]{1}$")
|
||||
GSTIN_UIN_FORMAT = re.compile("^[0-9]{4}[A-Z]{3}[0-9]{5}[0-9A-Z]{3}")
|
||||
PAN_NUMBER_FORMAT = re.compile("[A-Z]{5}[0-9]{4}[A-Z]{1}")
|
||||
|
||||
|
||||
def validate_gstin_for_india(doc, method):
|
||||
if hasattr(doc, 'gst_state') and doc.gst_state:
|
||||
doc.gst_state_number = state_numbers[doc.gst_state]
|
||||
if not hasattr(doc, 'gstin') or not doc.gstin:
|
||||
return
|
||||
|
||||
gst_category = []
|
||||
|
||||
if hasattr(doc, 'gst_category'):
|
||||
if len(doc.links):
|
||||
link_doctype = doc.links[0].get("link_doctype")
|
||||
link_name = doc.links[0].get("link_name")
|
||||
|
||||
if link_doctype in ["Customer", "Supplier"]:
|
||||
gst_category = frappe.db.get_value(link_doctype, {'name': link_name}, ['gst_category'])
|
||||
|
||||
doc.gstin = doc.gstin.upper().strip()
|
||||
if not doc.gstin or doc.gstin == 'NA':
|
||||
return
|
||||
|
||||
if len(doc.gstin) != 15:
|
||||
frappe.throw(_("A GSTIN must have 15 characters."), title=_("Invalid GSTIN"))
|
||||
|
||||
if gst_category and gst_category == 'UIN Holders':
|
||||
if not GSTIN_UIN_FORMAT.match(doc.gstin):
|
||||
frappe.throw(_("The input you've entered doesn't match the GSTIN format for UIN Holders or Non-Resident OIDAR Service Providers"),
|
||||
title=_("Invalid GSTIN"))
|
||||
else:
|
||||
if not GSTIN_FORMAT.match(doc.gstin):
|
||||
frappe.throw(_("The input you've entered doesn't match the format of GSTIN."), title=_("Invalid GSTIN"))
|
||||
|
||||
validate_gstin_check_digit(doc.gstin)
|
||||
set_gst_state_and_state_number(doc)
|
||||
|
||||
if not doc.gst_state:
|
||||
frappe.throw(_("Please enter GST state"), title=_("Invalid State"))
|
||||
|
||||
if doc.gst_state_number != doc.gstin[:2]:
|
||||
frappe.throw(_("First 2 digits of GSTIN should match with State number {0}.")
|
||||
.format(doc.gst_state_number), title=_("Invalid GSTIN"))
|
||||
|
||||
def validate_pan_for_india(doc, method):
|
||||
if doc.get('country') != 'India' or not doc.get('pan'):
|
||||
return
|
||||
|
||||
if not PAN_NUMBER_FORMAT.match(doc.pan):
|
||||
frappe.throw(_("Invalid PAN No. The input you've entered doesn't match the format of PAN."))
|
||||
|
||||
def validate_tax_category(doc, method):
|
||||
if doc.get('gst_state') and frappe.db.get_value('Tax Category', {'gst_state': doc.gst_state, 'is_inter_state': doc.is_inter_state,
|
||||
'is_reverse_charge': doc.is_reverse_charge}):
|
||||
if doc.is_inter_state:
|
||||
frappe.throw(_("Inter State tax category for GST State {0} already exists").format(doc.gst_state))
|
||||
else:
|
||||
frappe.throw(_("Intra State tax category for GST State {0} already exists").format(doc.gst_state))
|
||||
|
||||
def update_gst_category(doc, method):
|
||||
for link in doc.links:
|
||||
if link.link_doctype in ['Customer', 'Supplier']:
|
||||
meta = frappe.get_meta(link.link_doctype)
|
||||
if doc.get('gstin') and meta.has_field('gst_category'):
|
||||
frappe.db.set_value(link.link_doctype, {'name': link.link_name, 'gst_category': 'Unregistered'}, 'gst_category', 'Registered Regular')
|
||||
|
||||
def set_gst_state_and_state_number(doc):
|
||||
if not doc.gst_state:
|
||||
if not doc.state:
|
||||
return
|
||||
state = doc.state.lower()
|
||||
states_lowercase = {s.lower():s for s in states}
|
||||
if state in states_lowercase:
|
||||
doc.gst_state = states_lowercase[state]
|
||||
else:
|
||||
return
|
||||
|
||||
doc.gst_state_number = state_numbers[doc.gst_state]
|
||||
|
||||
def validate_gstin_check_digit(gstin, label='GSTIN'):
|
||||
''' Function to validate the check digit of the GSTIN.'''
|
||||
factor = 1
|
||||
total = 0
|
||||
code_point_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
mod = len(code_point_chars)
|
||||
input_chars = gstin[:-1]
|
||||
for char in input_chars:
|
||||
digit = factor * code_point_chars.find(char)
|
||||
digit = (digit // mod) + (digit % mod)
|
||||
total += digit
|
||||
factor = 2 if factor == 1 else 1
|
||||
if gstin[-1] != code_point_chars[((mod - (total % mod)) % mod)]:
|
||||
frappe.throw(_("""Invalid {0}! The check digit validation has failed. Please ensure you've typed the {0} correctly.""").format(label))
|
||||
|
||||
def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
|
||||
hsn_wise_in_gst_settings = frappe.db.get_single_value('GST Settings','hsn_wise_tax_breakup')
|
||||
if frappe.get_meta(item_doctype).has_field('gst_hsn_code') and hsn_wise_in_gst_settings:
|
||||
return [_("HSN/SAC"), _("Taxable Amount")] + tax_accounts
|
||||
else:
|
||||
return [_("Item"), _("Taxable Amount")] + tax_accounts
|
||||
|
||||
def get_itemised_tax_breakup_data(doc, account_wise=False, hsn_wise=False):
|
||||
itemised_tax = get_itemised_tax(doc.taxes, with_tax_account=account_wise)
|
||||
|
||||
itemised_taxable_amount = get_itemised_taxable_amount(doc.items)
|
||||
|
||||
if not frappe.get_meta(doc.doctype + " Item").has_field('gst_hsn_code'):
|
||||
return itemised_tax, itemised_taxable_amount
|
||||
|
||||
hsn_wise_in_gst_settings = frappe.db.get_single_value('GST Settings','hsn_wise_tax_breakup')
|
||||
|
||||
tax_breakup_hsn_wise = hsn_wise or hsn_wise_in_gst_settings
|
||||
if tax_breakup_hsn_wise:
|
||||
item_hsn_map = frappe._dict()
|
||||
for d in doc.items:
|
||||
item_hsn_map.setdefault(d.item_code or d.item_name, d.get("gst_hsn_code"))
|
||||
|
||||
hsn_tax = {}
|
||||
for item, taxes in itemised_tax.items():
|
||||
item_or_hsn = item if not tax_breakup_hsn_wise else item_hsn_map.get(item)
|
||||
hsn_tax.setdefault(item_or_hsn, frappe._dict())
|
||||
for tax_desc, tax_detail in taxes.items():
|
||||
key = tax_desc
|
||||
if account_wise:
|
||||
key = tax_detail.get('tax_account')
|
||||
hsn_tax[item_or_hsn].setdefault(key, {"tax_rate": 0, "tax_amount": 0})
|
||||
hsn_tax[item_or_hsn][key]["tax_rate"] = tax_detail.get("tax_rate")
|
||||
hsn_tax[item_or_hsn][key]["tax_amount"] += tax_detail.get("tax_amount")
|
||||
|
||||
# set taxable amount
|
||||
hsn_taxable_amount = frappe._dict()
|
||||
for item in itemised_taxable_amount:
|
||||
item_or_hsn = item if not tax_breakup_hsn_wise else item_hsn_map.get(item)
|
||||
hsn_taxable_amount.setdefault(item_or_hsn, 0)
|
||||
hsn_taxable_amount[item_or_hsn] += itemised_taxable_amount.get(item)
|
||||
|
||||
return hsn_tax, hsn_taxable_amount
|
||||
|
||||
def set_place_of_supply(doc, method=None):
|
||||
doc.place_of_supply = get_place_of_supply(doc, doc.doctype)
|
||||
|
||||
def validate_document_name(doc, method=None):
|
||||
"""Validate GST invoice number requirements."""
|
||||
|
||||
country = frappe.get_cached_value("Company", doc.company, "country")
|
||||
|
||||
# Date was chosen as start of next FY to avoid irritating current users.
|
||||
if country != "India" or getdate(doc.posting_date) < getdate("2021-04-01"):
|
||||
return
|
||||
|
||||
if len(doc.name) > 16:
|
||||
frappe.throw(_("Maximum length of document number should be 16 characters as per GST rules. Please change the naming series."))
|
||||
|
||||
if not GST_INVOICE_NUMBER_FORMAT.match(doc.name):
|
||||
frappe.throw(_("Document name should only contain alphanumeric values, dash(-) and slash(/) characters as per GST rules. Please change the naming series."))
|
||||
|
||||
# don't remove this function it is used in tests
|
||||
def test_method():
|
||||
'''test function'''
|
||||
return 'overridden'
|
||||
|
||||
def get_place_of_supply(party_details, doctype):
|
||||
if not frappe.get_meta('Address').has_field('gst_state'): return
|
||||
|
||||
if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
|
||||
address_name = party_details.customer_address or party_details.shipping_address_name
|
||||
elif doctype in ("Purchase Invoice", "Purchase Order", "Purchase Receipt"):
|
||||
address_name = party_details.shipping_address or party_details.supplier_address
|
||||
|
||||
if address_name:
|
||||
address = frappe.db.get_value("Address", address_name, ["gst_state", "gst_state_number", "gstin"], as_dict=1)
|
||||
if address and address.gst_state and address.gst_state_number:
|
||||
party_details.gstin = address.gstin
|
||||
return cstr(address.gst_state_number) + "-" + cstr(address.gst_state)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_regional_address_details(party_details, doctype, company):
|
||||
if isinstance(party_details, str):
|
||||
party_details = json.loads(party_details)
|
||||
party_details = frappe._dict(party_details)
|
||||
|
||||
update_party_details(party_details, doctype)
|
||||
|
||||
party_details.place_of_supply = get_place_of_supply(party_details, doctype)
|
||||
|
||||
if is_internal_transfer(party_details, doctype):
|
||||
party_details.taxes_and_charges = ''
|
||||
party_details.taxes = []
|
||||
return party_details
|
||||
|
||||
if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
|
||||
master_doctype = "Sales Taxes and Charges Template"
|
||||
tax_template_by_category = get_tax_template_based_on_category(master_doctype, company, party_details)
|
||||
|
||||
elif doctype in ("Purchase Invoice", "Purchase Order", "Purchase Receipt"):
|
||||
master_doctype = "Purchase Taxes and Charges Template"
|
||||
tax_template_by_category = get_tax_template_based_on_category(master_doctype, company, party_details)
|
||||
|
||||
if tax_template_by_category:
|
||||
party_details['taxes_and_charges'] = tax_template_by_category
|
||||
return party_details
|
||||
|
||||
if not party_details.place_of_supply: return party_details
|
||||
if not party_details.company_gstin: return party_details
|
||||
|
||||
if ((doctype in ("Sales Invoice", "Delivery Note", "Sales Order") and party_details.company_gstin
|
||||
and party_details.company_gstin[:2] != party_details.place_of_supply[:2]) or (doctype in ("Purchase Invoice",
|
||||
"Purchase Order", "Purchase Receipt") and party_details.supplier_gstin and party_details.supplier_gstin[:2] != party_details.place_of_supply[:2])):
|
||||
default_tax = get_tax_template(master_doctype, company, 1, party_details.company_gstin[:2])
|
||||
else:
|
||||
default_tax = get_tax_template(master_doctype, company, 0, party_details.company_gstin[:2])
|
||||
|
||||
if not default_tax:
|
||||
return party_details
|
||||
|
||||
party_details["taxes_and_charges"] = default_tax
|
||||
party_details.taxes = get_taxes_and_charges(master_doctype, default_tax)
|
||||
|
||||
return party_details
|
||||
|
||||
def update_party_details(party_details, doctype):
|
||||
for address_field in ['shipping_address', 'company_address', 'supplier_address', 'shipping_address_name', 'customer_address']:
|
||||
if party_details.get(address_field):
|
||||
party_details.update(get_fetch_values(doctype, address_field, party_details.get(address_field)))
|
||||
|
||||
def is_internal_transfer(party_details, doctype):
|
||||
if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
|
||||
destination_gstin = party_details.company_gstin
|
||||
elif doctype in ("Purchase Invoice", "Purchase Order", "Purchase Receipt"):
|
||||
destination_gstin = party_details.supplier_gstin
|
||||
|
||||
if not destination_gstin or party_details.gstin:
|
||||
return False
|
||||
|
||||
if party_details.gstin == destination_gstin:
|
||||
return True
|
||||
else:
|
||||
False
|
||||
|
||||
def get_tax_template_based_on_category(master_doctype, company, party_details):
|
||||
if not party_details.get('tax_category'):
|
||||
return
|
||||
|
||||
default_tax = frappe.db.get_value(master_doctype, {'company': company, 'tax_category': party_details.get('tax_category')},
|
||||
'name')
|
||||
|
||||
return default_tax
|
||||
|
||||
def get_tax_template(master_doctype, company, is_inter_state, state_code):
|
||||
tax_categories = frappe.get_all('Tax Category', fields = ['name', 'is_inter_state', 'gst_state'],
|
||||
filters = {'is_inter_state': is_inter_state, 'is_reverse_charge': 0})
|
||||
|
||||
default_tax = ''
|
||||
|
||||
for tax_category in tax_categories:
|
||||
if tax_category.gst_state == number_state_mapping[state_code] or \
|
||||
(not default_tax and not tax_category.gst_state):
|
||||
default_tax = frappe.db.get_value(master_doctype,
|
||||
{'company': company, 'disabled': 0, 'tax_category': tax_category.name}, 'name')
|
||||
return default_tax
|
||||
|
||||
def calculate_annual_eligible_hra_exemption(doc):
|
||||
basic_component, hra_component = frappe.db.get_value('Company', doc.company, ["basic_component", "hra_component"])
|
||||
if not (basic_component and hra_component):
|
||||
frappe.throw(_("Please mention Basic and HRA component in Company"))
|
||||
annual_exemption, monthly_exemption, hra_amount = 0, 0, 0
|
||||
if hra_component and basic_component:
|
||||
assignment = get_salary_assignment(doc.employee, nowdate())
|
||||
if assignment:
|
||||
hra_component_exists = frappe.db.exists("Salary Detail", {
|
||||
"parent": assignment.salary_structure,
|
||||
"salary_component": hra_component,
|
||||
"parentfield": "earnings",
|
||||
"parenttype": "Salary Structure"
|
||||
})
|
||||
|
||||
if hra_component_exists:
|
||||
basic_amount, hra_amount = get_component_amt_from_salary_slip(doc.employee,
|
||||
assignment.salary_structure, basic_component, hra_component)
|
||||
if hra_amount:
|
||||
if doc.monthly_house_rent:
|
||||
annual_exemption = calculate_hra_exemption(assignment.salary_structure,
|
||||
basic_amount, hra_amount, doc.monthly_house_rent, doc.rented_in_metro_city)
|
||||
if annual_exemption > 0:
|
||||
monthly_exemption = annual_exemption / 12
|
||||
else:
|
||||
annual_exemption = 0
|
||||
|
||||
elif doc.docstatus == 1:
|
||||
frappe.throw(_("Salary Structure must be submitted before submission of Tax Ememption Declaration"))
|
||||
|
||||
return frappe._dict({
|
||||
"hra_amount": hra_amount,
|
||||
"annual_exemption": annual_exemption,
|
||||
"monthly_exemption": monthly_exemption
|
||||
})
|
||||
|
||||
def get_component_amt_from_salary_slip(employee, salary_structure, basic_component, hra_component):
|
||||
salary_slip = make_salary_slip(salary_structure, employee=employee, for_preview=1, ignore_permissions=True)
|
||||
basic_amt, hra_amt = 0, 0
|
||||
for earning in salary_slip.earnings:
|
||||
if earning.salary_component == basic_component:
|
||||
basic_amt = earning.amount
|
||||
elif earning.salary_component == hra_component:
|
||||
hra_amt = earning.amount
|
||||
if basic_amt and hra_amt:
|
||||
return basic_amt, hra_amt
|
||||
return basic_amt, hra_amt
|
||||
|
||||
def calculate_hra_exemption(salary_structure, basic, monthly_hra, monthly_house_rent, rented_in_metro_city):
|
||||
# TODO make this configurable
|
||||
exemptions = []
|
||||
frequency = frappe.get_value("Salary Structure", salary_structure, "payroll_frequency")
|
||||
# case 1: The actual amount allotted by the employer as the HRA.
|
||||
exemptions.append(get_annual_component_pay(frequency, monthly_hra))
|
||||
|
||||
actual_annual_rent = monthly_house_rent * 12
|
||||
annual_basic = get_annual_component_pay(frequency, basic)
|
||||
|
||||
# case 2: Actual rent paid less 10% of the basic salary.
|
||||
exemptions.append(flt(actual_annual_rent) - flt(annual_basic * 0.1))
|
||||
# case 3: 50% of the basic salary, if the employee is staying in a metro city (40% for a non-metro city).
|
||||
exemptions.append(annual_basic * 0.5 if rented_in_metro_city else annual_basic * 0.4)
|
||||
# return minimum of 3 cases
|
||||
return min(exemptions)
|
||||
|
||||
def get_annual_component_pay(frequency, amount):
|
||||
if frequency == "Daily":
|
||||
return amount * 365
|
||||
elif frequency == "Weekly":
|
||||
return amount * 52
|
||||
elif frequency == "Fortnightly":
|
||||
return amount * 26
|
||||
elif frequency == "Monthly":
|
||||
return amount * 12
|
||||
elif frequency == "Bimonthly":
|
||||
return amount * 6
|
||||
|
||||
def validate_house_rent_dates(doc):
|
||||
if not doc.rented_to_date or not doc.rented_from_date:
|
||||
frappe.throw(_("House rented dates required for exemption calculation"))
|
||||
|
||||
if date_diff(doc.rented_to_date, doc.rented_from_date) < 14:
|
||||
frappe.throw(_("House rented dates should be atleast 15 days apart"))
|
||||
|
||||
proofs = frappe.db.sql("""
|
||||
select name
|
||||
from `tabEmployee Tax Exemption Proof Submission`
|
||||
where
|
||||
docstatus=1 and employee=%(employee)s and payroll_period=%(payroll_period)s
|
||||
and (rented_from_date between %(from_date)s and %(to_date)s or rented_to_date between %(from_date)s and %(to_date)s)
|
||||
""", {
|
||||
"employee": doc.employee,
|
||||
"payroll_period": doc.payroll_period,
|
||||
"from_date": doc.rented_from_date,
|
||||
"to_date": doc.rented_to_date
|
||||
})
|
||||
|
||||
if proofs:
|
||||
frappe.throw(_("House rent paid days overlapping with {0}").format(proofs[0][0]))
|
||||
|
||||
def calculate_hra_exemption_for_period(doc):
|
||||
monthly_rent, eligible_hra = 0, 0
|
||||
if doc.house_rent_payment_amount:
|
||||
validate_house_rent_dates(doc)
|
||||
# TODO receive rented months or validate dates are start and end of months?
|
||||
# Calc monthly rent, round to nearest .5
|
||||
factor = flt(date_diff(doc.rented_to_date, doc.rented_from_date) + 1)/30
|
||||
factor = round(factor * 2)/2
|
||||
monthly_rent = doc.house_rent_payment_amount / factor
|
||||
# update field used by calculate_annual_eligible_hra_exemption
|
||||
doc.monthly_house_rent = monthly_rent
|
||||
exemptions = calculate_annual_eligible_hra_exemption(doc)
|
||||
|
||||
if exemptions["monthly_exemption"]:
|
||||
# calc total exemption amount
|
||||
eligible_hra = exemptions["monthly_exemption"] * factor
|
||||
exemptions["monthly_house_rent"] = monthly_rent
|
||||
exemptions["total_eligible_hra_exemption"] = eligible_hra
|
||||
return exemptions
|
||||
|
||||
def get_ewb_data(dt, dn):
|
||||
|
||||
ewaybills = []
|
||||
for doc_name in dn:
|
||||
doc = frappe.get_doc(dt, doc_name)
|
||||
|
||||
validate_doc(doc)
|
||||
|
||||
data = frappe._dict({
|
||||
"transporterId": "",
|
||||
"TotNonAdvolVal": 0,
|
||||
})
|
||||
|
||||
data.userGstin = data.fromGstin = doc.company_gstin
|
||||
data.supplyType = 'O'
|
||||
|
||||
if dt == 'Delivery Note':
|
||||
data.subSupplyType = 1
|
||||
elif doc.gst_category in ['Registered Regular', 'SEZ']:
|
||||
data.subSupplyType = 1
|
||||
elif doc.gst_category in ['Overseas', 'Deemed Export']:
|
||||
data.subSupplyType = 3
|
||||
else:
|
||||
frappe.throw(_('Unsupported GST Category for E-Way Bill JSON generation'))
|
||||
|
||||
data.docType = 'INV'
|
||||
data.docDate = frappe.utils.formatdate(doc.posting_date, 'dd/mm/yyyy')
|
||||
|
||||
company_address = frappe.get_doc('Address', doc.company_address)
|
||||
billing_address = frappe.get_doc('Address', doc.customer_address)
|
||||
|
||||
#added dispatch address
|
||||
dispatch_address = frappe.get_doc('Address', doc.dispatch_address_name) if doc.dispatch_address_name else company_address
|
||||
shipping_address = frappe.get_doc('Address', doc.shipping_address_name)
|
||||
|
||||
data = get_address_details(data, doc, company_address, billing_address, dispatch_address)
|
||||
|
||||
data.itemList = []
|
||||
data.totalValue = doc.net_total
|
||||
|
||||
data = get_item_list(data, doc, hsn_wise=True)
|
||||
|
||||
disable_rounded = frappe.db.get_single_value('Global Defaults', 'disable_rounded_total')
|
||||
data.totInvValue = doc.grand_total if disable_rounded else doc.rounded_total
|
||||
|
||||
data = get_transport_details(data, doc)
|
||||
|
||||
fields = {
|
||||
"/. -": {
|
||||
'docNo': doc.name,
|
||||
'fromTrdName': doc.company,
|
||||
'toTrdName': doc.customer_name,
|
||||
'transDocNo': doc.lr_no,
|
||||
},
|
||||
"@#/,&. -": {
|
||||
'fromAddr1': company_address.address_line1,
|
||||
'fromAddr2': company_address.address_line2,
|
||||
'fromPlace': company_address.city,
|
||||
'toAddr1': shipping_address.address_line1,
|
||||
'toAddr2': shipping_address.address_line2,
|
||||
'toPlace': shipping_address.city,
|
||||
'transporterName': doc.transporter_name
|
||||
}
|
||||
}
|
||||
|
||||
for allowed_chars, field_map in fields.items():
|
||||
for key, value in field_map.items():
|
||||
if not value:
|
||||
data[key] = ''
|
||||
else:
|
||||
data[key] = re.sub(r'[^\w' + allowed_chars + ']', '', value)
|
||||
|
||||
ewaybills.append(data)
|
||||
|
||||
data = {
|
||||
'version': '1.0.0421',
|
||||
'billLists': ewaybills
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
@frappe.whitelist()
|
||||
def generate_ewb_json(dt, dn):
|
||||
dn = json.loads(dn)
|
||||
return get_ewb_data(dt, dn)
|
||||
|
||||
@frappe.whitelist()
|
||||
def download_ewb_json():
|
||||
data = json.loads(frappe.local.form_dict.data)
|
||||
frappe.local.response.filecontent = json.dumps(data, indent=4, sort_keys=True)
|
||||
frappe.local.response.type = 'download'
|
||||
|
||||
filename_prefix = 'Bulk'
|
||||
docname = frappe.local.form_dict.docname
|
||||
if docname:
|
||||
if docname.startswith('['):
|
||||
docname = json.loads(docname)
|
||||
if len(docname) == 1:
|
||||
docname = docname[0]
|
||||
|
||||
if not isinstance(docname, list):
|
||||
# removes characters not allowed in a filename (https://stackoverflow.com/a/38766141/4767738)
|
||||
filename_prefix = re.sub(r'[^\w_.)( -]', '', docname)
|
||||
|
||||
frappe.local.response.filename = '{0}_e-WayBill_Data_{1}.json'.format(filename_prefix, frappe.utils.random_string(5))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_gstins_for_company(company):
|
||||
company_gstins =[]
|
||||
if company:
|
||||
company_gstins = frappe.db.sql("""select
|
||||
distinct `tabAddress`.gstin
|
||||
from
|
||||
`tabAddress`, `tabDynamic Link`
|
||||
where
|
||||
`tabDynamic Link`.parent = `tabAddress`.name and
|
||||
`tabDynamic Link`.parenttype = 'Address' and
|
||||
`tabDynamic Link`.link_doctype = 'Company' and
|
||||
`tabDynamic Link`.link_name = %(company)s""", {"company": company})
|
||||
return company_gstins
|
||||
|
||||
def get_address_details(data, doc, company_address, billing_address, dispatch_address):
|
||||
data.fromPincode = validate_pincode(company_address.pincode, 'Company Address')
|
||||
data.fromStateCode = validate_state_code(company_address.gst_state_number, 'Company Address')
|
||||
data.actualFromStateCode = validate_state_code(dispatch_address.gst_state_number, 'Dispatch Address')
|
||||
|
||||
if not doc.billing_address_gstin or len(doc.billing_address_gstin) < 15:
|
||||
data.toGstin = 'URP'
|
||||
set_gst_state_and_state_number(billing_address)
|
||||
else:
|
||||
data.toGstin = doc.billing_address_gstin
|
||||
|
||||
data.toPincode = validate_pincode(billing_address.pincode, 'Customer Address')
|
||||
data.toStateCode = validate_state_code(billing_address.gst_state_number, 'Customer Address')
|
||||
|
||||
if doc.customer_address != doc.shipping_address_name:
|
||||
data.transType = 2
|
||||
shipping_address = frappe.get_doc('Address', doc.shipping_address_name)
|
||||
set_gst_state_and_state_number(shipping_address)
|
||||
data.toPincode = validate_pincode(shipping_address.pincode, 'Shipping Address')
|
||||
data.actualToStateCode = validate_state_code(shipping_address.gst_state_number, 'Shipping Address')
|
||||
else:
|
||||
data.transType = 1
|
||||
data.actualToStateCode = data.toStateCode
|
||||
shipping_address = billing_address
|
||||
|
||||
if doc.gst_category == 'SEZ':
|
||||
data.toStateCode = 99
|
||||
|
||||
return data
|
||||
|
||||
def get_item_list(data, doc, hsn_wise=False):
|
||||
for attr in ['cgstValue', 'sgstValue', 'igstValue', 'cessValue', 'OthValue']:
|
||||
data[attr] = 0
|
||||
|
||||
gst_accounts = get_gst_accounts(doc.company, account_wise=True)
|
||||
tax_map = {
|
||||
'sgst_account': ['sgstRate', 'sgstValue'],
|
||||
'cgst_account': ['cgstRate', 'cgstValue'],
|
||||
'igst_account': ['igstRate', 'igstValue'],
|
||||
'cess_account': ['cessRate', 'cessValue']
|
||||
}
|
||||
item_data_attrs = ['sgstRate', 'cgstRate', 'igstRate', 'cessRate', 'cessNonAdvol']
|
||||
hsn_wise_charges, hsn_taxable_amount = get_itemised_tax_breakup_data(doc, account_wise=True, hsn_wise=hsn_wise)
|
||||
for item_or_hsn, taxable_amount in hsn_taxable_amount.items():
|
||||
item_data = frappe._dict()
|
||||
if not item_or_hsn:
|
||||
frappe.throw(_('GST HSN Code does not exist for one or more items'))
|
||||
item_data.hsnCode = int(item_or_hsn) if hsn_wise else item_or_hsn
|
||||
item_data.taxableAmount = taxable_amount
|
||||
item_data.qtyUnit = ""
|
||||
for attr in item_data_attrs:
|
||||
item_data[attr] = 0
|
||||
|
||||
for account, tax_detail in hsn_wise_charges.get(item_or_hsn, {}).items():
|
||||
account_type = gst_accounts.get(account, '')
|
||||
for tax_acc, attrs in tax_map.items():
|
||||
if account_type == tax_acc:
|
||||
item_data[attrs[0]] = tax_detail.get('tax_rate')
|
||||
data[attrs[1]] += tax_detail.get('tax_amount')
|
||||
break
|
||||
else:
|
||||
data.OthValue += tax_detail.get('tax_amount')
|
||||
|
||||
data.itemList.append(item_data)
|
||||
|
||||
# Tax amounts rounded to 2 decimals to avoid exceeding max character limit
|
||||
for attr in ['sgstValue', 'cgstValue', 'igstValue', 'cessValue']:
|
||||
data[attr] = flt(data[attr], 2)
|
||||
|
||||
return data
|
||||
|
||||
def validate_doc(doc):
|
||||
if doc.docstatus != 1:
|
||||
frappe.throw(_('E-Way Bill JSON can only be generated from submitted document'))
|
||||
|
||||
if doc.is_return:
|
||||
frappe.throw(_('E-Way Bill JSON cannot be generated for Sales Return as of now'))
|
||||
|
||||
if doc.ewaybill:
|
||||
frappe.throw(_('e-Way Bill already exists for this document'))
|
||||
|
||||
reqd_fields = ['company_gstin', 'company_address', 'customer_address',
|
||||
'shipping_address_name', 'mode_of_transport', 'distance']
|
||||
|
||||
for fieldname in reqd_fields:
|
||||
if not doc.get(fieldname):
|
||||
frappe.throw(_('{} is required to generate E-Way Bill JSON').format(
|
||||
doc.meta.get_label(fieldname)
|
||||
))
|
||||
|
||||
if len(doc.company_gstin) < 15:
|
||||
frappe.throw(_('You must be a registered supplier to generate e-Way Bill'))
|
||||
|
||||
def get_transport_details(data, doc):
|
||||
if doc.distance > 4000:
|
||||
frappe.throw(_('Distance cannot be greater than 4000 kms'))
|
||||
|
||||
data.transDistance = int(round(doc.distance))
|
||||
|
||||
transport_modes = {
|
||||
'Road': 1,
|
||||
'Rail': 2,
|
||||
'Air': 3,
|
||||
'Ship': 4
|
||||
}
|
||||
|
||||
vehicle_types = {
|
||||
'Regular': 'R',
|
||||
'Over Dimensional Cargo (ODC)': 'O'
|
||||
}
|
||||
|
||||
data.transMode = transport_modes.get(doc.mode_of_transport)
|
||||
|
||||
if doc.mode_of_transport == 'Road':
|
||||
if not doc.gst_transporter_id and not doc.vehicle_no:
|
||||
frappe.throw(_('Either GST Transporter ID or Vehicle No is required if Mode of Transport is Road'))
|
||||
if doc.vehicle_no:
|
||||
data.vehicleNo = doc.vehicle_no.replace(' ', '')
|
||||
if not doc.gst_vehicle_type:
|
||||
frappe.throw(_('Vehicle Type is required if Mode of Transport is Road'))
|
||||
else:
|
||||
data.vehicleType = vehicle_types.get(doc.gst_vehicle_type)
|
||||
else:
|
||||
if not doc.lr_no or not doc.lr_date:
|
||||
frappe.throw(_('Transport Receipt No and Date are mandatory for your chosen Mode of Transport'))
|
||||
|
||||
if doc.lr_no:
|
||||
data.transDocNo = doc.lr_no
|
||||
|
||||
if doc.lr_date:
|
||||
data.transDocDate = frappe.utils.formatdate(doc.lr_date, 'dd/mm/yyyy')
|
||||
|
||||
if doc.gst_transporter_id:
|
||||
if doc.gst_transporter_id[0:2] != "88":
|
||||
validate_gstin_check_digit(doc.gst_transporter_id, label='GST Transporter ID')
|
||||
data.transporterId = doc.gst_transporter_id
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def validate_pincode(pincode, address):
|
||||
pin_not_found = "Pin Code doesn't exist for {}"
|
||||
incorrect_pin = "Pin Code for {} is incorrecty formatted. It must be 6 digits (without spaces)"
|
||||
|
||||
if not pincode:
|
||||
frappe.throw(_(pin_not_found.format(address)))
|
||||
|
||||
pincode = pincode.replace(' ', '')
|
||||
if not pincode.isdigit() or len(pincode) != 6:
|
||||
frappe.throw(_(incorrect_pin.format(address)))
|
||||
else:
|
||||
return int(pincode)
|
||||
|
||||
def validate_state_code(state_code, address):
|
||||
no_state_code = "GST State Code not found for {0}. Please set GST State in {0}"
|
||||
if not state_code:
|
||||
frappe.throw(_(no_state_code.format(address)))
|
||||
else:
|
||||
return int(state_code)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_gst_accounts(company=None, account_wise=False, only_reverse_charge=0, only_non_reverse_charge=0):
|
||||
filters={"parent": "GST Settings"}
|
||||
|
||||
if company:
|
||||
filters.update({'company': company})
|
||||
if only_reverse_charge:
|
||||
filters.update({'is_reverse_charge_account': 1})
|
||||
elif only_non_reverse_charge:
|
||||
filters.update({'is_reverse_charge_account': 0})
|
||||
|
||||
gst_accounts = frappe._dict()
|
||||
gst_settings_accounts = frappe.get_all("GST Account",
|
||||
filters=filters,
|
||||
fields=["cgst_account", "sgst_account", "igst_account", "cess_account"])
|
||||
|
||||
if not gst_settings_accounts and not frappe.flags.in_test and not frappe.flags.in_migrate:
|
||||
frappe.throw(_("Please set GST Accounts in GST Settings"))
|
||||
|
||||
for d in gst_settings_accounts:
|
||||
for acc, val in d.items():
|
||||
if not account_wise:
|
||||
gst_accounts.setdefault(acc, []).append(val)
|
||||
elif val:
|
||||
gst_accounts[val] = acc
|
||||
|
||||
return gst_accounts
|
||||
|
||||
def validate_reverse_charge_transaction(doc, method):
|
||||
country = frappe.get_cached_value('Company', doc.company, 'country')
|
||||
|
||||
if country != 'India':
|
||||
return
|
||||
|
||||
base_gst_tax = 0
|
||||
base_reverse_charge_booked = 0
|
||||
|
||||
if doc.reverse_charge == 'Y':
|
||||
gst_accounts = get_gst_accounts(doc.company, only_reverse_charge=1)
|
||||
reverse_charge_accounts = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
|
||||
+ gst_accounts.get('igst_account')
|
||||
|
||||
gst_accounts = get_gst_accounts(doc.company, only_non_reverse_charge=1)
|
||||
non_reverse_charge_accounts = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
|
||||
+ gst_accounts.get('igst_account')
|
||||
|
||||
for tax in doc.get('taxes'):
|
||||
if tax.account_head in non_reverse_charge_accounts:
|
||||
if tax.add_deduct_tax == 'Add':
|
||||
base_gst_tax += tax.base_tax_amount_after_discount_amount
|
||||
else:
|
||||
base_gst_tax += tax.base_tax_amount_after_discount_amount
|
||||
elif tax.account_head in reverse_charge_accounts:
|
||||
if tax.add_deduct_tax == 'Add':
|
||||
base_reverse_charge_booked += tax.base_tax_amount_after_discount_amount
|
||||
else:
|
||||
base_reverse_charge_booked += tax.base_tax_amount_after_discount_amount
|
||||
|
||||
if base_gst_tax != base_reverse_charge_booked:
|
||||
msg = _("Booked reverse charge is not equal to applied tax amount")
|
||||
msg += "<br>"
|
||||
msg += _("Please refer {gst_document_link} to learn more about how to setup and create reverse charge invoice").format(
|
||||
gst_document_link='<a href="https://docs.erpnext.com/docs/user/manual/en/regional/india/gst-setup">GST Documentation</a>')
|
||||
|
||||
frappe.throw(msg)
|
||||
|
||||
def update_itc_availed_fields(doc, method):
|
||||
country = frappe.get_cached_value('Company', doc.company, 'country')
|
||||
|
||||
if country != 'India':
|
||||
return
|
||||
|
||||
# Initialize values
|
||||
doc.itc_integrated_tax = doc.itc_state_tax = doc.itc_central_tax = doc.itc_cess_amount = 0
|
||||
gst_accounts = get_gst_accounts(doc.company, only_non_reverse_charge=1)
|
||||
|
||||
for tax in doc.get('taxes'):
|
||||
if tax.account_head in gst_accounts.get('igst_account', []):
|
||||
doc.itc_integrated_tax += flt(tax.base_tax_amount_after_discount_amount)
|
||||
if tax.account_head in gst_accounts.get('sgst_account', []):
|
||||
doc.itc_state_tax += flt(tax.base_tax_amount_after_discount_amount)
|
||||
if tax.account_head in gst_accounts.get('cgst_account', []):
|
||||
doc.itc_central_tax += flt(tax.base_tax_amount_after_discount_amount)
|
||||
if tax.account_head in gst_accounts.get('cess_account', []):
|
||||
doc.itc_cess_amount += flt(tax.base_tax_amount_after_discount_amount)
|
||||
|
||||
def update_place_of_supply(doc, method):
|
||||
country = frappe.get_cached_value('Company', doc.company, 'country')
|
||||
if country != 'India':
|
||||
return
|
||||
|
||||
address = frappe.db.get_value("Address", doc.get('customer_address'), ["gst_state", "gst_state_number"], as_dict=1)
|
||||
if address and address.gst_state and address.gst_state_number:
|
||||
doc.place_of_supply = cstr(address.gst_state_number) + "-" + cstr(address.gst_state)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_regional_round_off_accounts(company, account_list):
|
||||
country = frappe.get_cached_value('Company', company, 'country')
|
||||
|
||||
if country != 'India':
|
||||
return
|
||||
|
||||
if isinstance(account_list, str):
|
||||
account_list = json.loads(account_list)
|
||||
|
||||
if not frappe.db.get_single_value('GST Settings', 'round_off_gst_values'):
|
||||
return
|
||||
|
||||
gst_accounts = get_gst_accounts(company)
|
||||
|
||||
gst_account_list = []
|
||||
for account in ['cgst_account', 'sgst_account', 'igst_account']:
|
||||
if account in gst_accounts:
|
||||
gst_account_list += gst_accounts.get(account)
|
||||
|
||||
account_list.extend(gst_account_list)
|
||||
|
||||
return account_list
|
||||
|
||||
def update_taxable_values(doc, method):
|
||||
country = frappe.get_cached_value('Company', doc.company, 'country')
|
||||
|
||||
if country != 'India':
|
||||
return
|
||||
|
||||
gst_accounts = get_gst_accounts(doc.company)
|
||||
|
||||
# Only considering sgst account to avoid inflating taxable value
|
||||
gst_account_list = gst_accounts.get('sgst_account', []) + gst_accounts.get('sgst_account', []) \
|
||||
+ gst_accounts.get('igst_account', [])
|
||||
|
||||
additional_taxes = 0
|
||||
total_charges = 0
|
||||
item_count = 0
|
||||
considered_rows = []
|
||||
|
||||
for tax in doc.get('taxes'):
|
||||
prev_row_id = cint(tax.row_id) - 1
|
||||
if tax.account_head in gst_account_list and prev_row_id not in considered_rows:
|
||||
if tax.charge_type == 'On Previous Row Amount':
|
||||
additional_taxes += doc.get('taxes')[prev_row_id].tax_amount_after_discount_amount
|
||||
considered_rows.append(prev_row_id)
|
||||
if tax.charge_type == 'On Previous Row Total':
|
||||
additional_taxes += doc.get('taxes')[prev_row_id].base_total - doc.base_net_total
|
||||
considered_rows.append(prev_row_id)
|
||||
|
||||
for item in doc.get('items'):
|
||||
proportionate_value = item.base_net_amount if doc.base_net_total else item.qty
|
||||
total_value = doc.base_net_total if doc.base_net_total else doc.total_qty
|
||||
|
||||
applicable_charges = flt(flt(proportionate_value * (flt(additional_taxes) / flt(total_value)),
|
||||
item.precision('taxable_value')))
|
||||
item.taxable_value = applicable_charges + proportionate_value
|
||||
total_charges += applicable_charges
|
||||
item_count += 1
|
||||
|
||||
if total_charges != additional_taxes:
|
||||
diff = additional_taxes - total_charges
|
||||
doc.get('items')[item_count - 1].taxable_value += diff
|
||||
|
||||
def get_depreciation_amount(asset, depreciable_value, row):
|
||||
if row.depreciation_method in ("Straight Line", "Manual"):
|
||||
# if the Depreciation Schedule is being prepared for the first time
|
||||
if not asset.flags.increase_in_asset_life:
|
||||
depreciation_amount = (flt(asset.gross_purchase_amount) -
|
||||
flt(row.expected_value_after_useful_life)) / flt(row.total_number_of_depreciations)
|
||||
|
||||
# if the Depreciation Schedule is being modified after Asset Repair
|
||||
else:
|
||||
depreciation_amount = (flt(row.value_after_depreciation) -
|
||||
flt(row.expected_value_after_useful_life)) / (date_diff(asset.to_date, asset.available_for_use_date) / 365)
|
||||
|
||||
else:
|
||||
rate_of_depreciation = row.rate_of_depreciation
|
||||
# if its the first depreciation
|
||||
if depreciable_value == asset.gross_purchase_amount:
|
||||
if row.finance_book and frappe.db.get_value('Finance Book', row.finance_book, 'for_income_tax'):
|
||||
# as per IT act, if the asset is purchased in the 2nd half of fiscal year, then rate is divided by 2
|
||||
diff = date_diff(row.depreciation_start_date, asset.available_for_use_date)
|
||||
if diff <= 180:
|
||||
rate_of_depreciation = rate_of_depreciation / 2
|
||||
frappe.msgprint(
|
||||
_('As per IT Act, the rate of depreciation for the first depreciation entry is reduced by 50%.'))
|
||||
|
||||
depreciation_amount = flt(depreciable_value * (flt(rate_of_depreciation) / 100))
|
||||
|
||||
return depreciation_amount
|
||||
|
||||
def set_item_tax_from_hsn_code(item):
|
||||
if not item.taxes and item.gst_hsn_code:
|
||||
hsn_doc = frappe.get_doc("GST HSN Code", item.gst_hsn_code)
|
||||
|
||||
for tax in hsn_doc.taxes:
|
||||
item.append('taxes', {
|
||||
'item_tax_template': tax.item_tax_template,
|
||||
'tax_category': tax.tax_category,
|
||||
'valid_from': tax.valid_from
|
||||
})
|
||||
|
||||
def delete_gst_settings_for_company(doc, method):
|
||||
if doc.country != 'India':
|
||||
return
|
||||
|
||||
gst_settings = frappe.get_doc("GST Settings")
|
||||
records_to_delete = []
|
||||
|
||||
for d in reversed(gst_settings.get('gst_accounts')):
|
||||
if d.company == doc.name:
|
||||
records_to_delete.append(d)
|
||||
|
||||
for d in records_to_delete:
|
||||
gst_settings.remove(d)
|
||||
|
||||
gst_settings.save()
|
@ -1,22 +0,0 @@
|
||||
{
|
||||
"align_labels_right": 0,
|
||||
"creation": "2017-07-04 16:26:21.120187",
|
||||
"custom_format": 0,
|
||||
"disabled": 1,
|
||||
"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\\\">\\n\\t<h2>\\n\\t\\tTAX INVOICE<br>\\n\\t\\t<small>{{ doc.name }}</small>\\n\\t</h2>\\n</div>\\n<h2 class=\\\"text-center\\\">\\n\\t{% if doc.invoice_copy -%}\\n\\t\\t<small>{{ doc.invoice_copy }}</small>\\n\\t{% endif -%}\\n</h2>\"}, {\"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\"}, {\"print_hide\": 0, \"fieldname\": \"reverse_charge\", \"label\": \"Reverse Charge\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldname\": \"_custom_html\", \"options\": \"<hr>\", \"fieldtype\": \"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\": \"serial_no\", \"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\": \"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-12-15 11:57:25.477278",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "GST Tax Invoice",
|
||||
"owner": "Administrator",
|
||||
"print_format_builder": 1,
|
||||
"print_format_type": "Jinja",
|
||||
"show_section_headings": 0,
|
||||
"standard": "Yes"
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
/* eslint-disable */
|
||||
|
||||
frappe.query_reports["E-Invoice Summary"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"reqd": 1,
|
||||
"fieldname": "company",
|
||||
"label": __("Company"),
|
||||
"default": frappe.defaults.get_user_default("Company"),
|
||||
},
|
||||
{
|
||||
"fieldtype": "Link",
|
||||
"options": "Customer",
|
||||
"fieldname": "customer",
|
||||
"label": __("Customer")
|
||||
},
|
||||
{
|
||||
"fieldtype": "Date",
|
||||
"reqd": 1,
|
||||
"fieldname": "from_date",
|
||||
"label": __("From Date"),
|
||||
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
|
||||
},
|
||||
{
|
||||
"fieldtype": "Date",
|
||||
"reqd": 1,
|
||||
"fieldname": "to_date",
|
||||
"label": __("To Date"),
|
||||
"default": frappe.datetime.get_today(),
|
||||
},
|
||||
{
|
||||
"fieldtype": "Select",
|
||||
"fieldname": "status",
|
||||
"label": __("Status"),
|
||||
"options": "\nPending\nGenerated\nCancelled\nFailed"
|
||||
}
|
||||
],
|
||||
|
||||
"formatter": function (value, row, column, data, default_formatter) {
|
||||
value = default_formatter(value, row, column, data);
|
||||
|
||||
if (column.fieldname == "einvoice_status" && value) {
|
||||
if (value == 'Pending') value = `<span class="bold" style="color: var(--text-on-orange)">${value}</span>`;
|
||||
else if (value == 'Generated') value = `<span class="bold" style="color: var(--text-on-green)">${value}</span>`;
|
||||
else if (value == 'Cancelled') value = `<span class="bold" style="color: var(--text-on-red)">${value}</span>`;
|
||||
else if (value == 'Failed') value = `<span class="bold" style="color: var(--text-on-red)">${value}</span>`;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
};
|
@ -1,28 +0,0 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"columns": [],
|
||||
"creation": "2021-03-12 11:23:37.312294",
|
||||
"disable_prepared_report": 0,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"filters": [],
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"json": "{}",
|
||||
"letter_head": "Logo",
|
||||
"modified": "2021-03-13 12:36:48.689413",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Regional",
|
||||
"name": "E-Invoice Summary",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Sales Invoice",
|
||||
"report_name": "E-Invoice Summary",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Administrator"
|
||||
}
|
||||
]
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user