This is a python package to aid in fiscalisation of invoices with the Uganda Revenue Authority (URA) using the EFRIS API.
Project description
EFRIS Python Package (EFRISER)
This Python package provides a simple interface to interact with the EFRIS (Electronic Fiscal Receipt Information System) API provided by the Uganda Revenue Authority (URA) for invoicing.
Features
- Create EFRIS invoices
- Retrieve the status of credit notes
- Easily integrate with your existing application
- Query taxpayer by TIN
- Query document details
- Query invoice details by FDN (Fiscal Document Number)
- Get the system dictionary for API-related details
- Approve credit notes
- Cancel credit notes
- Get the Z daily report from the fiscal device
- Cancel credit note applications
- Acquire exchange rates for transactional purposes
Why I Created This Package
While working with the Uganda Revenue Authority (URA) API, I encountered numerous obstacles. My experiences led me to a deep understanding of the API's intricacies. This package is the result of my efforts to alleviate the "pain" for others—ensuring that you don't have to face the same challenges. Designed to be user-friendly, this guide will assist you, irrespective of your programming language, through the entire process from setting up the offline enabler to generating your first e-invoice. So grab a cup of chai and let's get started.
Setting Up the Offline Enabler
-
Download the Enabler: Navigate to the URA eFris test site and download the offline enabler. Follow the installation instructions provided on the website.
-
Installation and Configuration: After installation, you will receive an IP address from the enabler, for example,
199.82.32.128. Append a port, such as9880, resulting inhttp://199.82.32.128:9880— this will serve as your base URL. To access the GUI of your enabler, visithttp://199.82.32.128:9880/efristcs.Ensure you follow the detailed installation procedures in the guide to initialize your enabler and configure both a public and private key.
Consuming the API
Once everything is set up, you're ready to dive into using the API to produce your e-invoices and more. The detailed steps provided in this guide will ensure a smooth experience as you integrate with the URA's systems.
__init__(self, ip, device_number, tin, seller_name)
Initialize the EFRISInvoicing class.
Args:
ip(str): The IP address of the EFRIS Enabler server.device_number(str): The device number.tin(str): The Tax Identification Number.seller_name(str): The name of the seller.
Function: query_tax_payer_by_tin(self, tin)
This function is part of a class (not shown in the snippet) and is used to query a tax payer by their Tax Identification Number (TIN).
Parameters:
tin(str): The Tax Identification Number of the tax payer. This is the unique identifier for the tax payer.
Returns:
dict: A dictionary containing the formatted tax payer output.
Code Explanation:
The function takes a TIN as input and creates a message dictionary with the TIN and an empty 'ninBrn' field. The 'ic' variable is set to 'T119', which might be a code indicating the type of query being performed.
The function then calls self.efris_post(ic, message), which is likely a method in the same class that sends a POST request to a server (presumably the EFRIS server) with the 'ic' and 'message' as arguments.
The response from this POST request is then passed to the format_taxpayer_output() function (not shown in the snippet), which presumably formats the response into a more usable form. The result of this formatting function is what gets returned by query_tax_payer_by_tin().
Function: query_document(self, fdn, type)
This method queries a document by its Fiscal Document Number (FDN) and type.
Parameters:
fdn(str): The Fiscal Document Number of the document being queried.type(int): The type of the document (1 for Invoice, 2 for Receipt).
Returns:
dict: A dictionary containing the formatted output of the invoice query.
Code Explanation:
The query_document method initializes the ic variable with the value 'T106', which likely denotes the type of query being performed.
Next, it prepares the message by calling query_invoice_json(fdn, str(type)). This function likely formats the fdn and type into a JSON message suitable for querying the invoice.
The method then sends a POST request to an external server (possibly the EFRIS server) using self.efris_post(ic, message). This method handles the POST request and retrieves the response.
The response from the POST request is then passed to the format_invoice_query_output function (not shown in this snippet), which likely processes the response and formats it into a more usable dictionary.
Finally, the formatted output of the invoice query is returned as a dictionary by the query_document method.
Function: query_invoice_details(self, fdn)
This method queries the details of an invoice using its Fiscal Document Number (FDN).
Parameters:
fdn(str): The Fiscal Document Number (FDN) of the invoice.
Returns:
dict: A dictionary containing the cleaned invoice data.
Code Explanation:
The query_invoice_details method initializes the ic variable with the value 'T108', which likely indicates the type of query being performed for invoice details.
Next, it prepares the message by calling invoice_details_json(fdn). This function likely formats the fdn into a JSON message suitable for querying the invoice details.
The method then sends a POST request to an external server (possibly the EFRIS server) using self.efris_post(ic, message). This method handles the POST request and retrieves the response.
The response from the POST request is then passed to the clean_invoice_data_json function (not shown in this snippet), which likely processes the response and cleans the invoice data, preparing it for use.
Finally, the cleaned invoice data is returned as a dictionary by the query_invoice_details method.
Function: system_dictionary(self)
This method queries the system dictionary from the EFRIS server.
Returns:
dict: The response from the EFRIS server, representing the system dictionary.
Code Explanation:
The system_dictionary method initializes the ic variable with the value 'T115', which likely indicates the type of query being performed to retrieve the system dictionary.
It prepares an empty message list, as the system dictionary query may not require additional parameters.
The method then sends a POST request to an external server (presumably the EFRIS server) using self.efris_post(ic, message). This method handles the POST request and retrieves the response.
The response from the POST request, which is expected to contain the system dictionary information, is returned directly as a dictionary by the system_dictionary method.
Function: credit_notes_query(self)
This method queries credit notes from the EFRIS server.
Returns:
dict: The processed credit note output.
Code Explanation:
The credit_notes_query method initializes the ic variable with the value 'T111', which likely indicates the type of query being performed to retrieve credit notes.
It prepares the message by calling credit_note_json(). This function likely prepares a JSON message suitable for querying credit notes.
The method then sends a POST request to an external server (presumably the EFRIS server) using self.efris_post(ic, message). This method handles the POST request and retrieves the response.
The response from the POST request is then passed to the process_creditnote_output function (not shown in this snippet), which likely processes the response and formats the credit note data for further use.
Finally, the processed credit note output is returned as a dictionary by the credit_notes_query method.
Function: credit_note_details(self, id)
This method queries the details of a specific credit note from the EFRIS server.
Parameters:
id(str): The ID of the credit note to query.
Returns:
dict: The response from the EFRIS server containing the details of the credit note.
Code Explanation:
The credit_note_details method initializes the ic variable with the value 'T112', which likely indicates the type of query being performed to retrieve credit note details.
It prepares the message as a dictionary containing the id parameter provided as an argument to the method.
The method then sends a POST request to an external server (presumably the EFRIS server) using self.efris_post(ic, message). This method handles the POST request and includes the ic and message as arguments.
The response from the POST request, which contains the details of the queried credit note, is returned as a dictionary by the credit_note_details method.
Function: approve_credit_note(self, reference_no, status, id, remarks)
This method is used to approve or reject a credit note by sending a request to the EFRIS server.
Parameters:
reference_no(str): The reference number of the credit note.status(int): The status of the credit note, where:101: Indicates approval ("Approved")103: Indicates rejection ("Rejected")
id(str): The ID of the credit note.remarks(str): Remarks or comments for the credit note.
Returns:
dict: The response from the EFRIS server confirming the action.
Raises:
ValueError: If thestatusparameter is invalid and does not match the allowed values.
Code Explanation:
The approve_credit_note method initializes the ic variable with the value 'T113', which likely indicates the type of action being performed to approve or reject a credit note.
Input validation is performed for the status parameter using a dictionary valid_status that maps valid status codes (101 for approval and 103 for rejection) to their corresponding descriptions ("Approved" and "Rejected").
If the provided status value does not match any of the valid codes in valid_status, a ValueError is raised with a descriptive error message indicating the valid options.
The message is prepared by calling the approve_credit_note function with the provided parameters (reference_no, status, id, remarks). This function likely constructs a JSON message representing the request to approve or reject the credit note.
Finally, a POST request is sent to the EFRIS server using self.efris_post(ic, message), where ic is the action code and message is the request data. The response from the server, confirming the approval or rejection action, is returned as a dictionary by the approve_credit_note method.
Function: cancel_credit_note(self, inv_fdn, cn_fdn, reason)
This method is used to cancel a credit note by sending a request to the EFRIS server.
Parameters:
inv_fdn(str): The FDN (Fiscal Document Number) of the original invoice associated with the credit note.cn_fdn(str): The FDN of the credit note to be canceled.reason(str): The reason for canceling the credit note.
Returns:
dict: The response from the EFRIS server confirming the cancellation.
Code Explanation:
The cancel_credit_note method initializes the ic variable with the value 'T112', which likely indicates the type of action being performed to cancel a credit note.
The message is prepared by calling the cancel_credit_note function with the provided parameters (inv_fdn, cn_fdn, reason). This function likely constructs a JSON message representing the request to cancel the credit note, including the necessary document numbers (inv_fdn, cn_fdn) and cancellation reason.
Finally, a POST request is sent to the EFRIS server using self.efris_post(ic, message), where ic is the action code and message is the request data. The response from the server, confirming the cancellation of the credit note, is returned as a dictionary by the cancel_credit_note method.
Function: z_report(self)
This method is used to generate a Z report by sending a request to the EFRIS server.
Returns:
dict: The response from the EFRIS server containing the Z report data.
Code Explanation:
The z_report method initializes the ic variable with the value 'T116', which likely represents the action code for generating a Z report.
The message variable is initialized as an empty dictionary ({}), indicating that no specific parameters or data are required to generate the Z report.
A POST request is then sent to the EFRIS server using self.efris_post(ic, message), where ic is the action code and message is the request data (in this case, empty). The response from the server containing the Z report data is returned as a dictionary by the z_report method.
Function: cancel_credit_note_application(self, business_key, reference_no)
This method is used to cancel a credit note application by sending a request to the EFRIS server.
Args:
business_key (str): The business key associated with the credit note application.reference_no (str): The reference number of the credit note application.
Returns:
dict: The response from the EFRIS server confirming the cancellation.
Code Explanation:
The cancel_credit_note_application method initializes the ic variable with the value 'T120', representing the action code for canceling a credit note application.
The message variable is initialized as a dictionary containing the businessKey and referenceNo fields, which are provided as arguments to the method.
A POST request is then sent to the EFRIS server using self.efris_post(ic, message), where ic is the action code and message contains the business key and reference number of the credit note application to be canceled.
The response from the server confirming the cancellation of the credit note application is returned as a dictionary by the cancel_credit_note_application method.
Function: acquiring_exchange_rate(self, currency)
This method is used to acquire the exchange rate for a specific currency from the EFRIS server.
Args:
currency (str): The currency code for which the exchange rate is requested.
Returns:
dict: A dictionary containing the cleaned currency output, including the exchange rate.
Code Explanation:
The acquiring_exchange_rate method begins by initializing the ic variable with the value 'T121', which is the action code used to request the exchange rate for a currency.
The message variable is then created as a dictionary containing the currency code provided as an argument and the issueDate, presumably representing the date of the exchange rate request.
The method sends a POST request to the EFRIS server using self.efris_post(ic, message), passing the action code (ic) and message (message) as parameters.
The response from the server is then passed to the currency_output_cleaner function, which processes and cleans the currency output data.
Finally, the cleaned currency output, including the exchange rate, is returned as a dictionary by the acquiring_exchange_rate method.
Function: query_tax_payer_by_tin(self, tin)
This method is used to query a tax payer by their Tax Identification Number (TIN) from the EFRIS server.
Args:
tin (str): The Tax Identification Number of the tax payer. This is the unique identifier for the tax payer.
Returns:
dict: A dictionary containing the formatted tax payer output.
Code Explanation:
The query_tax_payer_by_tin method initializes the ic variable with the value 'T119', which represents the action code for querying a tax payer by TIN.
The message variable is created as a dictionary with keys "tin" set to the provided tin argument and `"ninBrn
Function: query_tax_payer_by_tin(self, tin)
This method is used to query a tax payer by their Tax Identification Number (TIN) from the EFRIS server.
Args:
tin (str): The Tax Identification Number of the tax payer. This is the unique identifier for the tax payer.
Returns:
dict: A dictionary containing the formatted tax payer output.
Code Explanation:
The query_tax_payer_by_tin method initializes the ic variable with the value 'T119', which represents the action code for querying a tax payer by TIN.
The message variable is created as a dictionary with keys "tin" set to the provided tin argument and "ninBrn" set to an empty string (""), which might represent another identifier or parameter.
The method then sends a POST request to the EFRIS server using self.efris_post(ic, message), passing the action code (ic) and message (message) as parameters.
The response from the server is passed to the format_taxpayer_output function, which formats and processes the tax payer data received from the server.
Finally, the formatted tax payer output is returned as a dictionary by the query_tax_payer_by_tin method.
Function: upload_products(self, invoice_data)
This method is used to create EFRIS invoices using the provided invoice data.
Args
invoice_data (list): A list of dictionaries representing invoices. Each dictionary should contain the following keys:"havePieceUnit": Indicator for piece unit availability."goodsName": Name of the goods."goodsCode": Code assigned to the goods should be unique."measureUnit": Measurement unit for the goods as per URA documentation."unitPrice": Price per unit of the goods."currency": Currency code for the price as per URA."commodityCategoryId": Category ID for the goods as per URA goods ID."haveExciseTax": Indicator for excise tax availability."description": Description of the goods."stockPrewarning": Stock prewarning threshold.
Returns
listorFalse: A list of return messages from the EFRIS service if successful, orFalseif any invalid invoices are encountered.
Code Explanation
The upload_products method validates each invoice in the provided invoice_data list to ensure all required keys are present. If any invalid invoices are found, they are logged, and the function returns False.
The method then makes a POST request to the EFRIS server using the action code 'T130' (assigned to the variable ic) and the invoice_data list as the message.
If the response from the server (return_msg) is empty ([]), the method returns an empty list.
If the response contains data, the content is decoded using base64 and parsed as JSON (decoded_data). If decoded_data is empty, an empty list is returned.
Otherwise, the method extracts the returnMessage from each dictionary in decoded_data to compile a list of return messages (return_messages), which is returned as the final result.
Example
invoice_data = [
{
"havePieceUnit": "102",
"goodsName": "Service ABC",
"goodsCode": "ABC123",
"measureUnit": "115",
"unitPrice": "10.00",
"currency": "101",
"commodityCategoryId": "84111601",
"haveExciseTax": "102",
"description": "This is Service A",
"stockPrewarning": "0"
},
{
"havePieceUnit": "102",
"goodsName": "Product",
"goodsCode": "ABC123",
"measureUnit": "115",
"unitPrice": "10.00",
"currency": "101",
"commodityCategoryId": "84111601",
"haveExciseTax": "102",
"description": "This is Product A",
"stockPrewarning": "50"
}
]
invoicing = EFRISInvoicing('193.53.52.28:9880', 'TCS1613912799535','1003332553', 'Test Company')
tax_payer = invoicing.upload_products(invoice_data)
If you found this package helpful, consider buying me a coffee! 😊
Mobile money number: +256705860416
Whatsapp: +256705860416
Or get in touch with me on douglasekuwanda@gmail.com
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file efriser-0.1.10.tar.gz.
File metadata
- Download URL: efriser-0.1.10.tar.gz
- Upload date:
- Size: 19.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07626b825daea513dbd15f946cdf11ce648ad5f1d5d46007b9334bf01e4bd9e4
|
|
| MD5 |
940a8c04e6fb56f7f4fbd2db28b384fb
|
|
| BLAKE2b-256 |
a3d43e525dcc4e4cfdfaf6bdd97a2ea05b41c88c3124b0413b93a669501100ff
|
File details
Details for the file efriser-0.1.10-py3-none-any.whl.
File metadata
- Download URL: efriser-0.1.10-py3-none-any.whl
- Upload date:
- Size: 24.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afab2ee4c457b6fb0a5b4bc7d93e0ae38f664a3ebde47f1c3aaac6b5217d1c13
|
|
| MD5 |
2ef93a4c3336af7611507c3979d66d94
|
|
| BLAKE2b-256 |
d141400fed5b61319f4d3e1d7c29ef1f3f5e40b3c8c82fab215b8a85785c32f5
|