class_docstr: A class for handling connections and interactions with the Frappe API.
  
  Attributes:
      client (FrappeClient): The `FrappeClient` object for interacting with the Frappe API.
      is_connected (bool): Whether or not the API client is connected to Frappe.
      domain (str): Frappe domain to send API requests to.
      access_token (str): OAuth token to use for authentication.
class_docstr_tok: ["A","class","for","handling","connections","and","interactions","with","the","Frappe","API",".","Attributes",":","client","(","FrappeClient",")",":","The","`","FrappeClient","`","object","for","interacting","with","the","Frappe","API",".","is_connected","(","bool",")",":","Whether","or","not","the","API","client","is","connected","to","Frappe",".","domain","(","str",")",":","Frappe","domain","to","send","API","requests","to",".","access_token","(","str",")",":","OAuth","token","to","use","for","authentication","."]
docstr: input is:
    {
      "due_date": "2023-05-31",
      "customer": "ksim",
      "items": [
        {
          "name": "T-shirt--",
          "description": "T-shirt",
          "quantity": 1
        }
      ]
    }
docstr_tok: ["input","is",":","{","``","due_date","''",":","``","2023-05-31","''",",","``","customer","''",":","``","ksim","''",",","``","items","''",":","[","{","``","name","''",":","``","T-shirt","--","''",",","``","description","''",":","``","T-shirt","''",",","``","quantity","''",":","1","}","]","}"]
code: def register_sales_invoice(self, data):
      """
      input is:
        {
          "due_date": "2023-05-31",
          "customer": "ksim",
          "items": [
            {
              "name": "T-shirt--",
              "description": "T-shirt",
              "quantity": 1
            }
          ]
        }
      """
      invoice = json.loads(data)
      date = dt.datetime.strptime(invoice["due_date"], "%Y-%m-%d")
      if date <= dt.datetime.today():
          return "Error: due_date have to be in the future"
  
      for item in invoice["items"]:
          # rename column
          item["qty"] = item["quantity"]
          del item["quantity"]
  
          # add required fields
          item["uom"] = "Nos"
          item["conversion_factor"] = 1
  
          income_account = self.connection_data.get(
              "income_account", "Sales Income - C8"
          )
          item["income_account"] = income_account
  
      try:
          self.connect()
          self.client.post_document("Sales Invoice", invoice)
      except Exception as e:
          return f"Error: {e}"
      return f"Success"
  
imports: import json
  import pandas
  import datetime
  from typing import Dict
  from mindsdb.integrations.handlers.frappe_handler.frappe_tables import FrappeDocumentsTable
  from mindsdb.integrations.handlers.frappe_handler.frappe_client import FrappeClient
  from mindsdb.integrations.libs.api_handler import APIHandler
  from mindsdb.integrations.libs.response import HandlerStatusResponse, HandlerResponse
  from mindsdb.utilities import log
  from mindsdb_sql import parse_sql
label_desc: Use image node_id 3 for calling the FrappeHandler obj's underlying member method code with example usage: obj.register_sales_invoice(data) and returns: str, str, str, e