Overriding GST Validations at Sales Order

Can someone suggest me a workaround for this scenario?

We have 3 warehouses - Kerala, Bangalore and Chennai.
At the point of creating a sales order, our sales team have no clue about where this product is going to be invoiced from. And customer could be either of these states. It may be invoiced and shipped from a single warehouse or from multiple warehouses.

At the time of creating SO, it is necessary to select either Interstate or Intrastate as sales tax template. Also, Company GSTIN, ie. Company Address is also mandatory. This becomes little complicated. Also while pushing the SO via API this creates a problem.

So how can we create the Sales Order by simply calculating only the taxis and without doing any other validations? All other validations and corrections will be done at the time of invoicing.

You can create the SO with a default values and then correct it at the time of invoicing?


Since my issue was while pushing the SO via API, it would conflict between iterstate and intrastate, so I rather did this

def assign_so_defaults(doc, method):

    from erpnext import get_default_company
    from frappe.contacts.doctype.address.address import get_company_address

    party_state = frappe.db.get_value("Address", doc.customer_address, "gst_state") or None
    company_state = frappe.db.get_value("Address", doc.company_address, "gst_state") or None

    message_parts = []

    if party_state:

        if not doc.company_address:
            company_address = frappe.db.get_value("Address", {
                "is_your_company_address": 1,
                "gst_state": party_state
            }, "name") or get_company_address(get_default_company()).company_address

            doc.company_address = company_address
            message_parts.append(f"• Company Address: {doc.company_address}")

            company_state = frappe.db.get_value("Address", company_address, "gst_state")

        if not doc.taxes_and_charges:
            if company_state == party_state:
                doc.taxes_and_charges = frappe.db.get_single_value('Zarnik Settings', 'default_intrastate_sales_taxes_and_charges_template')
                doc.taxes_and_charges = frappe.db.get_single_value('Zarnik Settings', 'default_interstate_sales_taxes_and_charges_template')

            message_parts.append(f"• Taxes and Charges: {doc.taxes_and_charges}")

        if doc.taxes_and_charges and not doc.taxes:

            template = frappe.db.get_all("Sales Taxes and Charges", {
                "parent": doc.taxes_and_charges
            }, ["charge_type", "account_head", "description","included_in_print_rate", "rate", "cost_center", "account_currency"])

            for row in template:
                doc.append("taxes", {
                    "charge_type": row.charge_type,
                    "account_head": row.account_head,
                    "description": row.description,

        if not doc.set_warehouse:
            warehouse = frappe.db.get_value("Warehouse", {
                "company": get_default_company(),
                "account": "Stock In Hand - ZHSPL",
                "state": party_state
            }, "name") or frappe.db.get_single_value('Zarnik Settings', 'default_so_warehouse')

            doc.set_warehouse = warehouse
            message_parts.append(f"• Warehouse: {doc.set_warehouse}")

        if message_parts:
            message = "The following values were automatically assigned:<br>" + "<br>".join(message_parts)
            # frappe.msgprint(message)


doc.run_method("set_missing_values") might’ve taken care of it.