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
2019-01-24 12:25:44 +00:00
from frappe . permissions import add_permission , update_permission_property
2017-06-21 11:52:38 +00:00
from erpnext . regional . india import states
2018-08-01 12:15:05 +00:00
from erpnext . accounts . utils import get_fiscal_year
from frappe . utils import today
2017-06-21 11:52:38 +00:00
2017-06-27 12:35:17 +00:00
def setup ( company = None , patch = True ) :
2018-11-13 10:26:15 +00:00
setup_company_independent_fixtures ( )
2018-11-12 11:49:56 +00:00
if not patch :
update_address_template ( )
2018-11-13 10:26:15 +00:00
make_fixtures ( company )
2018-11-12 11:49:56 +00:00
# TODO: for all countries
def setup_company_independent_fixtures ( ) :
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-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 ' ,
2018-08-20 12:23:56 +00:00
' GST Itemised Sales Register ' , ' GST Itemised Purchase Register ' , ' Eway Bill ' ) :
2017-06-22 11:07:04 +00:00
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 )
2019-01-24 12:25:44 +00:00
add_permission ( doctype , ' Accounts Manager ' , 0 )
update_permission_property ( doctype , ' Accounts Manager ' , 0 , ' write ' , 1 )
update_permission_property ( doctype , ' Accounts Manager ' , 0 , ' create ' , 1 )
2017-06-21 11:52:38 +00:00
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 ' ,
2018-11-13 12:49:58 +00:00
fieldtype = ' Data ' , fetch_from = ' item_code.gst_hsn_code ' , insert_after = ' description ' ,
2019-04-01 06:21:54 +00:00
allow_on_submit = 1 , print_hide = 1 , fetch_if_empty = 1 )
2019-03-21 15:17:47 +00:00
nil_rated_exempt = dict ( fieldname = ' is_nil_exempt ' , label = ' Is nil rated or exempted ' ,
fieldtype = ' Check ' , fetch_from = ' item_code.is_nil_exempt ' , insert_after = ' gst_hsn_code ' ,
print_hide = 1 )
is_non_gst = dict ( fieldname = ' is_non_gst ' , label = ' Is Non GST ' ,
fieldtype = ' Check ' , fetch_from = ' item_code.is_non_gst ' , insert_after = ' is_nil_exempt ' ,
print_hide = 1 )
purchase_invoice_gst_category = [
dict ( fieldname = ' gst_section ' , label = ' GST Details ' , fieldtype = ' Section Break ' ,
insert_after = ' language ' , print_hide = 1 , collapsible = 1 ) ,
dict ( fieldname = ' gst_category ' , label = ' GST Category ' ,
2019-04-01 15:26:51 +00:00
fieldtype = ' Select ' , insert_after = ' gst_section ' , print_hide = 1 ,
2019-05-01 08:48:21 +00:00
options = ' \n Registered Regular \n Registered Composition \n Unregistered \n SEZ \n Overseas \n UIN Holders ' ,
2019-04-01 15:26:51 +00:00
fetch_from = ' supplier.gst_category ' , fetch_if_empty = 1 )
2019-03-21 15:17:47 +00:00
]
sales_invoice_gst_category = [
2017-08-21 02:58:55 +00:00
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 ) ,
2019-03-21 15:17:47 +00:00
dict ( fieldname = ' gst_category ' , label = ' GST Category ' ,
2019-04-01 15:26:51 +00:00
fieldtype = ' Select ' , insert_after = ' gst_section ' , print_hide = 1 ,
2019-05-01 08:48:21 +00:00
options = ' \n Registered Regular \n Registered Composition \n Unregistered \n SEZ \n Overseas \n Consumer \n Deemed Export \n UIN Holders ' ,
2019-04-01 15:26:51 +00:00
fetch_from = ' customer.gst_category ' , fetch_if_empty = 1 )
2019-03-21 15:17:47 +00:00
]
invoice_gst_fields = [
2017-08-21 02:58:55 +00:00
dict ( fieldname = ' invoice_copy ' , label = ' Invoice Copy ' ,
2019-03-21 15:17:47 +00:00
fieldtype = ' Select ' , insert_after = ' gst_category ' , print_hide = 1 , allow_on_submit = 1 ,
2017-08-21 02:58:55 +00:00
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 = ' export_type ' , label = ' Export Type ' ,
2019-03-21 15:17:47 +00:00
fieldtype = ' Select ' , insert_after = ' reverse_charge ' , print_hide = 1 ,
depends_on = ' eval:in_list([ " SEZ " , " Overseas " , " Deemed Export " ], doc.gst_category) ' ,
2017-08-21 02:58:55 +00:00
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 ) ,
2019-01-09 11:39:11 +00:00
]
purchase_invoice_itc_fields = [
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 ,
2019-03-21 15:17:47 +00:00
options = ' Input Service Distributor \n Import Of Service \n Import Of Capital Goods \n Ineligible \n All Other ITC ' , default = " All Other ITC " ) ,
2018-01-29 08:27:34 +00:00
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 ) ,
2019-01-09 11:39:11 +00:00
]
sales_invoice_shipping_fields = [
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 ,
2019-03-21 15:17:47 +00:00
depends_on = " eval:doc.gst_category== ' Overseas ' " ) ,
2018-01-29 08:27:34 +00:00
dict ( fieldname = ' shipping_bill_number ' , label = ' Shipping Bill Number ' ,
fieldtype = ' Data ' , insert_after = ' port_code ' , print_hide = 1 ,
2019-03-21 15:17:47 +00:00
depends_on = " eval:doc.gst_category== ' Overseas ' " ) ,
2018-01-29 08:27:34 +00:00
dict ( fieldname = ' shipping_bill_date ' , label = ' Shipping Bill Date ' ,
fieldtype = ' Date ' , insert_after = ' shipping_bill_number ' , print_hide = 1 ,
2019-03-21 15:17:47 +00:00
depends_on = " eval:doc.gst_category== ' Overseas ' " ) ,
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 )
]
2018-10-10 09:21:26 +00:00
ewaybill_fields = [
{
' fieldname ' : ' distance ' ,
' label ' : ' Distance (in km) ' ,
' fieldtype ' : ' Float ' ,
' insert_after ' : ' vehicle_no ' ,
' print_hide ' : 1
} ,
{
' fieldname ' : ' gst_transporter_id ' ,
' label ' : ' GST Transporter ID ' ,
' fieldtype ' : ' Data ' ,
2019-07-03 05:04:31 +00:00
' insert_after ' : ' transporter ' ,
' fetch_from ' : ' transporter.gst_transporter_id ' ,
' print_hide ' : 1 ,
' translatable ' : 0
} ,
{
' fieldname ' : ' mode_of_transport ' ,
' label ' : ' Mode of Transport ' ,
' fieldtype ' : ' Select ' ,
' options ' : ' \n Road \n Air \n Rail \n Ship ' ,
' default ' : ' Road ' ,
2018-10-10 09:21:26 +00:00
' insert_after ' : ' transporter_name ' ,
2019-07-03 05:04:31 +00:00
' print_hide ' : 1 ,
' translatable ' : 0
} ,
{
' fieldname ' : ' gst_vehicle_type ' ,
' label ' : ' GST Vehicle Type ' ,
' fieldtype ' : ' Select ' ,
' options ' : ' Regular \n Over Dimensional Cargo (ODC) ' ,
' depends_on ' : ' eval:(doc.mode_of_transport === " Road " ) ' ,
' default ' : ' Regular ' ,
' insert_after ' : ' lr_date ' ,
' print_hide ' : 1 ,
' translatable ' : 0
}
]
si_ewaybill_fields = [
{
' fieldname ' : ' transporter_info ' ,
' label ' : ' Transporter Info ' ,
' fieldtype ' : ' Section Break ' ,
' insert_after ' : ' terms ' ,
' collapsible ' : 1 ,
' collapsible_depends_on ' : ' transporter ' ,
' print_hide ' : 1
} ,
{
' fieldname ' : ' transporter ' ,
' label ' : ' Transporter ' ,
' fieldtype ' : ' Link ' ,
' insert_after ' : ' transporter_info ' ,
' options ' : ' Supplier ' ,
' print_hide ' : 1
} ,
{
' fieldname ' : ' gst_transporter_id ' ,
' label ' : ' GST Transporter ID ' ,
' fieldtype ' : ' Data ' ,
' insert_after ' : ' transporter ' ,
2018-10-10 09:21:26 +00:00
' fetch_from ' : ' transporter.gst_transporter_id ' ,
2019-07-03 05:04:31 +00:00
' print_hide ' : 1 ,
' translatable ' : 0
} ,
{
' fieldname ' : ' driver ' ,
' label ' : ' Driver ' ,
' fieldtype ' : ' Link ' ,
' insert_after ' : ' gst_transporter_id ' ,
' options ' : ' Driver ' ,
' print_hide ' : 1
} ,
{
' fieldname ' : ' lr_no ' ,
' label ' : ' Transport Receipt No ' ,
' fieldtype ' : ' Data ' ,
' insert_after ' : ' driver ' ,
' print_hide ' : 1 ,
' translatable ' : 0
} ,
{
' fieldname ' : ' vehicle_no ' ,
' label ' : ' Vehicle No ' ,
' fieldtype ' : ' Data ' ,
' insert_after ' : ' lr_no ' ,
' print_hide ' : 1 ,
' translatable ' : 0
} ,
{
' fieldname ' : ' distance ' ,
' label ' : ' Distance (in km) ' ,
' fieldtype ' : ' Float ' ,
' insert_after ' : ' vehicle_no ' ,
2018-10-10 09:21:26 +00:00
' print_hide ' : 1
} ,
2019-07-03 05:04:31 +00:00
{
' fieldname ' : ' transporter_col_break ' ,
' fieldtype ' : ' Column Break ' ,
' insert_after ' : ' distance '
} ,
{
' fieldname ' : ' transporter_name ' ,
' label ' : ' Transporter Name ' ,
' fieldtype ' : ' Data ' ,
' insert_after ' : ' transporter_col_break ' ,
' fetch_from ' : ' transporter.name ' ,
' read_only ' : 1 ,
' print_hide ' : 1 ,
' translatable ' : 0
} ,
2018-10-10 09:21:26 +00:00
{
' fieldname ' : ' mode_of_transport ' ,
' label ' : ' Mode of Transport ' ,
' fieldtype ' : ' Select ' ,
' options ' : ' \n Road \n Air \n Rail \n Ship ' ,
' default ' : ' Road ' ,
2019-07-03 05:04:31 +00:00
' insert_after ' : ' transporter_name ' ,
' print_hide ' : 1 ,
' translatable ' : 0
} ,
{
' fieldname ' : ' driver_name ' ,
' label ' : ' Driver Name ' ,
' fieldtype ' : ' Data ' ,
' insert_after ' : ' mode_of_transport ' ,
' fetch_from ' : ' driver.full_name ' ,
' print_hide ' : 1 ,
' translatable ' : 0
} ,
{
' fieldname ' : ' lr_date ' ,
' label ' : ' Transport Receipt Date ' ,
' fieldtype ' : ' Date ' ,
' insert_after ' : ' driver_name ' ,
' default ' : ' Today ' ,
2018-10-10 09:21:26 +00:00
' print_hide ' : 1
} ,
{
' fieldname ' : ' gst_vehicle_type ' ,
' label ' : ' GST Vehicle Type ' ,
' fieldtype ' : ' Select ' ,
2019-07-03 05:04:31 +00:00
' options ' : ' Regular \n Over Dimensional Cargo (ODC) ' ,
2018-10-10 09:21:26 +00:00
' depends_on ' : ' eval:(doc.mode_of_transport === " Road " ) ' ,
2019-07-03 05:04:31 +00:00
' default ' : ' Regular ' ,
' insert_after ' : ' lr_date ' ,
' print_hide ' : 1 ,
' translatable ' : 0
} ,
{
' fieldname ' : ' ewaybill ' ,
' label ' : ' e-Way Bill No. ' ,
' fieldtype ' : ' Data ' ,
' depends_on ' : ' eval:(doc.docstatus === 1) ' ,
' allow_on_submit ' : 1 ,
2019-07-14 12:45:19 +00:00
' insert_after ' : ' tax_id ' ,
2019-07-03 05:04:31 +00:00
' translatable ' : 0
2018-10-10 09:21:26 +00:00
}
]
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 ' ,
2018-09-07 10:44:44 +00:00
fieldtype = ' Data ' , insert_after = ' gst_state ' , read_only = 1 ) ,
2017-06-21 11:52:38 +00:00
] ,
2019-03-21 15:17:47 +00:00
' Purchase Invoice ' : purchase_invoice_gst_category + invoice_gst_fields + purchase_invoice_itc_fields + purchase_invoice_gst_fields ,
2019-01-09 11:39:11 +00:00
' Purchase Order ' : purchase_invoice_gst_fields ,
' Purchase Receipt ' : purchase_invoice_gst_fields ,
2019-07-03 05:04:31 +00:00
' Sales Invoice ' : sales_invoice_gst_category + invoice_gst_fields + sales_invoice_shipping_fields + sales_invoice_gst_fields + si_ewaybill_fields ,
' Delivery Note ' : sales_invoice_gst_fields + ewaybill_fields + sales_invoice_shipping_fields ,
2019-01-09 11:39:11 +00:00
' Sales Order ' : sales_invoice_gst_fields ,
2018-06-05 05:57:53 +00:00
' 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 ' ) ,
2019-03-21 15:17:47 +00:00
dict ( fieldname = ' is_nil_exempt ' , label = ' Is nil rated or exempted ' ,
fieldtype = ' Check ' , insert_after = ' gst_hsn_code ' ) ,
dict ( fieldname = ' is_non_gst ' , label = ' Is Non GST ' ,
fieldtype = ' Check ' , insert_after = ' is_nil_exempt ' )
2017-06-21 11:52:38 +00:00
] ,
2019-03-21 15:17:47 +00:00
' Quotation Item ' : [ hsn_sac_field , nil_rated_exempt , is_non_gst ] ,
' Supplier Quotation Item ' : [ hsn_sac_field , nil_rated_exempt , is_non_gst ] ,
' Sales Order Item ' : [ hsn_sac_field , nil_rated_exempt , is_non_gst ] ,
' Delivery Note Item ' : [ hsn_sac_field , nil_rated_exempt , is_non_gst ] ,
' Sales Invoice Item ' : [ hsn_sac_field , nil_rated_exempt , is_non_gst ] ,
' Purchase Order Item ' : [ hsn_sac_field , nil_rated_exempt , is_non_gst ] ,
' Purchase Receipt Item ' : [ hsn_sac_field , nil_rated_exempt , is_non_gst ] ,
' Purchase Invoice Item ' : [ hsn_sac_field , nil_rated_exempt , is_non_gst ] ,
2019-04-01 14:08:43 +00:00
' Material Request Item ' : [ hsn_sac_field , nil_rated_exempt , is_non_gst ] ,
2018-04-05 09:24:51 +00:00
' 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 ' ,
2019-06-14 09:55:57 +00:00
fieldtype = ' Section Break ' , insert_after = ' asset_received_but_not_billed ' , collapsible = 1 ) ,
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 ' ,
2019-05-06 10:54:10 +00:00
fieldtype = ' Link ' , options = ' Salary Component ' , insert_after = ' hra_component ' ) ,
dict ( fieldname = ' bank_remittance_section ' , label = ' Bank Remittance Settings ' ,
fieldtype = ' Section Break ' , collapsible = 1 , insert_after = ' arrear_component ' ) ,
dict ( fieldname = ' client_code ' , label = ' Client Code ' , fieldtype = ' Data ' ,
insert_after = ' bank_remittance_section ' ) ,
dict ( fieldname = ' remittance_column_break ' , fieldtype = ' Column Break ' ,
insert_after = ' client_code ' ) ,
dict ( fieldname = ' product_code ' , label = ' Product Code ' , fieldtype = ' Data ' ,
insert_after = ' remittance_column_break ' ) ,
2018-06-14 12:26:16 +00:00
] ,
' Employee Tax Exemption Declaration ' : [
dict ( fieldname = ' hra_section ' , label = ' HRA Exemption ' ,
fieldtype = ' Section Break ' , insert_after = ' declarations ' ) ,
dict ( fieldname = ' monthly_house_rent ' , label = ' Monthly House Rent ' ,
2019-04-25 13:14:10 +00:00
fieldtype = ' Currency ' , insert_after = ' hra_section ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' rented_in_metro_city ' , label = ' Rented in Metro City ' ,
2019-04-25 13:14:10 +00:00
fieldtype = ' Check ' , insert_after = ' monthly_house_rent ' , depends_on = ' monthly_house_rent ' ) ,
dict ( fieldname = ' salary_structure_hra ' , label = ' HRA as per Salary Structure ' ,
fieldtype = ' Currency ' , insert_after = ' rented_in_metro_city ' , read_only = 1 , depends_on = ' monthly_house_rent ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' hra_column_break ' , fieldtype = ' Column Break ' ,
2019-04-25 13:14:10 +00:00
insert_after = ' salary_structure_hra ' , depends_on = ' monthly_house_rent ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' annual_hra_exemption ' , label = ' Annual HRA Exemption ' ,
2019-04-25 13:14:10 +00:00
fieldtype = ' Currency ' , insert_after = ' hra_column_break ' , read_only = 1 , depends_on = ' monthly_house_rent ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' monthly_hra_exemption ' , label = ' Monthly HRA Exemption ' ,
2019-04-25 13:14:10 +00:00
fieldtype = ' Currency ' , insert_after = ' annual_hra_exemption ' , read_only = 1 , depends_on = ' monthly_house_rent ' )
2018-06-14 12:26:16 +00:00
] ,
' 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 ' ,
2019-04-25 13:14:10 +00:00
fieldtype = ' Check ' , insert_after = ' house_rent_payment_amount ' , depends_on = ' house_rent_payment_amount ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' rented_from_date ' , label = ' Rented From Date ' ,
2019-04-25 13:14:10 +00:00
fieldtype = ' Date ' , insert_after = ' rented_in_metro_city ' , depends_on = ' house_rent_payment_amount ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' rented_to_date ' , label = ' Rented To Date ' ,
2019-04-25 13:14:10 +00:00
fieldtype = ' Date ' , insert_after = ' rented_from_date ' , depends_on = ' house_rent_payment_amount ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' hra_column_break ' , fieldtype = ' Column Break ' ,
2019-04-25 13:14:10 +00:00
insert_after = ' rented_to_date ' , depends_on = ' house_rent_payment_amount ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' monthly_house_rent ' , label = ' Monthly House Rent ' ,
2019-04-25 13:14:10 +00:00
fieldtype = ' Currency ' , insert_after = ' hra_column_break ' , read_only = 1 , depends_on = ' house_rent_payment_amount ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' monthly_hra_exemption ' , label = ' Monthly Eligible Amount ' ,
2019-04-25 13:14:10 +00:00
fieldtype = ' Currency ' , insert_after = ' monthly_house_rent ' , read_only = 1 , depends_on = ' house_rent_payment_amount ' ) ,
2018-06-14 12:26:16 +00:00
dict ( fieldname = ' total_eligible_hra_exemption ' , label = ' Total Eligible HRA Exemption ' ,
2019-04-25 13:14:10 +00:00
fieldtype = ' Currency ' , insert_after = ' monthly_hra_exemption ' , read_only = 1 , depends_on = ' house_rent_payment_amount ' )
2018-10-10 09:21:26 +00:00
] ,
' Supplier ' : [
{
' fieldname ' : ' gst_transporter_id ' ,
' label ' : ' GST Transporter ID ' ,
' fieldtype ' : ' Data ' ,
' insert_after ' : ' supplier_type ' ,
' depends_on ' : ' eval:doc.is_transporter '
2019-03-21 15:17:47 +00:00
} ,
{
' fieldname ' : ' gst_category ' ,
' label ' : ' GST Category ' ,
' fieldtype ' : ' Select ' ,
' insert_after ' : ' gst_transporter_id ' ,
' options ' : ' Registered Regular \n Registered Composition \n Unregistered \n SEZ \n Overseas \n UIN Holders ' ,
' default ' : ' Unregistered '
}
] ,
' Customer ' : [
{
' fieldname ' : ' gst_category ' ,
' label ' : ' GST Category ' ,
' fieldtype ' : ' Select ' ,
' insert_after ' : ' customer_type ' ,
' options ' : ' Registered Regular \n Registered Composition \n Unregistered \n SEZ \n Overseas \n Consumer \n Deemed Export \n UIN Holders ' ,
' default ' : ' Unregistered '
2018-10-10 09:21:26 +00:00
}
2018-06-14 12:26:16 +00:00
]
2017-06-21 11:52:38 +00:00
}
2019-03-21 15:17:47 +00:00
create_custom_fields ( custom_fields , 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 )
2018-07-24 05:37:28 +00:00
set_tds_account ( 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 :
2019-05-14 10:51:09 +00:00
frappe . clear_messages ( )
2018-08-01 12:15:05 +00:00
except frappe . DuplicateEntryError :
2019-05-14 10:51:09 +00:00
frappe . clear_messages ( )
2018-05-11 07:46:16 +00:00
2018-08-01 12:15:05 +00:00
# create records for Tax Withholding Category
2018-07-24 05:37:28 +00:00
set_tax_withholding_category ( company )
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 ' }
] )
2018-07-24 05:37:28 +00:00
def set_tax_withholding_category ( company ) :
2018-05-11 07:46:16 +00:00
accounts = [ ]
2018-07-24 05:37:28 +00:00
abbr = frappe . get_value ( " Company " , company , " abbr " )
tds_account = frappe . get_value ( " Account " , ' TDS Payable - {0} ' . format ( abbr ) , ' name ' )
2018-05-11 07:46:16 +00:00
if company and tds_account :
2018-07-24 05:37:28 +00:00
accounts = [ dict ( company = company , account = tds_account ) ]
2018-05-11 07:46:16 +00:00
2019-02-12 05:58:20 +00:00
fiscal_year = get_fiscal_year ( today ( ) , company = company ) [ 0 ]
2018-08-01 12:15:05 +00:00
docs = get_tds_details ( accounts , fiscal_year )
for d in docs :
try :
doc = frappe . get_doc ( d )
doc . flags . ignore_permissions = True
2019-02-12 05:58:20 +00:00
doc . flags . ignore_mandatory = True
2018-08-01 12:15:05 +00:00
doc . insert ( )
except frappe . DuplicateEntryError :
doc = frappe . get_doc ( " Tax Withholding Category " , d . get ( " name " ) )
2019-03-23 05:00:12 +00:00
if accounts :
doc . append ( " accounts " , accounts [ 0 ] )
2018-08-01 12:15:05 +00:00
# if fiscal year don't match with any of the already entered data, append rate row
fy_exist = [ k for k in doc . get ( ' rates ' ) if k . get ( ' fiscal_year ' ) == fiscal_year ]
if not fy_exist :
doc . append ( " rates " , d . get ( ' rates ' ) [ 0 ] )
2018-07-24 05:37:28 +00:00
2018-08-01 12:15:05 +00:00
doc . save ( )
2018-05-11 07:46:16 +00:00
def set_tds_account ( docs , company ) :
2018-07-24 05:37:28 +00:00
abbr = frappe . get_value ( " Company " , company , " abbr " )
2018-11-20 11:16:25 +00:00
parent_account = frappe . db . get_value ( " Account " , filters = { " account_name " : " Duties and Taxes " , " company " : company } )
if parent_account :
docs . extend ( [
{
" doctype " : " Account " ,
" account_name " : " TDS Payable " ,
" account_type " : " Tax " ,
" parent_account " : parent_account ,
" company " : company
}
] )
2018-08-01 12:15:05 +00:00
def get_tds_details ( accounts , fiscal_year ) :
# bootstrap default tax withholding sections
return [
dict ( name = " TDS - 194C - Company " ,
category_name = " Payment to Contractors (Single / Aggregate) " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 2 ,
" single_threshold " : 30000 , " cumulative_threshold " : 100000 } ] ) ,
dict ( name = " TDS - 194C - Individual " ,
category_name = " Payment to Contractors (Single / Aggregate) " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 1 ,
" single_threshold " : 30000 , " cumulative_threshold " : 100000 } ] ) ,
dict ( name = " TDS - 194C - No PAN / Invalid PAN " ,
category_name = " Payment to Contractors (Single / Aggregate) " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 20 ,
" single_threshold " : 30000 , " cumulative_threshold " : 100000 } ] ) ,
dict ( name = " TDS - 194D - Company " ,
category_name = " Insurance Commission " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 5 ,
" single_threshold " : 15000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194D - Company Assessee " ,
category_name = " Insurance Commission " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 10 ,
" single_threshold " : 15000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194D - Individual " ,
category_name = " Insurance Commission " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 5 ,
" single_threshold " : 15000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194D - No PAN / Invalid PAN " ,
category_name = " Insurance Commission " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 20 ,
" single_threshold " : 15000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194DA - Company " ,
category_name = " Non-exempt payments made under a life insurance policy " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 1 ,
" single_threshold " : 100000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194DA - Individual " ,
category_name = " Non-exempt payments made under a life insurance policy " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 1 ,
" single_threshold " : 100000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194DA - No PAN / Invalid PAN " ,
category_name = " Non-exempt payments made under a life insurance policy " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 20 ,
" single_threshold " : 100000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194H - Company " ,
category_name = " Commission / Brokerage " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 5 ,
" single_threshold " : 15000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194H - Individual " ,
category_name = " Commission / Brokerage " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 5 ,
" single_threshold " : 15000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194H - No PAN / Invalid PAN " ,
category_name = " Commission / Brokerage " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 20 ,
" single_threshold " : 15000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194I - Rent - Company " ,
category_name = " Rent " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 10 ,
" single_threshold " : 180000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194I - Rent - Individual " ,
category_name = " Rent " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 10 ,
" single_threshold " : 180000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194I - Rent - No PAN / Invalid PAN " ,
category_name = " Rent " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 20 ,
" single_threshold " : 180000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194I - Rent/Machinery - Company " ,
category_name = " Rent-Plant / Machinery " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 2 ,
" single_threshold " : 180000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194I - Rent/Machinery - Individual " ,
category_name = " Rent-Plant / Machinery " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 2 ,
" single_threshold " : 180000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194I - Rent/Machinery - No PAN / Invalid PAN " ,
category_name = " Rent-Plant / Machinery " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 20 ,
" single_threshold " : 180000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194J - Professional Fees - Company " ,
category_name = " Professional Fees " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 10 ,
" single_threshold " : 30000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194J - Professional Fees - Individual " ,
category_name = " Professional Fees " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 10 ,
" single_threshold " : 30000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194J - Professional Fees - No PAN / Invalid PAN " ,
category_name = " Professional Fees " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 20 ,
" single_threshold " : 30000 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194J - Director Fees - Company " ,
category_name = " Director Fees " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 10 ,
" single_threshold " : 0 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194J - Director Fees - Individual " ,
category_name = " Director Fees " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 10 ,
" single_threshold " : 0 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194J - Director Fees - No PAN / Invalid PAN " ,
category_name = " Director Fees " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 20 ,
" single_threshold " : 0 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194 - Dividends - Company " ,
category_name = " Dividends " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 10 ,
" single_threshold " : 2500 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194 - Dividends - Individual " ,
category_name = " Dividends " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 10 ,
" single_threshold " : 2500 , " cumulative_threshold " : 0 } ] ) ,
dict ( name = " TDS - 194 - Dividends - No PAN / Invalid PAN " ,
category_name = " Dividends " ,
doctype = " Tax Withholding Category " , accounts = accounts ,
rates = [ { " fiscal_year " : fiscal_year , " tax_withholding_rate " : 20 ,
" single_threshold " : 2500 , " cumulative_threshold " : 0 } ] )
2019-05-06 10:54:10 +00:00
]