Isolate Tally group hierarchy extraction from proven mirror reads
This commit is contained in:
@@ -4,7 +4,7 @@ import io
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
ERP_LOCAL_AGENT_VERSION = "1.26.6"
|
ERP_LOCAL_AGENT_VERSION = "1.26.7"
|
||||||
ERP_LOCAL_AGENT_NAME = "ERP Local Agent"
|
ERP_LOCAL_AGENT_NAME = "ERP Local Agent"
|
||||||
RUNTIME_ROOT = Path(__file__).resolve().parent / "local_agent_runtime"
|
RUNTIME_ROOT = Path(__file__).resolve().parent / "local_agent_runtime"
|
||||||
_DETERMINISTIC_ZIP_TIMESTAMP = (2026, 1, 1, 0, 0, 0)
|
_DETERMINISTIC_ZIP_TIMESTAMP = (2026, 1, 1, 0, 0, 0)
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
__version__ = "1.26.6"
|
__version__ = "1.26.7"
|
||||||
AGENT_NAME = "ERP Local Agent"
|
AGENT_NAME = "ERP Local Agent"
|
||||||
|
|||||||
@@ -317,6 +317,10 @@ class AccountingMirrorEngine:
|
|||||||
"COMPANY - ROWS READ:": (14, "Company read"),
|
"COMPANY - ROWS READ:": (14, "Company read"),
|
||||||
"LEDGER MASTER - BEFORE QUERY": (15, "Reading ledgers"),
|
"LEDGER MASTER - BEFORE QUERY": (15, "Reading ledgers"),
|
||||||
"LEDGER MASTER - ROWS READ:": (25, "Ledgers read"),
|
"LEDGER MASTER - ROWS READ:": (25, "Ledgers read"),
|
||||||
|
"GROUP MASTER - BEFORE QUERY": (91, "Reading group/subgroup hierarchy"),
|
||||||
|
"GROUP MASTER NAME/PARENT - BEFORE QUERY": (91, "Reading group/subgroup hierarchy"),
|
||||||
|
"GROUP MASTER COMPAT - BEFORE QUERY": (91, "Reading group/subgroup hierarchy"),
|
||||||
|
"GROUP SUMMARY": (93, "Group/subgroup hierarchy completed"),
|
||||||
"STOCK MASTER - BEFORE QUERY": (26, "Reading stock items"),
|
"STOCK MASTER - BEFORE QUERY": (26, "Reading stock items"),
|
||||||
"STOCK MASTER - ROWS READ:": (34, "Stock items read"),
|
"STOCK MASTER - ROWS READ:": (34, "Stock items read"),
|
||||||
"STOCK HSN MASTER - BEFORE QUERY": (35, "Reading HSN details"),
|
"STOCK HSN MASTER - BEFORE QUERY": (35, "Reading HSN details"),
|
||||||
|
|||||||
-5
@@ -19,11 +19,6 @@
|
|||||||
Fetch : Name, Parent, GUID, AlterID, OpeningBalance, ClosingBalance, IsRevenue, PartyGSTIN, GSTRegistrationType
|
Fetch : Name, Parent, GUID, AlterID, OpeningBalance, ClosingBalance, IsRevenue, PartyGSTIN, GSTRegistrationType
|
||||||
Is ODBC Table : Yes
|
Is ODBC Table : Yes
|
||||||
|
|
||||||
[Collection : ERPAMGroupMaster]
|
|
||||||
Type : Group
|
|
||||||
Fetch : Name, Parent, GUID
|
|
||||||
Is ODBC Table : Yes
|
|
||||||
|
|
||||||
[Collection : ERPAMStockMaster]
|
[Collection : ERPAMStockMaster]
|
||||||
Type : StockItem
|
Type : StockItem
|
||||||
Fetch : Name, Parent, GUID, AlterID, BaseUnits, OpeningBalance, OpeningValue, GSTApplicable, GSTRepUoM, GSTTypeofSupply, GSTItemHSNCodeEx
|
Fetch : Name, Parent, GUID, AlterID, BaseUnits, OpeningBalance, OpeningValue, GSTApplicable, GSTRepUoM, GSTTypeofSupply, GSTItemHSNCodeEx
|
||||||
|
|||||||
+77
-9
@@ -58,6 +58,74 @@ class TallyAccountingMirrorV301
|
|||||||
Console.Out.Flush();
|
Console.Out.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool TryExtractFresh(string dsn, string label, string sql, string path,
|
||||||
|
out int rows, out double sec)
|
||||||
|
{
|
||||||
|
rows = 0;
|
||||||
|
sec = 0;
|
||||||
|
try {
|
||||||
|
using (var fresh = new OdbcConnection("DSN=" + dsn + ";")) {
|
||||||
|
fresh.Open();
|
||||||
|
Extract(fresh, label, sql, path, out rows, out sec);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(Exception ex) {
|
||||||
|
Console.WriteLine(label + " - OPTIONAL QUERY FAILED");
|
||||||
|
Console.WriteLine(label + " - ERROR TYPE: " + ex.GetType().FullName);
|
||||||
|
Console.WriteLine(label + " - ERROR: " + ex.Message);
|
||||||
|
if(ex.InnerException != null)
|
||||||
|
Console.WriteLine(label + " - INNER: " + ex.InnerException.Message);
|
||||||
|
Console.Out.Flush();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteEmptyGroupCsv(string path)
|
||||||
|
{
|
||||||
|
using (var w = new StreamWriter(path, false, new UTF8Encoding(true))) {
|
||||||
|
w.WriteLine("GUID,Name,Parent");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ExtractGroupHierarchy(string dsn, string outDir,
|
||||||
|
out int groupRows, out double groupSec)
|
||||||
|
{
|
||||||
|
groupRows = 0;
|
||||||
|
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.
|
||||||
|
if (TryExtractFresh(
|
||||||
|
dsn, "GROUP MASTER",
|
||||||
|
"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();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int Main(string[] args)
|
static int Main(string[] args)
|
||||||
{
|
{
|
||||||
string dsn="TallyODBC64_9000", outDir="mirror_output_v3_0_1";
|
string dsn="TallyODBC64_9000", outDir="mirror_output_v3_0_1";
|
||||||
@@ -69,6 +137,8 @@ class TallyAccountingMirrorV301
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
var total=Stopwatch.StartNew();
|
var total=Stopwatch.StartNew();
|
||||||
|
int groupRows = 0;
|
||||||
|
double groupSec = 0;
|
||||||
Console.WriteLine("ERP ACCOUNTING MIRROR v3.0.1 - ERP INTEGRATION CANDIDATE");
|
Console.WriteLine("ERP ACCOUNTING MIRROR v3.0.1 - ERP INTEGRATION CANDIDATE");
|
||||||
Console.WriteLine("READ ONLY | ODBC | NO XML | NO TALLY WRITES");
|
Console.WriteLine("READ ONLY | ODBC | NO XML | NO TALLY WRITES");
|
||||||
Console.WriteLine("BEFORE CONNECT");
|
Console.WriteLine("BEFORE CONNECT");
|
||||||
@@ -88,13 +158,6 @@ class TallyAccountingMirrorV301
|
|||||||
"SELECT $GUID,$AlterID,$Name,$Parent,$OpeningBalance,$ClosingBalance,$IsRevenue,$PartyGSTIN,$GSTRegistrationType FROM ERPAMLedgerMaster",
|
"SELECT $GUID,$AlterID,$Name,$Parent,$OpeningBalance,$ClosingBalance,$IsRevenue,$PartyGSTIN,$GSTRegistrationType FROM ERPAMLedgerMaster",
|
||||||
Path.Combine(outDir,"ledger_master.csv"),out l,out sl);
|
Path.Combine(outDir,"ledger_master.csv"),out l,out sl);
|
||||||
|
|
||||||
// Group hierarchy only. Ledger extraction above is intentionally
|
|
||||||
// the same proven ERPAMLedgerMaster path used before.
|
|
||||||
int groupRows; double groupSec;
|
|
||||||
Extract(cn,"GROUP MASTER",
|
|
||||||
"SELECT $GUID,$Name,$Parent FROM ERPAMGroupMaster",
|
|
||||||
Path.Combine(outDir,"group_master.csv"),out groupRows,out groupSec);
|
|
||||||
|
|
||||||
Extract(cn,"STOCK MASTER",
|
Extract(cn,"STOCK MASTER",
|
||||||
"SELECT $GUID,$AlterID,$Name,$Parent,$BaseUnits,$OpeningBalance,$OpeningValue,$GSTApplicable,$GSTRepUoM,$GSTTypeofSupply,$GSTItemHSNCodeEx FROM ERPAMStockMaster",
|
"SELECT $GUID,$AlterID,$Name,$Parent,$BaseUnits,$OpeningBalance,$OpeningValue,$GSTApplicable,$GSTRepUoM,$GSTTypeofSupply,$GSTItemHSNCodeEx FROM ERPAMStockMaster",
|
||||||
Path.Combine(outDir,"stock_master.csv"),out s,out ss);
|
Path.Combine(outDir,"stock_master.csv"),out s,out ss);
|
||||||
@@ -132,9 +195,8 @@ class TallyAccountingMirrorV301
|
|||||||
"SELECT $VoucherGUID,$VoucherAlterID,$VoucherMasterID,$VoucherDate,$VoucherType,$VoucherNumber,$PartyLedger,$StockItemName,$HSNCode,$BilledQty,$ActualQty,$Rate,$IsDeemedPositive,$InventoryAmount FROM ERPAMInventoryMovement",
|
"SELECT $VoucherGUID,$VoucherAlterID,$VoucherMasterID,$VoucherDate,$VoucherType,$VoucherNumber,$PartyLedger,$StockItemName,$HSNCode,$BilledQty,$ActualQty,$Rate,$IsDeemedPositive,$InventoryAmount FROM ERPAMInventoryMovement",
|
||||||
Path.Combine(outDir,"inventory_movement.csv"),out im,out sim);
|
Path.Combine(outDir,"inventory_movement.csv"),out im,out sim);
|
||||||
|
|
||||||
Console.WriteLine("SUMMARY | Company="+c+
|
Console.WriteLine("CORE SUMMARY | Company="+c+
|
||||||
" | Ledger="+l+
|
" | Ledger="+l+
|
||||||
" | Group="+groupRows+
|
|
||||||
" | Stock="+s+
|
" | Stock="+s+
|
||||||
" | StockHSN="+tax+" | StockGST="+gstRows+
|
" | StockHSN="+tax+" | StockGST="+gstRows+
|
||||||
" | Voucher="+v+
|
" | Voucher="+v+
|
||||||
@@ -143,6 +205,12 @@ class TallyAccountingMirrorV301
|
|||||||
" | TotalSeconds="+total.Elapsed.TotalSeconds.ToString("0.000"));
|
" | TotalSeconds="+total.Elapsed.TotalSeconds.ToString("0.000"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read only Group -> Parent hierarchy after all proven core reads have
|
||||||
|
// completed and the original connection has been disposed.
|
||||||
|
ExtractGroupHierarchy(dsn, outDir, out groupRows, out groupSec);
|
||||||
|
Console.WriteLine("GROUP SUMMARY | Rows="+groupRows+
|
||||||
|
" | Seconds="+groupSec.ToString("0.000"));
|
||||||
|
|
||||||
Console.WriteLine("SUCCESS");
|
Console.WriteLine("SUCCESS");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user