An open API service indexing awesome lists of open source software.

https://github.com/alok-ahirrao/tally-odbc-integration-with-python

This project provides a Flask-based REST API to integrate with Tally ERP 9 / TallyPrime.
https://github.com/alok-ahirrao/tally-odbc-integration-with-python

api-rest debugging flask odbc odbc-api odbcsql python python3 tally tally-odbc

Last synced: 2 months ago
JSON representation

This project provides a Flask-based REST API to integrate with Tally ERP 9 / TallyPrime.

Awesome Lists containing this project

README

        

# Tally Integration API

## Overview

This project provides a Flask-based REST API to integrate with Tally ERP 9 / TallyPrime. It allows external applications to programmatically create Sales Invoices in Tally by sending structured data, which is then converted into Tally-compatible XML format. The API handles communication with the Tally instance, processes responses, and provides clear feedback.

## Output Screenshots

### Tally Invoice Image
![Tally Invoice](output/tally_invoice.jpg)

### Tally Invoice PDF
[View PDF](output/tally_invoice.pdf)

### Tally Output
![Tally Output 2](output/tally_output2.jpg)

### Post API Output
![Post API Output](output/Post_api_output1.jpg)

## 📘 Tally Initial Setup

Before running the integration, make sure Tally is properly configured.

👉 For full setup instructions, **[check out Tally Initial Setup.md](./Tally%20Initial%20Setup.md)**

This includes:
- Enabling Tally HTTP Server
- Creating necessary ledgers and inventory items
- Configuring the company name for XML import
- Common errors and how to resolve them

## Features

* **Create Sales Invoices:** Endpoint to create sales vouchers (invoice mode) in Tally.
* **Tally XML Generation:** Dynamically generates Tally-compatible XML for voucher import based on input JSON data.
* **Data Validation:** Validates incoming request data (required fields, data types, amounts, dates).
* **Tally Communication:** Sends XML requests to the configured Tally instance URL.
* **Response Parsing:** Interprets Tally's XML response to determine success or failure.
* **Environment-Based Configuration:** Uses `.env` file for easy configuration of Tally URL, company name, ledger names, logging level, and server settings.
* **Structured Error Handling:** Returns informative JSON error messages with appropriate HTTP status codes.
* **Logging:** Configurable logging to track requests, responses, and errors.

## Tech Stack

* **Python 3.x**
* **Flask:** Micro web framework for the API.
* **Requests:** For making HTTP requests to Tally.
* **python-dotenv:** For managing environment variables.
* **Standard Libraries:** `xml.etree.ElementTree`, `logging`, `os`, `uuid`, `datetime`, `decimal`.

## Setup Instructions

1. **Clone the repository:**
```bash
git clone https://github.com/alok-ahirrao/Tally-ODBC-Integration-with-Python.git
cd Tally-ODBC-Integration-with-Python
```

2. **Create and activate a virtual environment (recommended):**
```bash
# Windows
python -m venv venv
.\venv\Scripts\activate

# macOS/Linux
python3 -m venv venv
source venv/bin/activate
```

3. **Install dependencies:**
```bash
pip install -r requirements.txt
```

4. **Create a `.env` file:**
Copy the example below and create a `.env` file in the project root. Fill in your specific Tally configuration details.

## Environment Variables (`.env`)

Create a `.env` file in the project root with the following variables:

```dotenv
# Tally Configuration
TALLY_URL=http://localhost:9000 # Your Tally instance URL (ensure Tally is running and configured for ODBC/HTTP access)
DEFAULT_COMPANY_NAME="Your Company Name Ltd" # The exact name of the company loaded in Tally
SALES_LEDGER_NAME="Sales Account" # The exact name of your Sales Ledger in Tally
TAX_LEDGER_NAME="Output GST" # The exact name of your primary Tax Ledger (e.g., Output CGST, Output SGST, Output IGST, or a combined GST ledger)

# Logging Configuration
LOG_LEVEL=INFO # Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)

# Flask Server Configuration (Optional - Defaults are usually fine for development)
# FLASK_RUN_HOST=0.0.0.0 # Host to bind to (0.0.0.0 to allow external access)
# FLASK_RUN_PORT=5001 # Port to run the server on
# FLASK_DEBUG=True # Enable Flask debug mode (DO NOT use True in production)

# Security (Recommended - Implement API Key check in your code)
# API_KEY="your_secret_api_key_here"
```

**Important:** Ensure the `DEFAULT_COMPANY_NAME`, `SALES_LEDGER_NAME`, and `TAX_LEDGER_NAME` exactly match the names configured in your Tally company data.

## How to Run the Server

Ensure your virtual environment is activated and the `.env` file is configured.

```bash
flask run
```

Alternatively, you can run the script directly:

```bash
python app.py
```

The server will start, typically on `http://127.0.0.1:5001` (or as configured in `.env`).

## API Endpoints

### 1. Create Sales Invoice

* **URL:** `/create-invoice`
* **Method:** `POST`
* **Content-Type:** `application/json`
* **Description:** Creates a new Sales voucher (in Invoice mode) in the specified Tally company. Requires detailed invoice data in the request body.
* **Request Body (Example JSON):**

```json
{
"date": "2025-04-06", // YYYY-MM-DD format
"invoice_number": "API-INV-001", // Unique invoice number
"customer_name": "Customer Ledger Name", // Must exist in Tally
"items": [
{
"name": "Stock Item A", // Must exist in Tally
"quantity": "2",
"rate": "150.50",
"unit": "Nos" // Optional, defaults to 'Nos' if omitted. Must match Tally unit.
},
{
"name": "Stock Item B",
"quantity": "1",
"rate": "500.00"
}
],
"total_amount": "801.00", // Sum of (item quantity * item rate)
"tax": "72.09", // Total tax amount for the invoice
"grand_total": "873.09", // total_amount + tax
"narration": "Optional narration for the voucher", // Optional
"company_name": "Optional Company Name Ltd" // Optional: Overrides DEFAULT_COMPANY_NAME from .env if provided
}
```

* **Success Response (201 Created):**

```json
{
"message": "Voucher processed successfully by Tally. (LastVchId: 123)", // Example success message
"invoice_reference_id": "API-INV-001",
"request_id": "unique-request-uuid"
}
```

* **Error Response (e.g., 400 Bad Request, 422 Unprocessable Entity, 50x Server Error):**

```json
// Validation Error (400)
{
"error": "Data validation failed: Missing required fields: customer_name",
"request_id": "unique-request-uuid"
}

// Tally Rejection Error (422)
{
"error": "Tally rejected the voucher.",
"tally_message": "Tally Error: Ledger 'NonExistent Customer' does not exist.",
"request_id": "unique-request-uuid"
}

// Connection Error (503)
{
"error": "Could not connect to Tally at http://localhost:9000. Is Tally running and accessible?",
"request_id": "unique-request-uuid"
}
```

### 2. Get Sales Invoice (Planned)

* **URL:** `/get-invoice/`
* **Method:** `GET`
* **Description:** (This endpoint is planned but not yet implemented in the current version). It would fetch details of an existing sales invoice from Tally using its voucher number.

## Error Handling

The API handles several types of errors:

* **Request Validation Errors (400 Bad Request):** Missing fields, invalid data types (dates, numbers), inconsistent amounts.
* **Invalid Content-Type (415 Unsupported Media Type):** If the request is not `application/json`.
* **Tally Functional Errors (422 Unprocessable Entity):** Tally receives the request but rejects it due to issues like non-existent ledgers/items, incorrect periods, etc. The specific error from Tally is included in the response.
* **Tally Connection Errors (502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout):** Failure to connect to the Tally instance (Tally not running, network issues, incorrect URL, timeout).
* **Internal Server Errors (500 Internal Server Error):** Unexpected errors during XML generation or response processing.

Error responses include a descriptive `error` message and a unique `request_id` for tracking.

## Logging

* Logging is configured using Python's standard `logging` module.
* The log level (`DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`) can be set via the `LOG_LEVEL` environment variable.
* Logs include timestamps, level, and messages, providing insights into request processing, Tally communication, and errors.
* By default, logs are printed to the console where the Flask server is running.

## Security Notes

* **API Key:** The current code does *not* implement API key authentication. **It is strongly recommended to add API key validation** to secure the endpoints. This typically involves:
* Adding an `API_KEY` variable to the `.env` file.
* Requiring clients to send the API key in a request header (e.g., `X-API-Key`).
* Adding a decorator or middleware in Flask to check the provided key against the one in `.env` before processing requests.
* **HTTPS:** In a production environment, run the Flask application behind a proper web server (like Nginx or Apache) configured with HTTPS/SSL to encrypt communication.
* **Network Security:** Ensure the Tally instance is accessible only from trusted network locations. Restrict access to the Tally port (default 9000).
* **Input Sanitization:** While basic validation is done, ensure robust validation against potential injection or unexpected data, especially if data originates from untrusted sources.

## Tally Configuration Requirements

For the integration to work, ensure the following in your Tally setup:

1. **Tally ERP 9 / TallyPrime is running.**
2. **Enable ODBC/HTTP Access:** In Tally's Gateway Server configuration (or Tally.ini), ensure the port (default 9000) is enabled for external connections. Configure security settings appropriately (e.g., allow specific client IPs if needed).
3. **Company Loaded:** The company specified in `DEFAULT_COMPANY_NAME` (or the `company_name` in the request) must be loaded in Tally when the request is made.
4. **Ledgers Exist:** The `customer_name`, `SALES_LEDGER_NAME`, and `TAX_LEDGER_NAME` must exist in the loaded Tally company.
5. **Stock Items Exist:** All item names provided in the `items` array must exist as Stock Items in Tally.
6. **Units Exist:** Item units (`unit`) must match units defined in Tally.
7. **Voucher Type:** The "Sales" voucher type should exist and be configured appropriately (e.g., for inventory tracking if used).

## Troubleshooting Tips

* **Connection Refused/Timeout:** Verify Tally is running, the company is loaded, the `TALLY_URL` in `.env` is correct, and the port is open/accessible from where the API server is running. Check firewall settings.
* **"Ledger/Stock Item does not exist" Error (422):** Double-check the spelling and case of ledger names and stock item names in your request against Tally data. Ensure they exist in the *currently loaded* company.
* **XML Errors / "Invalid XML" (500/422):** Check the generated XML structure in `app.py` (`create_tally_xml` function) against Tally's required format. Look for encoding issues (should be UTF-8). Check Tally's `tally.imp` file (in the Tally application folder) for detailed import errors.
* **Amount Mismatches (400/422):** Ensure `total_amount`, `tax`, and `grand_total` are calculated correctly and consistently with the sum of item amounts. Check for rounding differences.
* **Date Errors (400/422):** Ensure the date format is `YYYY-MM-DD`. Tally might reject dates outside the current financial period.
* **Check API Logs:** Set `LOG_LEVEL=DEBUG` in `.env` for detailed logs, including request data and Tally responses.

## 📜 License

Copyright © 2025, Alok Ahirrao

Licensed under the **Creative Commons Attribution-NonCommercial 4.0 International License**. You may use or modify this project for personal or educational purposes only. Commercial usage requires explicit permission.

For inquiries, please contact [[email protected]](mailto:[email protected]).

## Author

**Alok Ahirrao**
[GitHub](https://github.com/alok-ahirrao) | [LinkedIn](https://www.linkedin.com/in/alokahirrao/) | [Resume](https://alokahirrao.netlify.app)
📧 [email protected]

🌟 **Happy Coding!** 🌟