ERPNEXT Integration with E-INVOINCING

Hello everyone,
I am trying to integrate ERPNEXT with E-Invoicing (EFRIS). My inquiry is: How can I fetch the sales invoice data? For example, the items(item_code,item_name) in the sales invoice document are a table. So I want to fetch these value fields from my JSON so that they can be posted to another system for e-invoicing.

This is my code

import base64
from datetime import datetime
import json
import frappe
from frappe.model.document import Document
import requests

items=frappe.get_value(‘Item’, ‘’, ‘item_name’)
itemcodes=frappe.get_value(‘Item’,‘’,‘item_code’)
qtys = frappe.get_value(‘Sales Invoice’,‘’,‘total_qty’)
unitOfMeasures=frappe.get_value(‘Item’,‘’,‘stock_uom’)
unitPrices=frappe.get_value(‘Item’,‘’,‘valuation_rate’)
totals=frappe.get_value(‘Sales Invoice’,‘’,‘base_grand_total’)
taxs=frappe.get_value(‘Sales Taxes and Charges’,‘’,‘tax_amount’)
netAmounts=frappe.get_value(‘Sales Invoice’,‘’,‘net_total’)
grossAmounts=frappe.get_value(‘Sales Invoice’,‘’,‘grand_total’)
goodsCategoryId=frappe.get_value(‘Item’,‘’,‘custom_goods_category’)

json_data = [
{
“sellerDetails”: {
“tin”: “1021525903”,
“ninBrn”: “”,
“legalName”: “”,
“businessName”: " ",
“address”: “473 KIGOWA ROAD KAMPALA NAKAWA DIVISION”,
“mobilePhone”: “”,
“linePhone”: “”,
“emailAddress”: “”,
“placeOfBusiness”: “”,
“referenceNo”: “210115545”,
“branchId”: “”,
“isCheckReferenceNo”: “0”
},
“basicInformation”: {
“invoiceNo”: “”,
“antifakeCode”: “”,
“deviceNo”: “TCSb146f44119674599”,
“issuedDate”: “”,
“operator”: “”,
“currency”: “UGX”,
“oriInvoiceId”: “1”,
“invoiceType”: “1”,
“invoiceKind”: “1”,
“dataSource”: “106”,
“invoiceIndustryCode”: “”,
“isBatch”: “0”
},
“buyerDetails”: {
“buyerTin”: “1040800897”,
“buyerNinBrn”: “”,
“buyerPassportNum”: “”,
“buyerLegalName”: “”,
“buyerBusinessName”: “”,
“buyerAddress”: “”,
“buyerEmail”: “”,
“buyerMobilePhone”: “0757001909”,
“buyerLinePhone”: “”,
“buyerPlaceOfBusi”: “”,
“buyerType”: “1”,
“buyerCitizenship”: “”,
“buyerSector”: “1”,
“buyerReferenceNo”: “”
},
“buyerExtend”: {
“propertyType”: “abc”,
“district”: “”,
“municipalityCounty”: “”,
“divisionSubcounty”: “”,
“town”: “”,
“cellVillage”: “”,
“effectiveRegistrationDate”: “”,
“meterStatus”: “”
},
“goodsDetails”: {
“item”: items,
“itemCode”: itemcodes,
“qty”: qtys,
“unitOfMeasure”: unitOfMeasures,
“unitPrice”: unitPrices,
“total”: totals,
“taxRate”: “0.18”,
“tax”: “”,
“discountTotal”: “”,
“discountTaxRate”: “”,
“orderNumber”: “”,
“discountFlag”: “2”,
“deemedFlag”: “2”,
“exciseFlag”: “2”,
“categoryId”: “”,
“categoryName”: “”,
“goodsCategoryId”: goodsCategoryId,
“goodsCategoryName”: “”,
“exciseRate”: “”,
“exciseRule”: “”,
“exciseTax”: “”,
“pack”: “”,
“stick”: “”,
“exciseUnit”: “”,
“exciseCurrency”: “”,
“exciseRateName”: “”,
“vatApplicableFlag”: “”
},
“taxDetails”: [
{
“taxCategoryCode”: “01”,
“netAmount”: netAmounts,
“taxRate”: “0.18”,
“taxAmount”: “”,
“grossAmount”: “”,
“exciseUnit”: “101”,
“exciseCurrency”: “”,
“taxRateName”: “”
}
],
“summary”: {
“netAmount”: netAmounts,
“taxAmount”: taxs,
“grossAmount”: grossAmounts,
“itemCount”: qtys,
“modeCode”: “1”,
“remarks”: “This is a test presentation.”,
“qrCode”: “”
},
“payWay”: [
{
“paymentMode”: “102”,
“paymentAmount”: “685”,
“orderNumber”: “a”
},
{
“paymentMode”: “102”,
“paymentAmount”: “685”,
“orderNumber”: “a”
}
],
“extend”: {
“reason”: “reason”,
“reasonCode”: “102”
},
“importServicesSeller”: {
“importBusinessName”: “”,
“importEmailAddress”: “”,
“importContactNumber”: “”,
“importAddress”: “”,
“importInvoiceDate”: “”,
“importAttachmentName”: “”,
“importAttachmentContent”: “”
},
“airlineGoodsDetails”: [
{
“item”: “”,
“itemCode”: “”,
“qty”: “”,
“unitOfMeasure”: “”,
“unitPrice”: “”,
“total”: “”,
“taxRate”: “0.18”,
“tax”: “”,
“discountTotal”: “”,
“discountTaxRate”: “”,
“orderNumber”: “”,
“discountFlag”: “”,
“deemedFlag”: “”,
“exciseFlag”: “”,
“categoryId”: “”,
“categoryName”: “”,
“goodsCategoryId”: “”,
“goodsCategoryName”: “”,
“exciseRate”: “”,
“exciseRule”: “”,
“exciseTax”: “”,
“pack”: “1”,
“stick”: “”,
“exciseUnit”: “”,
“exciseCurrency”: “”,
“exciseRateName”: “”
}
],
“edcDetails”: {
“tankNo”: “”,
“pumpNo”: “”,
“nozzleNo”: “”,
“controllerNo”: “”,
“acquisitionEquipmentNo”: “”,
“levelGaugeNo”: “”,
“mvrn”: “”
}
}
]

Convert JSON object to JSON-formatted string

json_string = json.dumps(json_data)

Encode the JSON string to Base64

encoded_json = base64.b64encode(json_string.encode(‘utf-8’)).decode(‘utf-8’)

def send(doc, event):
try:
# Get the current time and format it as a string
current_time = datetime.now().strftime(‘%Y-%m-%d %H:%M:%S’)

    # Your custom logic to prepare data for the API request
    data_to_post = {
        'data': {
            'content': encoded_json,
            'signature': '',
            'dataDescription': {
                'codeType': '0',
                'encryptCode': '1',
                'zipCode': '0'
            }
        },
        'globalInfo': {
            'appId': 'AP04',
            'version': '1.1.20191201',
            'dataExchangeId': '9230489223014123',
            'interfaceCode': 'T109',
            'requestCode': 'TP',
            'requestTime': current_time,
            'responseCode': 'TA',
            'userName': 'admin',
            'deviceMAC': 'B47720524158',
            'deviceNo': 'TCSb146f44119674599',
            'tin': '',
            'brn': '',
            'taxpayerID': '1',
            'longitude': '32.61665',
            'latitude': '0.36601',
            'agentType': '0',
            'extendField': {
                'responseDateFormat': 'dd/MM/yyyy',
                'responseTimeFormat': 'dd/MM/yyyy HH:mm:ss',
                'referenceNo': '24PL01000221',
                'operatorName': 'administrator'
            }
        },
        'returnStateInfo': {
            'returnCode': '',
            'returnMessage': ''  
        }
    }

    # Make a POST request to the external API
    api_url = 'http://192.168.0.9:9880/efristcs/ws/tcsapp/getInformation'  # Replace with your actual endpoint
    headers = {'Content-Type': 'application/json'}

    response = requests.post(api_url, json=data_to_post)
    response.raise_for_status()  # Raise an HTTPError for bad responses

    # Print the response status code and content
    print(f"Response Status Code: {response.status_code}")
    print(f"Response Content: {response.text}")

    # Handle the response status code
    if response.status_code == 200:
        frappe.msgprint("Successfully submitted to the external API")
    else:
        frappe.msgprint(f"Failed to submit to the external API. Status code: {response.status_code}")

except requests.exceptions.RequestException as e:
    frappe.msgprint(f"Error making API request: {e}")