Скрипт Tally Python Bridge [закрыт]Python

Программы на Python
Ответить
Anonymous
 Скрипт Tally Python Bridge [закрыт]

Сообщение Anonymous »

Этот код предназначен для соединения 3 компаний в Tally Prime A,B,C
A и B предназначены для продаж, а C — для управления запасами.
Когда я запускаю сценарий, A распознается, но никаких действий в C (компания C не распознается)
Компания открыта в Tally.
Порт — 9000, и все остальные настройки соответственно. В чем проблема, я не могу понять. ПОМОГИТЕ!
import requests
import time
import sqlite3
import xml.etree.ElementTree as ET
import re
from datetime import date

# --- Configuration ---
TALLY_URL = "http://localhost:9000"
COMPANY_A = "A"
COMPANY_B = "B"
CENTRAL_COMPANY = "C"
POLL_INTERVAL = 15
# --- Configuration End ---

DB_FILE = "tally_sync.db"

conn = sqlite3.connect(DB_FILE)
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS processed_vouchers (
company TEXT, voucher_number TEXT, item_name TEXT, qty REAL,
PRIMARY KEY(company, voucher_number, item_name)
)
""")
conn.commit()

def safe_parse_xml(response_content):
try:
text = response_content.decode("utf-8", errors="replace")
text = text.replace('', '')
invalid_xml_chars_re = r'[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\U00010000-\U0010FFFF]'
text = re.sub(invalid_xml_chars_re, '', text)
return ET.fromstring(text)
except Exception as e:
print(f"[XML Parse Error] Tally ka response XML format mein nahi hai. Error: {e}")
with open("LAST_ERROR_RESPONSE.xml", "w", encoding="utf-8") as f: f.write(text)
return None

def get_vouchers_from_tally(company_name):
from_date = "20240401"
to_date = "20260331"
xml_req = f"""
Export Data
{from_date}{to_date}{company_name}
Voucher Register
"""
try:
r = requests.post(TALLY_URL, data=xml_req.encode("utf-8"), timeout=10)
r.raise_for_status()
return safe_parse_xml(r.content)
except requests.exceptions.RequestException as e:
print(f"[Connection Error] Tally se connect nahi ho pa raha: {e}")
return None

def parse_vouchers_from_xml(tree):
vouchers = {}
if tree is None: return vouchers
for v in tree.findall(".//VOUCHER"):
vch_type = v.findtext("VOUCHERTYPENAME")
if vch_type and "sales" in vch_type.lower():
vno = v.findtext("VOUCHERNUMBER")
if not vno: continue
items = []
for item in v.findall(".//ALLINVENTORYENTRIES.LIST"):
name = item.findtext("STOCKITEMNAME")
qty_text = item.findtext("BILLEDQTY", "0")
try:
qty_value_str = re.split(r'\s', qty_text.strip())[0]
if qty_value_str: qty = abs(float(qty_value_str))
else: qty = 0
except (ValueError, IndexError): qty = 0
if name and qty > 0: items.append({'name': name, 'qty': qty})
if items: vouchers[vno] = items
return vouchers

# >
def build_stock_journal_xml(company, item_name, qty, mode):
from datetime import date
today = date.today().strftime("%Y%m%d")
narration = "Auto Re-Stock for deleted bill" if mode == 'add' else "Auto Stock reduction for sale"

# For Tally: positive when adding, negative when reducing
is_positive = "Yes" if mode == 'add' else "No"
qty_value = qty if mode == 'add' else -qty

xml = f"""


Import Data




Vouchers

{company}





{today}
Stock Journal
{narration}

{item_name}
{is_positive}
{qty_value}
{qty_value}







"""
return xml
def post_to_tally(xml):
try:
r = requests.post(TALLY_URL, data=xml.encode("utf-8"), timeout=10)
r.raise_for_status()
response_text = r.content.decode('utf-8', errors='ignore')
if "1" in response_text or "1" in response_text:
return True
else:
print(f"[Warning] Tally ne entry confirm nahi ki: {response_text.strip()[:200]}")
return False
except requests.exceptions.RequestException as e:
print(f"[POST Error] Tally mein post karte waqt error: {e}")
return False

def reconcile_deleted_vouchers(company, current_vouchers_in_tally):
cur.execute("SELECT DISTINCT voucher_number FROM processed_vouchers WHERE company=?", (company,))
processed_vnos = {row[0] for row in cur.fetchall()}
deleted_vnos = processed_vnos - set(current_vouchers_in_tally.keys())
for vno in deleted_vnos:
print(f"--- Bill delete hua! Vch No: {vno} ({company}). Stock waapis add kiya ja raha hai...")
cur.execute("SELECT item_name, qty FROM processed_vouchers WHERE company=? AND voucher_number=?", (company, vno))
items_to_restock = cur.fetchall()
success_count = 0
for item_name, qty in items_to_restock:
xml = build_stock_journal_xml(CENTRAL_COMPANY, item_name, qty, mode='add')
if post_to_tally(xml):
print(f" → Success: {item_name} ({qty}) CENTRAL mein waapis add ho gaya.")
success_count += 1
else:
print(f" → Failed: {item_name} ({qty}) waapis add nahi ho paya.")
if success_count == len(items_to_restock):
cur.execute("DELETE FROM processed_vouchers WHERE company=? AND voucher_number=?", (company, vno))
conn.commit()
print(f"Voucher {vno} database se saaf kar diya gaya hai.")

def process_company(company):
print(f"\nChecking vouchers for '{company}'...")
tree = get_vouchers_from_tally(company)
if tree is None:
print(f"'{company}' se data nahi mil paya. Agle cycle mein try karenge.")
return
current_vouchers = parse_vouchers_from_xml(tree)
if not current_vouchers:
print("Is company mein koi Sales voucher nahi mila.")
reconcile_deleted_vouchers(company, current_vouchers)
for vno, items in current_vouchers.items():
for item in items:
item_name, qty = item['name'], item['qty']
cur.execute("SELECT 1 FROM processed_vouchers WHERE company=? AND voucher_number=? AND item_name=?", (company, vno, item_name))
if cur.fetchone() is None:
print(f"→ Naya Sale Bill mila: {item_name} ({qty}) in Vch No: {vno}. Stock kam kiya ja raha hai...")
xml = build_stock_journal_xml(CENTRAL_COMPANY, item_name, qty, mode='reduce')
if post_to_tally(xml):
print(f" → Success: Stock CENTRAL mein kam ho gaya.")
cur.execute("INSERT INTO processed_vouchers VALUES (?, ?, ?, ?)", (company, vno, item_name, qty))
conn.commit()
else:
print(f" → Failed: Stock Journal entry nahi ho payi.")

def main():
print("--- Tally Bridge Script Shuru ho gaya hai ---")
while True:
try:
for company in [COMPANY_A, COMPANY_B]:
process_company(company)
print(f"\n--- Cycle complete. Ab {POLL_INTERVAL} seconds intezaar... ---\n")
time.sleep(POLL_INTERVAL)
except KeyboardInterrupt:
print("\nScript band kiya ja raha hai. Bye!")
break
except Exception as e:
print(f"An unexpected error occurred: {e}")
time.sleep(POLL_INTERVAL)

if __name__ == "__main__":
main()


Подробнее здесь: https://stackoverflow.com/questions/798 ... dge-script
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»