Add flat Tally group master alongside proven ledger master

This commit is contained in:
A R R R Associates
2026-09-08 21:38:13 +05:30
parent f334d25ed4
commit 8bbdd3be30
5 changed files with 65 additions and 15 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ import io
from pathlib import Path
import zipfile
ERP_LOCAL_AGENT_VERSION = "1.26.7"
ERP_LOCAL_AGENT_VERSION = "1.26.8"
ERP_LOCAL_AGENT_NAME = "ERP Local Agent"
RUNTIME_ROOT = Path(__file__).resolve().parent / "local_agent_runtime"
_DETERMINISTIC_ZIP_TIMESTAMP = (2026, 1, 1, 0, 0, 0)
@@ -1,2 +1,2 @@
__version__ = "1.26.7"
__version__ = "1.26.8"
AGENT_NAME = "ERP Local Agent"
@@ -245,6 +245,53 @@ class AccountingMirrorEngine:
value = _text(value)
values.append(value)
db.execute(f"INSERT INTO {table} ({','.join(names)}) VALUES ({placeholders})", values)
# Common flat accounting master table. Keep the original
# ledger_master and group_master physical tables intact.
db.execute("DROP TABLE IF EXISTS accounting_master_flat")
db.execute("""
CREATE TABLE accounting_master_flat (
object_type TEXT NOT NULL,
guid TEXT,
name TEXT NOT NULL,
parent TEXT,
opening_balance REAL,
closing_balance REAL
)
""")
db.execute("""
INSERT INTO accounting_master_flat(
object_type,guid,name,parent,opening_balance,closing_balance
)
SELECT
'LEDGER',
COALESCE(ledger_guid,''),
COALESCE(ledger_name,''),
COALESCE(parent_group,''),
opening_balance,
closing_balance
FROM ledger_master
""")
db.execute("""
INSERT INTO accounting_master_flat(
object_type,guid,name,parent,opening_balance,closing_balance
)
SELECT
'GROUP',
COALESCE(master_guid,''),
COALESCE(name,''),
COALESCE(parent,''),
NULL,
NULL
FROM group_master
""")
db.execute(
"CREATE INDEX IF NOT EXISTS idx_accounting_master_flat_type_name "
"ON accounting_master_flat(object_type,name)"
)
db.execute(
"CREATE INDEX IF NOT EXISTS idx_accounting_master_flat_parent "
"ON accounting_master_flat(parent)"
)
db.commit()
finally:
db.close()
@@ -19,6 +19,11 @@
Fetch : Name, Parent, GUID, AlterID, OpeningBalance, ClosingBalance, IsRevenue, PartyGSTIN, GSTRegistrationType
Is ODBC Table : Yes
[Collection : ERPAMFlatGroupMaster]
Type : Group
Fetch : Name, Parent, GUID
Is ODBC Table : Yes
[Collection : ERPAMStockMaster]
Type : StockItem
Fetch : Name, Parent, GUID, AlterID, BaseUnits, OpeningBalance, OpeningValue, GSTApplicable, GSTRepUoM, GSTTypeofSupply, GSTItemHSNCodeEx
@@ -95,31 +95,29 @@ class TallyAccountingMirrorV301
groupSec = 0;
string path = Path.Combine(outDir, "group_master.csv");
// Tally's built-in ODBC Groups table is queried on its own connection.
// This deliberately avoids a custom Group TDL collection and protects
// the proven Ledger/Voucher extraction connection from being disabled.
// Flat Group Master uses the same TDL/ODBC pattern as the proven
// Ledger Master. It is deliberately queried only AFTER the core mirror
// has finished and on a fresh connection, so a Group-side Tally error
// can never disable the Ledger/Voucher/Stock extraction connection.
if (TryExtractFresh(
dsn, "GROUP MASTER",
"SELECT $GUID,$Name,$Parent FROM ERPAMFlatGroupMaster",
path, out groupRows, out groupSec) && groupRows > 0)
return true;
// Compatibility fallback for builds that expose Groups directly.
if (TryExtractFresh(
dsn, "GROUP MASTER COMPAT",
"SELECT $GUID,$Name,$Parent FROM Groups",
path, out groupRows, out groupSec) && groupRows > 0)
return true;
// Some builds expose the table but not GUID. Name + Parent are all the
// ERP needs for recursive Fixed Assets / Capital hierarchy traversal.
if (TryExtractFresh(
dsn, "GROUP MASTER NAME/PARENT",
"SELECT $Name,$Parent FROM Groups",
path, out groupRows, out groupSec) && groupRows > 0)
return true;
// Last compatibility attempt: singular built-in collection/table name,
// again on a NEW connection so a rejected query cannot poison the core.
if (TryExtractFresh(
dsn, "GROUP MASTER COMPAT",
"SELECT $GUID,$Name,$Parent FROM Group",
path, out groupRows, out groupSec) && groupRows > 0)
return true;
WriteEmptyGroupCsv(path);
Console.WriteLine("GROUP MASTER - NO GROUP ROWS EXTRACTED; CORE MIRROR DATA REMAINS VALID");
Console.Out.Flush();