2017-06-21 11:52:38 +00:00
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe , os , json
2017-09-13 07:22:30 +00:00
from frappe . custom . doctype . custom_field . custom_field import create_custom_fields
2017-06-21 11:52:38 +00:00
from frappe . permissions import add_permission
from erpnext . regional . india import states
2017-06-27 12:35:17 +00:00
def setup ( company = None , patch = True ) :
2017-06-21 11:52:38 +00:00
make_custom_fields ( )
add_permissions ( )
2017-06-22 11:07:04 +00:00
add_custom_roles_for_reports ( )
2017-09-28 13:25:40 +00:00
frappe . enqueue ( ' erpnext.regional.india.setup.add_hsn_sac_codes ' , now = frappe . flags . in_test )
2017-07-05 07:28:19 +00:00
add_print_formats ( )
2017-06-27 12:35:17 +00:00
if not patch :
2017-07-13 06:46:04 +00:00
update_address_template ( )
2018-05-11 07:46:16 +00:00
make_fixtures ( company )
2017-06-22 11:07:04 +00:00
def update_address_template ( ) :
with open ( os . path . join ( os . path . dirname ( __file__ ) , ' address_template.html ' ) , ' r ' ) as f :
html = f . read ( )
address_template = frappe . db . get_value ( ' Address Template ' , ' India ' )
if address_template :
frappe . db . set_value ( ' Address Template ' , ' India ' , ' template ' , html )
else :
# make new html template for India
2017-06-27 06:47:39 +00:00
frappe . get_doc ( dict (
2017-06-22 11:07:04 +00:00
doctype = ' Address Template ' ,
country = ' India ' ,
template = html
2017-06-27 06:47:39 +00:00
) ) . insert ( )
2017-06-21 11:52:38 +00:00
2017-07-13 06:46:04 +00:00
def add_hsn_sac_codes ( ) :
# HSN codes
2017-06-21 11:52:38 +00:00
with open ( os . path . join ( os . path . dirname ( __file__ ) , ' hsn_code_data.json ' ) , ' r ' ) as f :
hsn_codes = json . loads ( f . read ( ) )
2017-07-13 06:46:04 +00:00
create_hsn_codes ( hsn_codes , code_field = " hsn_code " )
2017-09-04 05:44:04 +00:00
2017-07-13 06:46:04 +00:00
# SAC Codes
with open ( os . path . join ( os . path . dirname ( __file__ ) , ' sac_code_data.json ' ) , ' r ' ) as f :
sac_codes = json . loads ( f . read ( ) )
create_hsn_codes ( sac_codes , code_field = " sac_code " )
2017-09-04 05:44:04 +00:00
2017-07-13 06:46:04 +00:00
def create_hsn_codes ( data , code_field ) :
for d in data :
2017-09-27 10:01:30 +00:00
hsn_code = frappe . new_doc ( ' GST HSN Code ' )
hsn_code . description = d [ " description " ]
hsn_code . hsn_code = d [ code_field ]
hsn_code . name = d [ code_field ]
try :
2017-07-13 06:46:04 +00:00
hsn_code . db_insert ( )
2017-09-27 10:01:30 +00:00
except frappe . DuplicateEntryError :
pass
2017-06-21 11:52:38 +00:00
2017-06-22 11:07:04 +00:00
def add_custom_roles_for_reports ( ) :
for report_name in ( ' GST Sales Register ' , ' GST Purchase Register ' ,
' GST Itemised Sales Register ' , ' GST Itemised Purchase Register ' ) :
if not frappe . db . get_value ( ' Custom Role ' , dict ( report = report_name ) ) :
frappe . get_doc ( dict (
doctype = ' Custom Role ' ,
report = report_name ,
roles = [
dict ( role = ' Accounts User ' ) ,
dict ( role = ' Accounts Manager ' )
]
) ) . insert ( )
2017-06-21 11:52:38 +00:00
def add_permissions ( ) :
2017-06-27 12:01:41 +00:00
for doctype in ( ' GST HSN Code ' , ' GST Settings ' ) :
2017-06-21 11:52:38 +00:00
add_permission ( doctype , ' All ' , 0 )
2017-07-05 07:28:19 +00:00
def add_print_formats ( ) :
frappe . reload_doc ( " regional " , " print_format " , " gst_tax_invoice " )
2017-12-16 05:23:53 +00:00
frappe . reload_doc ( " accounts " , " print_format " , " gst_pos_invoice " )
frappe . db . sql ( """ update `tabPrint Format` set disabled = 0 where
name in ( ' GST POS Invoice ' , ' GST Tax Invoice ' ) """ )
2017-07-05 07:28:19 +00:00
2018-07-17 12:52:51 +00:00
def make_custom_fields ( update = True ) :
2017-07-06 09:19:34 +00:00
hsn_sac_field = dict ( fieldname = ' gst_hsn_code ' , label = ' HSN/SAC ' ,
2017-09-11 13:51:37 +00:00
fieldtype = ' Data ' , options = ' item_code.gst_hsn_code ' , insert_after = ' description ' ,
allow_on_submit = 1 , print_hide = 1 )
2017-08-21 02:58:55 +00:00
invoice_gst_fields = [
dict ( fieldname = ' gst_section ' , label = ' GST Details ' , fieldtype = ' Section Break ' ,
2018-01-30 06:41:13 +00:00
insert_after = ' language ' , print_hide = 1 , collapsible = 1 ) ,
2017-08-21 02:58:55 +00:00
dict ( fieldname = ' invoice_copy ' , label = ' Invoice Copy ' ,
fieldtype = ' Select ' , insert_after = ' gst_section ' , print_hide = 1 , allow_on_submit = 1 ,
options = ' Original for Recipient \n Duplicate for Transporter \n Duplicate for Supplier \n Triplicate for Supplier ' ) ,
dict ( fieldname = ' reverse_charge ' , label = ' Reverse Charge ' ,
fieldtype = ' Select ' , insert_after = ' invoice_copy ' , print_hide = 1 ,
options = ' Y \n N ' , default = ' N ' ) ,
dict ( fieldname = ' invoice_type ' , label = ' Invoice Type ' ,
2018-02-14 12:14:06 +00:00
fieldtype = ' Select ' , insert_after = ' invoice_copy ' , print_hide = 1 ,
2017-08-21 02:58:55 +00:00
options = ' Regular \n SEZ \n Export \n Deemed Export ' , default = ' Regular ' ) ,
dict ( fieldname = ' export_type ' , label = ' Export Type ' ,
fieldtype = ' Select ' , insert_after = ' invoice_type ' , print_hide = 1 ,
depends_on = ' eval:in_list([ " SEZ " , " Export " , " Deemed Export " ], doc.invoice_type) ' ,
options = ' \n With Payment of Tax \n Without Payment of Tax ' ) ,
dict ( fieldname = ' ecommerce_gstin ' , label = ' E-commerce GSTIN ' ,
2018-01-26 05:57:22 +00:00
fieldtype = ' Data ' , insert_after = ' export_type ' , print_hide = 1 ) ,
2018-02-14 12:14:06 +00:00
dict ( fieldname = ' gst_col_break ' , fieldtype = ' Column Break ' , insert_after = ' ecommerce_gstin ' ) ,
2018-01-26 05:57:22 +00:00
dict ( fieldname = ' reason_for_issuing_document ' , label = ' Reason For Issuing document ' ,
2018-02-05 10:39:51 +00:00
fieldtype = ' Select ' , insert_after = ' gst_col_break ' , print_hide = 1 ,
2018-02-14 12:14:06 +00:00
depends_on = ' eval:doc.is_return==1 ' ,
2018-02-12 11:24:13 +00:00
options = ' \n 01-Sales Return \n 02-Post Sale Discount \n 03-Deficiency in services \n 04-Correction in Invoice \n 05-Change in POS \n 06-Finalization of Provisional assessment \n 07-Others ' )
2017-08-21 02:58:55 +00:00
]
2017-09-04 05:44:04 +00:00
2017-08-21 02:58:55 +00:00
purchase_invoice_gst_fields = [
2017-06-21 11:52:38 +00:00
dict ( fieldname = ' supplier_gstin ' , label = ' Supplier GSTIN ' ,
2017-06-22 11:07:04 +00:00
fieldtype = ' Data ' , insert_after = ' supplier_address ' ,
2018-06-05 05:57:53 +00:00
fetch_from = ' supplier_address.gstin ' , print_hide = 1 ) ,
2017-06-21 11:52:38 +00:00
dict ( fieldname = ' company_gstin ' , label = ' Company GSTIN ' ,
2018-06-05 05:57:53 +00:00
fieldtype = ' Data ' , insert_after = ' shipping_address_display ' ,
fetch_from = ' shipping_address.gstin ' , print_hide = 1 ) ,
2018-02-05 10:39:51 +00:00
dict ( fieldname = ' place_of_supply ' , label = ' Place of Supply ' ,
fieldtype = ' Data ' , insert_after = ' shipping_address ' ,
print_hide = 1 , read_only = 0 ) ,
2018-01-29 08:27:34 +00:00
dict ( fieldname = ' eligibility_for_itc ' , label = ' Eligibility For ITC ' ,
fieldtype = ' Select ' , insert_after = ' reason_for_issuing_document ' , print_hide = 1 ,
options = ' input \n input service \n capital goods \n ineligible ' , default = " ineligible " ) ,
dict ( fieldname = ' itc_integrated_tax ' , label = ' Availed ITC Integrated Tax ' ,
fieldtype = ' Data ' , insert_after = ' eligibility_for_itc ' , print_hide = 1 ) ,
dict ( fieldname = ' itc_central_tax ' , label = ' Availed ITC Central Tax ' ,
fieldtype = ' Data ' , insert_after = ' itc_integrated_tax ' , print_hide = 1 ) ,
dict ( fieldname = ' itc_state_tax ' , label = ' Availed ITC State/UT Tax ' ,
fieldtype = ' Data ' , insert_after = ' itc_central_tax ' , print_hide = 1 ) ,
dict ( fieldname = ' itc_cess_amount ' , label = ' Availed ITC Cess ' ,
fieldtype = ' Data ' , insert_after = ' itc_state_tax ' , print_hide = 1 ) ,
2017-08-21 02:58:55 +00:00
]
2017-09-04 05:44:04 +00:00
2017-08-21 02:58:55 +00:00
sales_invoice_gst_fields = [
2017-09-28 05:35:03 +00:00
dict ( fieldname = ' billing_address_gstin ' , label = ' Billing Address GSTIN ' ,
fieldtype = ' Data ' , insert_after = ' customer_address ' ,
2018-06-05 05:57:53 +00:00
fetch_from = ' customer_address.gstin ' , print_hide = 1 ) ,
2017-06-21 11:52:38 +00:00
dict ( fieldname = ' customer_gstin ' , label = ' Customer GSTIN ' ,
2018-06-05 05:57:53 +00:00
fieldtype = ' Data ' , insert_after = ' shipping_address_name ' ,
fetch_from = ' shipping_address_name.gstin ' , print_hide = 1 ) ,
2017-08-21 02:58:55 +00:00
dict ( fieldname = ' place_of_supply ' , label = ' Place of Supply ' ,
2018-01-10 12:18:03 +00:00
fieldtype = ' Data ' , insert_after = ' customer_gstin ' ,
print_hide = 1 , read_only = 0 ) ,
2017-06-21 11:52:38 +00:00
dict ( fieldname = ' company_gstin ' , label = ' Company GSTIN ' ,
2017-06-22 11:07:04 +00:00
fieldtype = ' Data ' , insert_after = ' company_address ' ,
2018-06-05 05:57:53 +00:00
fetch_from = ' company_address.gstin ' , print_hide = 1 ) ,
2018-01-29 08:27:34 +00:00
dict ( fieldname = ' port_code ' , label = ' Port Code ' ,
fieldtype = ' Data ' , insert_after = ' reason_for_issuing_document ' , print_hide = 1 ,
depends_on = " eval:doc.invoice_type== ' Export ' " ) ,
dict ( fieldname = ' shipping_bill_number ' , label = ' Shipping Bill Number ' ,
fieldtype = ' Data ' , insert_after = ' port_code ' , print_hide = 1 ,
depends_on = " eval:doc.invoice_type== ' Export ' " ) ,
dict ( fieldname = ' shipping_bill_date ' , label = ' Shipping Bill Date ' ,
fieldtype = ' Date ' , insert_after = ' shipping_bill_number ' , print_hide = 1 ,
depends_on = " eval:doc.invoice_type== ' Export ' " )
2017-08-21 02:58:55 +00:00
]
2017-09-04 05:44:04 +00:00
2018-06-05 05:57:53 +00:00
inter_state_gst_field = [
dict ( fieldname = ' is_inter_state ' , label = ' Is Inter State ' ,
fieldtype = ' Check ' , insert_after = ' disabled ' , print_hide = 1 )
]
2017-08-21 02:58:55 +00:00
custom_fields = {
' Address ' : [
dict ( fieldname = ' gstin ' , label = ' Party GSTIN ' , fieldtype = ' Data ' ,
insert_after = ' fax ' ) ,
dict ( fieldname = ' gst_state ' , label = ' GST State ' , fieldtype = ' Select ' ,
options = ' \n ' . join ( states ) , insert_after = ' gstin ' ) ,
dict ( fieldname = ' gst_state_number ' , label = ' GST State Number ' ,
fieldtype = ' Int ' , insert_after = ' gst_state ' , read_only = 1 ) ,
2017-06-21 11:52:38 +00:00
] ,
2018-02-05 10:39:51 +00:00
' Purchase Invoice ' : invoice_gst_fields + purchase_invoice_gst_fields ,
' Sales Invoice ' : invoice_gst_fields + sales_invoice_gst_fields ,
2018-06-05 05:57:53 +00:00
' Delivery Note ' : sales_invoice_gst_fields ,
' Sales Taxes and Charges Template ' : inter_state_gst_field ,
' Purchase Taxes and Charges Template ' : inter_state_gst_field ,
2017-06-21 11:52:38 +00:00
' Item ' : [
2017-07-06 09:19:34 +00:00
dict ( fieldname = ' gst_hsn_code ' , label = ' HSN/SAC ' ,
2017-06-21 11:52:38 +00:00
fieldtype = ' Link ' , options = ' GST HSN Code ' , insert_after = ' item_group ' ) ,
] ,
2017-07-20 08:02:01 +00:00
' Quotation Item ' : [ hsn_sac_field ] ,
' Supplier Quotation Item ' : [ hsn_sac_field ] ,
2017-07-06 09:19:34 +00:00
' Sales Order Item ' : [ hsn_sac_field ] ,
' Delivery Note Item ' : [ hsn_sac_field ] ,
' Sales Invoice Item ' : [ hsn_sac_field ] ,
' Purchase Order Item ' : [ hsn_sac_field ] ,
' Purchase Receipt Item ' : [ hsn_sac_field ] ,
2018-04-05 09:24:51 +00:00
' Purchase Invoice Item ' : [ hsn_sac_field ] ,
' Employee ' : [
dict ( fieldname = ' ifsc_code ' , label = ' IFSC Code ' ,
2018-04-26 04:40:03 +00:00
fieldtype = ' Data ' , insert_after = ' bank_ac_no ' , print_hide = 1 ,
2018-06-14 12:26:16 +00:00
depends_on = ' eval:doc.salary_mode == " Bank " ' )
] ,
' Company ' : [
dict ( fieldname = ' hra_section ' , label = ' HRA Settings ' ,
fieldtype = ' Section Break ' , insert_after = ' asset_received_but_not_billed ' ) ,
2018-07-01 11:12:38 +00:00
dict ( fieldname = ' basic_component ' , label = ' Basic Component ' ,
2018-06-14 12:26:16 +00:00
fieldtype = ' Link ' , options = ' Salary Component ' , insert_after = ' hra_section ' ) ,
2018-07-01 11:12:38 +00:00
dict ( fieldname = ' hra_component ' , label = ' HRA Component ' ,
fieldtype = ' Link ' , options = ' Salary Component ' , insert_after = ' basic_component ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' arrear_component ' , label = ' Arrear Component ' ,
fieldtype = ' Link ' , options = ' Salary Component ' , insert_after = ' hra_component ' )
] ,
' Employee Tax Exemption Declaration ' : [
dict ( fieldname = ' hra_section ' , label = ' HRA Exemption ' ,
fieldtype = ' Section Break ' , insert_after = ' declarations ' ) ,
dict ( fieldname = ' salary_structure_hra ' , label = ' HRA as per Salary Structure ' ,
fieldtype = ' Currency ' , insert_after = ' hra_section ' , read_only = 1 ) ,
dict ( fieldname = ' monthly_house_rent ' , label = ' Monthly House Rent ' ,
fieldtype = ' Currency ' , insert_after = ' salary_structure_hra ' ) ,
dict ( fieldname = ' rented_in_metro_city ' , label = ' Rented in Metro City ' ,
fieldtype = ' Check ' , insert_after = ' monthly_house_rent ' ) ,
dict ( fieldname = ' hra_column_break ' , fieldtype = ' Column Break ' ,
insert_after = ' rented_in_metro_city ' ) ,
dict ( fieldname = ' annual_hra_exemption ' , label = ' Annual HRA Exemption ' ,
fieldtype = ' Currency ' , insert_after = ' hra_column_break ' , read_only = 1 ) ,
dict ( fieldname = ' monthly_hra_exemption ' , label = ' Monthly HRA Exemption ' ,
fieldtype = ' Currency ' , insert_after = ' annual_hra_exemption ' , read_only = 1 )
] ,
' Employee Tax Exemption Proof Submission ' : [
dict ( fieldname = ' hra_section ' , label = ' HRA Exemption ' ,
fieldtype = ' Section Break ' , insert_after = ' tax_exemption_proofs ' ) ,
dict ( fieldname = ' house_rent_payment_amount ' , label = ' House Rent Payment Amount ' ,
fieldtype = ' Currency ' , insert_after = ' hra_section ' ) ,
dict ( fieldname = ' rented_in_metro_city ' , label = ' Rented in Metro City ' ,
fieldtype = ' Check ' , insert_after = ' house_rent_payment_amount ' ) ,
dict ( fieldname = ' rented_from_date ' , label = ' Rented From Date ' ,
fieldtype = ' Date ' , insert_after = ' rented_in_metro_city ' ) ,
dict ( fieldname = ' rented_to_date ' , label = ' Rented To Date ' ,
fieldtype = ' Date ' , insert_after = ' rented_from_date ' ) ,
dict ( fieldname = ' hra_column_break ' , fieldtype = ' Column Break ' ,
insert_after = ' rented_to_date ' ) ,
dict ( fieldname = ' monthly_house_rent ' , label = ' Monthly House Rent ' ,
fieldtype = ' Currency ' , insert_after = ' hra_column_break ' , read_only = 1 ) ,
dict ( fieldname = ' monthly_hra_exemption ' , label = ' Monthly Eligible Amount ' ,
fieldtype = ' Currency ' , insert_after = ' monthly_house_rent ' , read_only = 1 ) ,
dict ( fieldname = ' total_eligible_hra_exemption ' , label = ' Total Eligible HRA Exemption ' ,
fieldtype = ' Currency ' , insert_after = ' monthly_hra_exemption ' , read_only = 1 )
]
2017-06-21 11:52:38 +00:00
}
2018-07-17 12:52:51 +00:00
create_custom_fields ( custom_fields , ignore_validate = frappe . flags . in_patch , update = update )
2017-07-20 08:02:01 +00:00
2018-05-11 07:46:16 +00:00
def make_fixtures ( company = None ) :
docs = [ ]
company = company . name if company else frappe . db . get_value ( " Global Defaults " , None , " default_company " )
set_salary_components ( docs )
set_tds_account ( docs , company )
set_tax_withholding_category ( docs , company )
2017-06-21 11:52:38 +00:00
for d in docs :
try :
doc = frappe . get_doc ( d )
doc . flags . ignore_permissions = True
doc . insert ( )
except frappe . NameError :
pass
2018-05-11 07:46:16 +00:00
def set_salary_components ( docs ) :
docs . extend ( [
{ ' doctype ' : ' Salary Component ' , ' salary_component ' : ' Professional Tax ' , ' description ' : ' Professional Tax ' , ' type ' : ' Deduction ' } ,
{ ' doctype ' : ' Salary Component ' , ' salary_component ' : ' Provident Fund ' , ' description ' : ' Provident fund ' , ' type ' : ' Deduction ' } ,
{ ' doctype ' : ' Salary Component ' , ' salary_component ' : ' House Rent Allowance ' , ' description ' : ' House Rent Allowance ' , ' type ' : ' Earning ' } ,
{ ' doctype ' : ' Salary Component ' , ' salary_component ' : ' Basic ' , ' description ' : ' Basic ' , ' type ' : ' Earning ' } ,
{ ' doctype ' : ' Salary Component ' , ' salary_component ' : ' Arrear ' , ' description ' : ' Arrear ' , ' type ' : ' Earning ' } ,
{ ' doctype ' : ' Salary Component ' , ' salary_component ' : ' Leave Encashment ' , ' description ' : ' Leave Encashment ' , ' type ' : ' Earning ' }
] )
def set_tax_withholding_category ( docs , company ) :
accounts = [ ]
tds_account = frappe . db . get_value ( " Account " , filter = { " account_type " : " Payable " ,
" account_name " : " TDS " , " company " : company } )
if company and tds_account :
accounts = [
{
' company ' : company ,
' account ' : tds_account
}
]
docs . extend ( [
{
' doctype ' : ' Tax Withholding Category ' , ' __newname ' : ' TDS ' ,
' percent_of_tax_withheld ' : 10 , ' threshold ' : 150000 , ' book_on_invoice ' : 1 ,
2018-06-19 05:16:41 +00:00
' withhold_cumulative_tax_amount ' : 0 , ' accounts ' : accounts
2018-05-11 07:46:16 +00:00
}
] )
def set_tds_account ( docs , company ) :
docs . extend ( [
{
2018-05-12 12:12:20 +00:00
' doctype ' : ' Account ' , ' account_name ' : ' TDS ' , ' account_type ' : ' Tax ' ,
' parent_account ' : ' Duties and Taxes ' , ' company ' : company
2018-05-11 07:46:16 +00:00
}
2018-06-14 12:26:16 +00:00
] )