| # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors |
| # License: GNU General Public License v3. See license.txt |
| |
| |
| import frappe, os, json |
| from frappe.custom.doctype.custom_field.custom_field import create_custom_fields |
| from frappe.custom.doctype.property_setter.property_setter import make_property_setter |
| from frappe.permissions import add_permission, update_permission_property |
| from erpnext.regional.india import states |
| from erpnext.accounts.utils import get_fiscal_year, FiscalYearError |
| from frappe.utils import today |
| |
| |
| def setup(company=None, patch=True): |
| # Company independent fixtures should be called only once at the first company setup |
| if patch or frappe.db.count("Company", {"country": "India"}) <= 1: |
| setup_company_independent_fixtures(patch=patch) |
| |
| if not patch: |
| make_fixtures(company) |
| |
| |
| # TODO: for all countries |
| def setup_company_independent_fixtures(patch=False): |
| make_custom_fields() |
| make_property_setters(patch=patch) |
| add_permissions() |
| add_custom_roles_for_reports() |
| frappe.enqueue("erpnext.regional.india.setup.add_hsn_sac_codes", now=frappe.flags.in_test) |
| create_gratuity_rule() |
| add_print_formats() |
| update_accounts_settings_for_taxes() |
| |
| |
| def add_hsn_sac_codes(): |
| if frappe.flags.in_test and frappe.flags.created_hsn_codes: |
| return |
| |
| # HSN codes |
| with open(os.path.join(os.path.dirname(__file__), "hsn_code_data.json"), "r") as f: |
| hsn_codes = json.loads(f.read()) |
| |
| create_hsn_codes(hsn_codes, code_field="hsn_code") |
| |
| # 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") |
| |
| if frappe.flags.in_test: |
| frappe.flags.created_hsn_codes = True |
| |
| |
| def create_hsn_codes(data, code_field): |
| for d in data: |
| 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] |
| hsn_code.db_insert(ignore_if_duplicate=True) |
| |
| |
| def add_custom_roles_for_reports(): |
| for report_name in ( |
| "GST Sales Register", |
| "GST Purchase Register", |
| "GST Itemised Sales Register", |
| "GST Itemised Purchase Register", |
| "Eway Bill", |
| "E-Invoice Summary", |
| ): |
| |
| 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() |
| |
| for report_name in ("Professional Tax Deductions", "Provident Fund Deductions"): |
| |
| 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="HR User"), dict(role="HR Manager"), dict(role="Employee")], |
| ) |
| ).insert() |
| |
| for report_name in ("HSN-wise-summary of outward supplies", "GSTR-1", "GSTR-2"): |
| |
| 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"), dict(role="Auditor")], |
| ) |
| ).insert() |
| |
| |
| def add_permissions(): |
| for doctype in ( |
| "GST HSN Code", |
| "GST Settings", |
| "GSTR 3B Report", |
| "Lower Deduction Certificate", |
| "E Invoice Settings", |
| ): |
| add_permission(doctype, "All", 0) |
| for role in ("Accounts Manager", "Accounts User", "System Manager"): |
| add_permission(doctype, role, 0) |
| update_permission_property(doctype, role, 0, "write", 1) |
| update_permission_property(doctype, role, 0, "create", 1) |
| |
| if doctype == "GST HSN Code": |
| for role in ("Item Manager", "Stock Manager"): |
| add_permission(doctype, role, 0) |
| update_permission_property(doctype, role, 0, "write", 1) |
| update_permission_property(doctype, role, 0, "create", 1) |
| |
| |
| def add_print_formats(): |
| frappe.reload_doc("regional", "print_format", "gst_tax_invoice") |
| frappe.reload_doc("selling", "print_format", "gst_pos_invoice") |
| frappe.reload_doc("accounts", "print_format", "GST E-Invoice") |
| |
| frappe.db.set_value("Print Format", "GST POS Invoice", "disabled", 0) |
| frappe.db.set_value("Print Format", "GST Tax Invoice", "disabled", 0) |
| frappe.db.set_value("Print Format", "GST E-Invoice", "disabled", 0) |
| |
| |
| def make_property_setters(patch=False): |
| # GST rules do not allow for an invoice no. bigger than 16 characters |
| journal_entry_types = frappe.get_meta("Journal Entry").get_options("voucher_type").split("\n") + [ |
| "Reversal Of ITC" |
| ] |
| sales_invoice_series = ["SINV-.YY.-", "SRET-.YY.-", ""] + frappe.get_meta( |
| "Sales Invoice" |
| ).get_options("naming_series").split("\n") |
| purchase_invoice_series = ["PINV-.YY.-", "PRET-.YY.-", ""] + frappe.get_meta( |
| "Purchase Invoice" |
| ).get_options("naming_series").split("\n") |
| |
| if not patch: |
| make_property_setter( |
| "Sales Invoice", "naming_series", "options", "\n".join(sales_invoice_series), "" |
| ) |
| make_property_setter( |
| "Purchase Invoice", "naming_series", "options", "\n".join(purchase_invoice_series), "" |
| ) |
| make_property_setter( |
| "Journal Entry", "voucher_type", "options", "\n".join(journal_entry_types), "" |
| ) |
| |
| |
| def make_custom_fields(update=True): |
| custom_fields = get_custom_fields() |
| create_custom_fields(custom_fields, update=update) |
| |
| |
| def get_custom_fields(): |
| hsn_sac_field = dict( |
| fieldname="gst_hsn_code", |
| label="HSN/SAC", |
| fieldtype="Data", |
| fetch_from="item_code.gst_hsn_code", |
| insert_after="description", |
| allow_on_submit=1, |
| print_hide=1, |
| fetch_if_empty=1, |
| ) |
| 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, |
| ) |
| taxable_value = dict( |
| fieldname="taxable_value", |
| label="Taxable Value", |
| fieldtype="Currency", |
| insert_after="base_net_amount", |
| hidden=1, |
| options="Company:company:default_currency", |
| 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", |
| fieldtype="Select", |
| insert_after="gst_section", |
| print_hide=1, |
| options="\nRegistered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nUIN Holders", |
| fetch_from="supplier.gst_category", |
| fetch_if_empty=1, |
| ), |
| dict( |
| fieldname="export_type", |
| label="Export Type", |
| fieldtype="Select", |
| insert_after="gst_category", |
| print_hide=1, |
| depends_on='eval:in_list(["SEZ", "Overseas"], doc.gst_category)', |
| options="\nWith Payment of Tax\nWithout Payment of Tax", |
| fetch_from="supplier.export_type", |
| fetch_if_empty=1, |
| ), |
| ] |
| |
| sales_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", |
| fieldtype="Select", |
| insert_after="gst_section", |
| print_hide=1, |
| options="\nRegistered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nConsumer\nDeemed Export\nUIN Holders", |
| fetch_from="customer.gst_category", |
| fetch_if_empty=1, |
| length=25, |
| ), |
| dict( |
| fieldname="export_type", |
| label="Export Type", |
| fieldtype="Select", |
| insert_after="gst_category", |
| print_hide=1, |
| depends_on='eval:in_list(["SEZ", "Overseas", "Deemed Export"], doc.gst_category)', |
| options="\nWith Payment of Tax\nWithout Payment of Tax", |
| fetch_from="customer.export_type", |
| fetch_if_empty=1, |
| length=25, |
| ), |
| ] |
| |
| delivery_note_gst_category = [ |
| dict( |
| fieldname="gst_category", |
| label="GST Category", |
| fieldtype="Select", |
| insert_after="gst_vehicle_type", |
| print_hide=1, |
| options="\nRegistered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nConsumer\nDeemed Export\nUIN Holders", |
| fetch_from="customer.gst_category", |
| fetch_if_empty=1, |
| ), |
| ] |
| |
| invoice_gst_fields = [ |
| dict( |
| fieldname="invoice_copy", |
| label="Invoice Copy", |
| length=30, |
| fieldtype="Select", |
| insert_after="export_type", |
| print_hide=1, |
| allow_on_submit=1, |
| options="Original for Recipient\nDuplicate for Transporter\nDuplicate for Supplier\nTriplicate for Supplier", |
| ), |
| dict( |
| fieldname="reverse_charge", |
| label="Reverse Charge", |
| length=2, |
| fieldtype="Select", |
| insert_after="invoice_copy", |
| print_hide=1, |
| options="Y\nN", |
| default="N", |
| ), |
| dict( |
| fieldname="ecommerce_gstin", |
| label="E-commerce GSTIN", |
| length=15, |
| fieldtype="Data", |
| insert_after="export_type", |
| print_hide=1, |
| ), |
| dict(fieldname="gst_col_break", fieldtype="Column Break", insert_after="ecommerce_gstin"), |
| dict( |
| fieldname="reason_for_issuing_document", |
| label="Reason For Issuing document", |
| fieldtype="Select", |
| insert_after="gst_col_break", |
| print_hide=1, |
| depends_on="eval:doc.is_return==1", |
| length=45, |
| options="\n01-Sales Return\n02-Post Sale Discount\n03-Deficiency in services\n04-Correction in Invoice\n05-Change in POS\n06-Finalization of Provisional assessment\n07-Others", |
| ), |
| ] |
| |
| purchase_invoice_gst_fields = [ |
| dict( |
| fieldname="supplier_gstin", |
| label="Supplier GSTIN", |
| fieldtype="Data", |
| insert_after="supplier_address", |
| fetch_from="supplier_address.gstin", |
| print_hide=1, |
| read_only=1, |
| ), |
| dict( |
| fieldname="company_gstin", |
| label="Company GSTIN", |
| fieldtype="Data", |
| insert_after="shipping_address_display", |
| fetch_from="shipping_address.gstin", |
| print_hide=1, |
| read_only=1, |
| ), |
| dict( |
| fieldname="place_of_supply", |
| label="Place of Supply", |
| fieldtype="Data", |
| insert_after="shipping_address", |
| print_hide=1, |
| read_only=1, |
| ), |
| ] |
| |
| purchase_invoice_itc_fields = [ |
| dict( |
| fieldname="eligibility_for_itc", |
| label="Eligibility For ITC", |
| fieldtype="Select", |
| insert_after="reason_for_issuing_document", |
| print_hide=1, |
| options="Input Service Distributor\nImport Of Service\nImport Of Capital Goods\nITC on Reverse Charge\nIneligible As Per Section 17(5)\nIneligible Others\nAll Other ITC", |
| default="All Other ITC", |
| ), |
| dict( |
| fieldname="itc_integrated_tax", |
| label="Availed ITC Integrated Tax", |
| fieldtype="Currency", |
| insert_after="eligibility_for_itc", |
| options="Company:company:default_currency", |
| print_hide=1, |
| ), |
| dict( |
| fieldname="itc_central_tax", |
| label="Availed ITC Central Tax", |
| fieldtype="Currency", |
| insert_after="itc_integrated_tax", |
| options="Company:company:default_currency", |
| print_hide=1, |
| ), |
| dict( |
| fieldname="itc_state_tax", |
| label="Availed ITC State/UT Tax", |
| fieldtype="Currency", |
| insert_after="itc_central_tax", |
| options="Company:company:default_currency", |
| print_hide=1, |
| ), |
| dict( |
| fieldname="itc_cess_amount", |
| label="Availed ITC Cess", |
| fieldtype="Currency", |
| insert_after="itc_state_tax", |
| options="Company:company:default_currency", |
| print_hide=1, |
| ), |
| ] |
| |
| sales_invoice_gst_fields = [ |
| dict( |
| fieldname="billing_address_gstin", |
| label="Billing Address GSTIN", |
| fieldtype="Data", |
| insert_after="customer_address", |
| read_only=1, |
| fetch_from="customer_address.gstin", |
| print_hide=1, |
| length=15, |
| ), |
| dict( |
| fieldname="customer_gstin", |
| label="Customer GSTIN", |
| fieldtype="Data", |
| insert_after="shipping_address_name", |
| fetch_from="shipping_address_name.gstin", |
| print_hide=1, |
| length=15, |
| ), |
| dict( |
| fieldname="place_of_supply", |
| label="Place of Supply", |
| fieldtype="Data", |
| insert_after="customer_gstin", |
| print_hide=1, |
| read_only=1, |
| length=50, |
| ), |
| dict( |
| fieldname="company_gstin", |
| label="Company GSTIN", |
| fieldtype="Data", |
| insert_after="company_address", |
| fetch_from="company_address.gstin", |
| print_hide=1, |
| read_only=1, |
| length=15, |
| ), |
| ] |
| |
| sales_invoice_shipping_fields = [ |
| dict( |
| fieldname="port_code", |
| label="Port Code", |
| fieldtype="Data", |
| insert_after="reason_for_issuing_document", |
| print_hide=1, |
| depends_on="eval:doc.gst_category=='Overseas' ", |
| length=15, |
| ), |
| dict( |
| fieldname="shipping_bill_number", |
| label=" Shipping Bill Number", |
| fieldtype="Data", |
| insert_after="port_code", |
| print_hide=1, |
| depends_on="eval:doc.gst_category=='Overseas' ", |
| length=50, |
| ), |
| dict( |
| fieldname="shipping_bill_date", |
| label="Shipping Bill Date", |
| fieldtype="Date", |
| insert_after="shipping_bill_number", |
| print_hide=1, |
| depends_on="eval:doc.gst_category=='Overseas' ", |
| ), |
| ] |
| |
| journal_entry_fields = [ |
| dict( |
| fieldname="reversal_type", |
| label="Reversal Type", |
| fieldtype="Select", |
| insert_after="voucher_type", |
| print_hide=1, |
| options="As per rules 42 & 43 of CGST Rules\nOthers", |
| depends_on="eval:doc.voucher_type=='Reversal Of ITC'", |
| mandatory_depends_on="eval:doc.voucher_type=='Reversal Of ITC'", |
| ), |
| dict( |
| fieldname="company_address", |
| label="Company Address", |
| fieldtype="Link", |
| options="Address", |
| insert_after="reversal_type", |
| print_hide=1, |
| depends_on="eval:doc.voucher_type=='Reversal Of ITC'", |
| mandatory_depends_on="eval:doc.voucher_type=='Reversal Of ITC'", |
| ), |
| dict( |
| fieldname="company_gstin", |
| label="Company GSTIN", |
| fieldtype="Data", |
| read_only=1, |
| insert_after="company_address", |
| print_hide=1, |
| fetch_from="company_address.gstin", |
| depends_on="eval:doc.voucher_type=='Reversal Of ITC'", |
| mandatory_depends_on="eval:doc.voucher_type=='Reversal Of ITC'", |
| ), |
| ] |
| |
| inter_state_gst_field = [ |
| dict( |
| fieldname="is_inter_state", |
| label="Is Inter State", |
| fieldtype="Check", |
| insert_after="disabled", |
| print_hide=1, |
| ), |
| dict( |
| fieldname="is_reverse_charge", |
| label="Is Reverse Charge", |
| fieldtype="Check", |
| insert_after="is_inter_state", |
| print_hide=1, |
| ), |
| dict( |
| fieldname="tax_category_column_break", |
| fieldtype="Column Break", |
| insert_after="is_reverse_charge", |
| ), |
| dict( |
| fieldname="gst_state", |
| label="Source State", |
| fieldtype="Select", |
| options="\n".join(states), |
| insert_after="company", |
| ), |
| ] |
| |
| 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", |
| "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": "\nRoad\nAir\nRail\nShip", |
| "default": "Road", |
| "insert_after": "transporter_name", |
| "print_hide": 1, |
| "translatable": 0, |
| }, |
| { |
| "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": "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, |
| "insert_after": "customer_name_in_arabic", |
| "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", |
| "fetch_from": "transporter.gst_transporter_id", |
| "print_hide": 1, |
| "translatable": 0, |
| "length": 20, |
| }, |
| { |
| "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, |
| "length": 30, |
| }, |
| { |
| "fieldname": "vehicle_no", |
| "label": "Vehicle No", |
| "fieldtype": "Data", |
| "insert_after": "lr_no", |
| "print_hide": 1, |
| "translatable": 0, |
| "length": 10, |
| }, |
| { |
| "fieldname": "distance", |
| "label": "Distance (in km)", |
| "fieldtype": "Float", |
| "insert_after": "vehicle_no", |
| "print_hide": 1, |
| }, |
| {"fieldname": "transporter_col_break", "fieldtype": "Column Break", "insert_after": "distance"}, |
| { |
| "fieldname": "transporter_name", |
| "label": "Transporter Name", |
| "fieldtype": "Small Text", |
| "insert_after": "transporter_col_break", |
| "fetch_from": "transporter.name", |
| "read_only": 1, |
| "print_hide": 1, |
| "translatable": 0, |
| }, |
| { |
| "fieldname": "mode_of_transport", |
| "label": "Mode of Transport", |
| "fieldtype": "Select", |
| "options": "\nRoad\nAir\nRail\nShip", |
| "insert_after": "transporter_name", |
| "print_hide": 1, |
| "translatable": 0, |
| "length": 5, |
| }, |
| { |
| "fieldname": "driver_name", |
| "label": "Driver Name", |
| "fieldtype": "Small Text", |
| "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", |
| "print_hide": 1, |
| }, |
| { |
| "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": "Regular", |
| "insert_after": "lr_date", |
| "print_hide": 1, |
| "translatable": 0, |
| "length": 30, |
| }, |
| { |
| "fieldname": "ewaybill", |
| "label": "E-Way Bill No.", |
| "fieldtype": "Data", |
| "depends_on": "eval:((doc.docstatus === 1 || doc.ewaybill) && doc.eway_bill_cancelled === 0)", |
| "allow_on_submit": 1, |
| "insert_after": "tax_id", |
| "translatable": 0, |
| "length": 20, |
| }, |
| ] |
| |
| payment_entry_fields = [ |
| dict( |
| fieldname="gst_section", |
| label="GST Details", |
| fieldtype="Section Break", |
| insert_after="deductions", |
| print_hide=1, |
| collapsible=1, |
| ), |
| dict( |
| fieldname="company_address", |
| label="Company Address", |
| fieldtype="Link", |
| insert_after="gst_section", |
| print_hide=1, |
| options="Address", |
| ), |
| dict( |
| fieldname="company_gstin", |
| label="Company GSTIN", |
| fieldtype="Data", |
| insert_after="company_address", |
| fetch_from="company_address.gstin", |
| print_hide=1, |
| read_only=1, |
| ), |
| dict( |
| fieldname="place_of_supply", |
| label="Place of Supply", |
| fieldtype="Data", |
| insert_after="company_gstin", |
| print_hide=1, |
| read_only=1, |
| ), |
| dict(fieldname="gst_column_break", fieldtype="Column Break", insert_after="place_of_supply"), |
| dict( |
| fieldname="customer_address", |
| label="Customer Address", |
| fieldtype="Link", |
| insert_after="gst_column_break", |
| print_hide=1, |
| options="Address", |
| depends_on='eval:doc.party_type == "Customer"', |
| ), |
| dict( |
| fieldname="customer_gstin", |
| label="Customer GSTIN", |
| fieldtype="Data", |
| insert_after="customer_address", |
| fetch_from="customer_address.gstin", |
| print_hide=1, |
| read_only=1, |
| ), |
| ] |
| |
| si_einvoice_fields = [ |
| dict( |
| fieldname="irn", |
| label="IRN", |
| fieldtype="Data", |
| read_only=1, |
| insert_after="customer", |
| no_copy=1, |
| print_hide=1, |
| depends_on='eval:in_list(["Registered Regular", "SEZ", "Overseas", "Deemed Export"], doc.gst_category) && doc.irn_cancelled === 0', |
| ), |
| dict( |
| fieldname="irn_cancelled", |
| label="IRN Cancelled", |
| fieldtype="Check", |
| no_copy=1, |
| print_hide=1, |
| depends_on="eval: doc.irn", |
| allow_on_submit=1, |
| insert_after="customer", |
| ), |
| dict( |
| fieldname="eway_bill_validity", |
| label="E-Way Bill Validity", |
| fieldtype="Data", |
| no_copy=1, |
| print_hide=1, |
| depends_on="ewaybill", |
| read_only=1, |
| allow_on_submit=1, |
| insert_after="ewaybill", |
| ), |
| dict( |
| fieldname="eway_bill_cancelled", |
| label="E-Way Bill Cancelled", |
| fieldtype="Check", |
| no_copy=1, |
| print_hide=1, |
| depends_on="eval:(doc.eway_bill_cancelled === 1)", |
| read_only=1, |
| allow_on_submit=1, |
| insert_after="customer", |
| ), |
| dict( |
| fieldname="einvoice_section", |
| label="E-Invoice Fields", |
| fieldtype="Section Break", |
| insert_after="gst_vehicle_type", |
| print_hide=1, |
| hidden=1, |
| ), |
| dict( |
| fieldname="ack_no", |
| label="Ack. No.", |
| fieldtype="Data", |
| read_only=1, |
| hidden=1, |
| insert_after="einvoice_section", |
| no_copy=1, |
| print_hide=1, |
| ), |
| dict( |
| fieldname="ack_date", |
| label="Ack. Date", |
| fieldtype="Data", |
| read_only=1, |
| hidden=1, |
| insert_after="ack_no", |
| no_copy=1, |
| print_hide=1, |
| ), |
| dict( |
| fieldname="irn_cancel_date", |
| label="Cancel Date", |
| fieldtype="Data", |
| read_only=1, |
| hidden=1, |
| insert_after="ack_date", |
| no_copy=1, |
| print_hide=1, |
| ), |
| dict( |
| fieldname="signed_einvoice", |
| label="Signed E-Invoice", |
| fieldtype="Code", |
| options="JSON", |
| hidden=1, |
| insert_after="irn_cancel_date", |
| no_copy=1, |
| print_hide=1, |
| read_only=1, |
| ), |
| dict( |
| fieldname="signed_qr_code", |
| label="Signed QRCode", |
| fieldtype="Code", |
| options="JSON", |
| hidden=1, |
| insert_after="signed_einvoice", |
| no_copy=1, |
| print_hide=1, |
| read_only=1, |
| ), |
| dict( |
| fieldname="qrcode_image", |
| label="QRCode", |
| fieldtype="Attach Image", |
| hidden=1, |
| insert_after="signed_qr_code", |
| no_copy=1, |
| print_hide=1, |
| read_only=1, |
| ), |
| dict( |
| fieldname="einvoice_status", |
| label="E-Invoice Status", |
| fieldtype="Select", |
| insert_after="qrcode_image", |
| options="\nPending\nGenerated\nCancelled\nFailed", |
| default=None, |
| hidden=1, |
| no_copy=1, |
| print_hide=1, |
| read_only=1, |
| ), |
| dict( |
| fieldname="failure_description", |
| label="E-Invoice Failure Description", |
| fieldtype="Code", |
| options="JSON", |
| hidden=1, |
| insert_after="einvoice_status", |
| no_copy=1, |
| print_hide=1, |
| read_only=1, |
| ), |
| ] |
| |
| 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="Data", |
| insert_after="gst_state", |
| read_only=1, |
| ), |
| ], |
| "Purchase Invoice": purchase_invoice_gst_category |
| + invoice_gst_fields |
| + purchase_invoice_itc_fields |
| + purchase_invoice_gst_fields, |
| "Purchase Order": purchase_invoice_gst_fields, |
| "Purchase Receipt": purchase_invoice_gst_fields, |
| "Sales Invoice": sales_invoice_gst_category |
| + invoice_gst_fields |
| + sales_invoice_shipping_fields |
| + sales_invoice_gst_fields |
| + si_ewaybill_fields |
| + si_einvoice_fields, |
| "POS Invoice": sales_invoice_gst_fields, |
| "Delivery Note": sales_invoice_gst_fields |
| + ewaybill_fields |
| + sales_invoice_shipping_fields |
| + delivery_note_gst_category, |
| "Payment Entry": payment_entry_fields, |
| "Journal Entry": journal_entry_fields, |
| "Sales Order": sales_invoice_gst_fields, |
| "Tax Category": inter_state_gst_field, |
| "Item": [ |
| dict( |
| fieldname="gst_hsn_code", |
| label="HSN/SAC", |
| fieldtype="Link", |
| options="GST HSN Code", |
| insert_after="item_group", |
| ), |
| 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" |
| ), |
| ], |
| "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, taxable_value], |
| "POS Invoice Item": [hsn_sac_field, nil_rated_exempt, is_non_gst, taxable_value], |
| "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, taxable_value], |
| "Material Request Item": [hsn_sac_field, nil_rated_exempt, is_non_gst], |
| "Salary Component": [ |
| dict( |
| fieldname="component_type", |
| label="Component Type", |
| fieldtype="Select", |
| insert_after="description", |
| options="\nProvident Fund\nAdditional Provident Fund\nProvident Fund Loan\nProfessional Tax", |
| depends_on='eval:doc.type == "Deduction"', |
| ) |
| ], |
| "Employee": [ |
| dict( |
| fieldname="ifsc_code", |
| label="IFSC Code", |
| fieldtype="Data", |
| insert_after="bank_ac_no", |
| print_hide=1, |
| depends_on='eval:doc.salary_mode == "Bank"', |
| ), |
| dict( |
| fieldname="pan_number", |
| label="PAN Number", |
| fieldtype="Data", |
| insert_after="payroll_cost_center", |
| print_hide=1, |
| ), |
| dict( |
| fieldname="micr_code", |
| label="MICR Code", |
| fieldtype="Data", |
| insert_after="ifsc_code", |
| print_hide=1, |
| depends_on='eval:doc.salary_mode == "Bank"', |
| ), |
| dict( |
| fieldname="provident_fund_account", |
| label="Provident Fund Account", |
| fieldtype="Data", |
| insert_after="pan_number", |
| ), |
| ], |
| "Company": [ |
| dict( |
| fieldname="hra_section", |
| label="HRA Settings", |
| fieldtype="Section Break", |
| insert_after="asset_received_but_not_billed", |
| collapsible=1, |
| ), |
| dict( |
| fieldname="basic_component", |
| label="Basic Component", |
| fieldtype="Link", |
| options="Salary Component", |
| insert_after="hra_section", |
| ), |
| dict( |
| fieldname="hra_component", |
| label="HRA Component", |
| fieldtype="Link", |
| options="Salary Component", |
| insert_after="basic_component", |
| ), |
| dict(fieldname="hra_column_break", fieldtype="Column Break", insert_after="hra_component"), |
| dict( |
| fieldname="arrear_component", |
| label="Arrear Component", |
| fieldtype="Link", |
| options="Salary Component", |
| insert_after="hra_column_break", |
| ), |
| ], |
| "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", |
| fieldtype="Currency", |
| insert_after="hra_section", |
| ), |
| dict( |
| fieldname="rented_in_metro_city", |
| label="Rented in Metro City", |
| 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", |
| ), |
| dict( |
| fieldname="hra_column_break", |
| fieldtype="Column Break", |
| insert_after="salary_structure_hra", |
| depends_on="monthly_house_rent", |
| ), |
| dict( |
| fieldname="annual_hra_exemption", |
| label="Annual HRA Exemption", |
| fieldtype="Currency", |
| insert_after="hra_column_break", |
| read_only=1, |
| depends_on="monthly_house_rent", |
| ), |
| dict( |
| fieldname="monthly_hra_exemption", |
| label="Monthly HRA Exemption", |
| fieldtype="Currency", |
| insert_after="annual_hra_exemption", |
| read_only=1, |
| depends_on="monthly_house_rent", |
| ), |
| ], |
| "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", |
| depends_on="house_rent_payment_amount", |
| ), |
| dict( |
| fieldname="rented_from_date", |
| label="Rented From Date", |
| fieldtype="Date", |
| insert_after="rented_in_metro_city", |
| depends_on="house_rent_payment_amount", |
| ), |
| dict( |
| fieldname="rented_to_date", |
| label="Rented To Date", |
| fieldtype="Date", |
| insert_after="rented_from_date", |
| depends_on="house_rent_payment_amount", |
| ), |
| dict( |
| fieldname="hra_column_break", |
| fieldtype="Column Break", |
| insert_after="rented_to_date", |
| depends_on="house_rent_payment_amount", |
| ), |
| dict( |
| fieldname="monthly_house_rent", |
| label="Monthly House Rent", |
| fieldtype="Currency", |
| insert_after="hra_column_break", |
| read_only=1, |
| depends_on="house_rent_payment_amount", |
| ), |
| dict( |
| fieldname="monthly_hra_exemption", |
| label="Monthly Eligible Amount", |
| fieldtype="Currency", |
| insert_after="monthly_house_rent", |
| read_only=1, |
| depends_on="house_rent_payment_amount", |
| ), |
| dict( |
| fieldname="total_eligible_hra_exemption", |
| label="Total Eligible HRA Exemption", |
| fieldtype="Currency", |
| insert_after="monthly_hra_exemption", |
| read_only=1, |
| depends_on="house_rent_payment_amount", |
| ), |
| ], |
| "Supplier": [ |
| {"fieldname": "pan", "label": "PAN", "fieldtype": "Data", "insert_after": "supplier_type"}, |
| { |
| "fieldname": "gst_transporter_id", |
| "label": "GST Transporter ID", |
| "fieldtype": "Data", |
| "insert_after": "pan", |
| "depends_on": "eval:doc.is_transporter", |
| }, |
| { |
| "fieldname": "gst_category", |
| "label": "GST Category", |
| "fieldtype": "Select", |
| "insert_after": "gst_transporter_id", |
| "options": "Registered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nUIN Holders", |
| "default": "Unregistered", |
| }, |
| { |
| "fieldname": "export_type", |
| "label": "Export Type", |
| "fieldtype": "Select", |
| "insert_after": "gst_category", |
| "depends_on": 'eval:in_list(["SEZ", "Overseas"], doc.gst_category)', |
| "options": "\nWith Payment of Tax\nWithout Payment of Tax", |
| "mandatory_depends_on": 'eval:in_list(["SEZ", "Overseas"], doc.gst_category)', |
| }, |
| ], |
| "Customer": [ |
| {"fieldname": "pan", "label": "PAN", "fieldtype": "Data", "insert_after": "customer_type"}, |
| { |
| "fieldname": "gst_category", |
| "label": "GST Category", |
| "fieldtype": "Select", |
| "insert_after": "pan", |
| "options": "Registered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nConsumer\nDeemed Export\nUIN Holders", |
| "default": "Unregistered", |
| }, |
| { |
| "fieldname": "export_type", |
| "label": "Export Type", |
| "fieldtype": "Select", |
| "insert_after": "gst_category", |
| "depends_on": 'eval:in_list(["SEZ", "Overseas", "Deemed Export"], doc.gst_category)', |
| "options": "\nWith Payment of Tax\nWithout Payment of Tax", |
| "mandatory_depends_on": 'eval:in_list(["SEZ", "Overseas", "Deemed Export"], doc.gst_category)', |
| }, |
| ], |
| "Finance Book": [ |
| { |
| "fieldname": "for_income_tax", |
| "label": "For Income Tax", |
| "fieldtype": "Check", |
| "insert_after": "finance_book_name", |
| "description": "If the asset is put to use for less than 180 days, the first Depreciation Rate will be reduced by 50%.", |
| } |
| ], |
| } |
| |
| return custom_fields |
| |
| |
| def make_fixtures(company=None): |
| docs = [] |
| company = company or frappe.db.get_value("Global Defaults", None, "default_company") |
| |
| set_salary_components(docs) |
| set_tds_account(docs, company) |
| |
| for d in docs: |
| try: |
| doc = frappe.get_doc(d) |
| doc.flags.ignore_permissions = True |
| doc.insert() |
| except frappe.NameError: |
| frappe.clear_messages() |
| except frappe.DuplicateEntryError: |
| frappe.clear_messages() |
| |
| # create records for Tax Withholding Category |
| set_tax_withholding_category(company) |
| |
| |
| def update_regional_tax_settings(country, company): |
| # Will only add default GST accounts if present |
| input_account_names = ["Input Tax CGST", "Input Tax SGST", "Input Tax IGST"] |
| output_account_names = ["Output Tax CGST", "Output Tax SGST", "Output Tax IGST"] |
| rcm_accounts = ["Input Tax CGST RCM", "Input Tax SGST RCM", "Input Tax IGST RCM"] |
| gst_settings = frappe.get_single("GST Settings") |
| existing_account_list = [] |
| |
| for account in gst_settings.get("gst_accounts"): |
| for key in ["cgst_account", "sgst_account", "igst_account"]: |
| existing_account_list.append(account.get(key)) |
| |
| gst_accounts = frappe._dict( |
| frappe.get_all( |
| "Account", |
| { |
| "company": company, |
| "account_name": ("in", input_account_names + output_account_names + rcm_accounts), |
| }, |
| ["account_name", "name"], |
| as_list=1, |
| ) |
| ) |
| |
| add_accounts_in_gst_settings( |
| company, input_account_names, gst_accounts, existing_account_list, gst_settings |
| ) |
| add_accounts_in_gst_settings( |
| company, output_account_names, gst_accounts, existing_account_list, gst_settings |
| ) |
| add_accounts_in_gst_settings( |
| company, rcm_accounts, gst_accounts, existing_account_list, gst_settings, is_reverse_charge=1 |
| ) |
| |
| gst_settings.save() |
| |
| |
| def add_accounts_in_gst_settings( |
| company, account_names, gst_accounts, existing_account_list, gst_settings, is_reverse_charge=0 |
| ): |
| accounts_not_added = 1 |
| |
| for account in account_names: |
| # Default Account Added does not exists |
| if not gst_accounts.get(account): |
| accounts_not_added = 0 |
| |
| # Check if already added in GST Settings |
| if gst_accounts.get(account) in existing_account_list: |
| accounts_not_added = 0 |
| |
| if accounts_not_added: |
| gst_settings.append( |
| "gst_accounts", |
| { |
| "company": company, |
| "cgst_account": gst_accounts.get(account_names[0]), |
| "sgst_account": gst_accounts.get(account_names[1]), |
| "igst_account": gst_accounts.get(account_names[2]), |
| "is_reverse_charge_account": is_reverse_charge, |
| }, |
| ) |
| |
| |
| def set_salary_components(docs): |
| docs.extend( |
| [ |
| { |
| "doctype": "Salary Component", |
| "salary_component": "Professional Tax", |
| "description": "Professional Tax", |
| "type": "Deduction", |
| "exempted_from_income_tax": 1, |
| }, |
| { |
| "doctype": "Salary Component", |
| "salary_component": "Provident Fund", |
| "description": "Provident fund", |
| "type": "Deduction", |
| "is_tax_applicable": 1, |
| }, |
| { |
| "doctype": "Salary Component", |
| "salary_component": "House Rent Allowance", |
| "description": "House Rent Allowance", |
| "type": "Earning", |
| "is_tax_applicable": 1, |
| }, |
| { |
| "doctype": "Salary Component", |
| "salary_component": "Basic", |
| "description": "Basic", |
| "type": "Earning", |
| "is_tax_applicable": 1, |
| }, |
| { |
| "doctype": "Salary Component", |
| "salary_component": "Arrear", |
| "description": "Arrear", |
| "type": "Earning", |
| "is_tax_applicable": 1, |
| }, |
| { |
| "doctype": "Salary Component", |
| "salary_component": "Leave Encashment", |
| "description": "Leave Encashment", |
| "type": "Earning", |
| "is_tax_applicable": 1, |
| }, |
| ] |
| ) |
| |
| |
| def set_tax_withholding_category(company): |
| accounts = [] |
| fiscal_year_details = None |
| abbr = frappe.get_value("Company", company, "abbr") |
| tds_account = frappe.get_value("Account", "TDS Payable - {0}".format(abbr), "name") |
| |
| if company and tds_account: |
| accounts = [dict(company=company, account=tds_account)] |
| |
| try: |
| fiscal_year_details = get_fiscal_year(today(), verbose=0) |
| except FiscalYearError: |
| pass |
| |
| docs = get_tds_details(accounts, fiscal_year_details) |
| |
| for d in docs: |
| if not frappe.db.exists("Tax Withholding Category", d.get("name")): |
| doc = frappe.get_doc(d) |
| doc.flags.ignore_validate = True |
| doc.flags.ignore_permissions = True |
| doc.flags.ignore_mandatory = True |
| doc.insert() |
| else: |
| doc = frappe.get_doc("Tax Withholding Category", d.get("name"), for_update=True) |
| |
| if accounts: |
| doc.append("accounts", accounts[0]) |
| |
| if fiscal_year_details: |
| # 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("from_date") <= fiscal_year_details[1] and k.get("to_date") >= fiscal_year_details[2] |
| ] |
| if not fy_exist: |
| doc.append("rates", d.get("rates")[0]) |
| |
| doc.flags.ignore_permissions = True |
| doc.flags.ignore_validate = True |
| doc.flags.ignore_mandatory = True |
| doc.flags.ignore_links = True |
| doc.save() |
| |
| |
| def set_tds_account(docs, company): |
| 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, |
| } |
| ] |
| ) |
| |
| |
| def get_tds_details(accounts, fiscal_year_details): |
| # 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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "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=[ |
| { |
| "from_date": fiscal_year_details[1], |
| "to_date": fiscal_year_details[2], |
| "tax_withholding_rate": 20, |
| "single_threshold": 2500, |
| "cumulative_threshold": 0, |
| } |
| ], |
| ), |
| ] |
| |
| |
| def create_gratuity_rule(): |
| # Standard Indain Gratuity Rule |
| if not frappe.db.exists("Gratuity Rule", "Indian Standard Gratuity Rule"): |
| rule = frappe.new_doc("Gratuity Rule") |
| rule.name = "Indian Standard Gratuity Rule" |
| rule.calculate_gratuity_amount_based_on = "Current Slab" |
| rule.work_experience_calculation_method = "Round Off Work Experience" |
| rule.minimum_year_for_gratuity = 5 |
| |
| fraction = 15 / 26 |
| rule.append( |
| "gratuity_rule_slabs", |
| {"from_year": 0, "to_year": 0, "fraction_of_applicable_earnings": fraction}, |
| ) |
| |
| rule.flags.ignore_mandatory = True |
| rule.save() |
| |
| |
| def update_accounts_settings_for_taxes(): |
| if frappe.db.count("Company") == 1: |
| frappe.db.set_value("Accounts Settings", None, "add_taxes_from_item_tax_template", 0) |