eTax API for EVCS

API Example for EVCS

 · 3 min read

1. Case sign Tax Invoice

Sample JSON body

{
    "form_type": "frappe",
    "form_name": "EM ETax Form",
    "pdf_content": "",
    "doc_data": {
        "source_system": "https://xxx.energyabsolute.co.th",
        "send_mail": "N",
        "currency_code": "THB",
        "document_type_code": "388",
        "document_id": "IV_AAB_23110011",
        "document_issue_dtm": "2023-11-04T00:00:00",
        "create_purpose_code": "",
        "create_purpose": "",
        "ref_document_id": "",
        "ref_document_issue_dtm": "",
        "ref_document_type_code": "",
        "buyer_ref_document": "?????",
        "seller_branch_id": "00000",        <-------------------- YOUR COMPANY
        "seller_tax_id": "0105554048641",   <-------------------- YOUR BRANCH
        "buyer_name": "บริษัท เน็กซ์ จำกัด (มหาชน)",
        "buyer_tax_id": "010???????788",
        "buyer_branch_id": "00001",
        "buyer_email": "fin_group@nexpoint.co.th",
        "buyer_zip": "10540",
        "buyer_building_name": "",
        "buyer_building_no": "",
        "buyer_address_line1": "9/11 หมู่ 4 ต.บางโฉลง",
        "buyer_address_line2": "อ.บางพลี",
        "buyer_address_line3": "",
        "buyer_address_line4": "",
        "buyer_address_line5": "",
        "buyer_city_name": "จ.สมุทรปราการ",
        "buyer_country_code": "TH",
        "line_item_information": [
            {
                "product_code": "03-C420",
                "product_name": "Electric tractor Head",
                "product_price": 100.0,  <-- ราคาต่อหน่วยก่อนภาษี
                "product_quantity": 10.0,
                "line_tax_type_code": "VAT",
                "line_tax_rate": 7.0,
                "line_base_amount": 1000.0,  <-- ราคารวมก่อนภาษี
                "line_tax_amount": 70.0,
                "line_total_amount": 1070.0  <-- ราคารวมหลังภาษี
            }
        ],
        "original_amount_untaxed": 0,
        "final_amount_untaxed": 0,
        "adjust_amount_untaxed": 0
    }
}

Sample API Call

  • auth_token = <token for frappe authen>
  • server_url = <frappe server url>

Note: to pass PDF from EVCS

  • form_type = "evcs"
  • form_name = <name of your form>
  • pdf_contenct = <string of pdf content>

To use PDF from frappe

  • form_type = "frappe"
  • form_name = ""
  • pdf_content = ""

Sample in Postman

Sample in Python

    def _send_to_frappe(self, doc_data, form_type, form_name, pdf_content):
        auth_token, server_url = self._get_connection()
        try:
            # -- HERE is the API call --
            res = requests.post(
                # https://<frappe server>/api/method/etax_inet.api.etax.sign_etax_document
                url="%s/api/method/%s" % (server_url, "etax_inet.api.etax.sign_etax_document"),
                headers={"Authorization": "token %s" % auth_token},
                data={
                    "doc_data": json.dumps(doc_data),   # JSON input
                    "form_type": form_type,
                    "form_name": form_name,
                    "pdf_content": pdf_content,
                },
                timeout=20,
            ).json()
            # -- END HERE - the rest are to update data back to the singing document
            response = res.get("message")
            if not response:  # Can't create record on Frappe
                self.etax_status = "error"
                self.etax_error_message = res.get("exception", res.get("_server_messages"))
                return
            # Update status
            self.etax_status = response.get("status").lower()
            self.etax_transaction_code = response.get("transaction_code")
            self.etax_error_code = response.get("error_code")
            self.etax_error_message = response.get("error_message")
            # Get signed document back
            if self.etax_status == "success":
                pdf_url, xml_url = [response.get("pdf_url"), response.get("xml_url")]
                if pdf_url:
                    self.env["ir.attachment"].create(
                        {
                            "name": "%s_signed.pdf" % self.name,
                            "datas": base64.b64encode(requests.get(pdf_url).content),
                            "type": "binary",
                            "res_model": "account.move",
                            "res_id": self.id,
                        }
                    )
                if xml_url:
                    self.env["ir.attachment"].create(
                        {
                            "name": "%s_signed.xml" % self.name,
                            "datas": base64.b64encode(requests.get(xml_url).content),
                            "type": "binary",
                            "res_model": "account.move",
                            "res_id": self.id,
                        }
                    )
        except Exception as e:
            self.etax_status = "error"
            self.etax_error_message = str(e)

2. Case Check Status (document in process)

GET API

  • auth_token = <token for frappe authen>
  • server_url = <frappe server url>
  • transaction_code = <transaction code received from previous step>

URL = **server_url**/api/resource/INET ETax Document?filters=[["transaction_code","="," **transaction_code**"]]&fields=["status","transaction_code","error_code","error_message","pdf_url","xml_url"]

Sample in Python

    def update_processing_document(self):
        self.ensure_one()
        if self.etax_status != "processing":
            return
        auth_token, server_url = self._get_connection()
        url=(
            '%s/api/resource/?filters=[["transaction_code","=","%s"]]'
            '&fields=["status","transaction_code","error_code","error_message","pdf_url","xml_url"]'
            % (server_url, "INET ETax Document", self.etax_transaction_code)
        )
        res = requests.get(
            url,
            headers={"Authorization": "token %s" % auth_token},
            timeout=20,
        ).json()
        if not res.get("data"):
            return
        response = res.get("data")[0]
        # Update status
        self.etax_status = response.get("status").lower()
        self.etax_error_code = response.get("error_code")
        self.etax_error_message = response.get("error_message")
        if self.etax_status == "success":
            pdf_url, xml_url = [response.get("pdf_url"), response.get("xml_url")]
            if pdf_url:
                self.env["ir.attachment"].create(
                    {
                        "name": "%s_signed.pdf" % self.name,
                        "datas": base64.b64encode(requests.get(pdf_url).content),
                        "type": "binary",
                        "res_model": self._name,
                        "res_id": self.id,
                    }
                )
            if xml_url:
                self.env["ir.attachment"].create(
                    {
                        "name": "%s_signed.xml" % self.name,
                        "datas": base64.b64encode(requests.get(xml_url).content),
                        "type": "binary",
                        "res_model": self._name,
                        "res_id": self.id,
                    }
                )

3. Case Replacement (ใบแทน)

Replacement is just a normal document with reference to the old document and the purpose

Coding Steps:

  1. Cancel existing document, i.e., IW20201203210836
  2. Do the signing again with revised name i.e., IW20201203210836-R1
  3. JSON is exactly the same with additonal informaiton as following,
    "document_id": "IW20201203210836-R1",
    "create_purpose_code: "TIVC01",              <---- TIVC01 (ชื่อผิด), TIVC02 (ที่อยู่ผิด), TIVC99 (อื่นๆ โปรดระบุ)
    "create_purpose": "ชื่อผิด",                   <---- เหตุผล
    "ref_document_id": IW20201203210836",
    "ref_document_issue_dtm": "2023-11-04T00:00:00",
    "ref_document_type_code": <same as document_type_code, i.e., T03>

No comments yet.

Add a comment
Ctrl+Enter to add comment