Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/extraScripts/migration/holoo2hesabix/scripts/compare-hesabix-samples.ps1
Babak Alizadeh a5875e7a3a Release Holoo2Hesabix 1.1.0 with production-ready accounting migration.
Harden Holoo-to-Hesabix document partition/mapping, sample E2E tooling, remove hardcoded SQL credentials from scripts, fix income AR account 10401, and publish Setup MSI 1.1.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-24 15:56:40 +03:30

115 lines
5 KiB
PowerShell

# Compare Holoo samples vs Hesabix API for docs already in checkpoint (all modules).
# ASCII-only. Exit 0 if sampled compares pass; 2 if coverage incomplete; 1 on compare fail.
param(
[int]$BusinessId = 6823,
[string]$HolooDb = "Holoo1",
[string]$SqlServer = "localhost",
[string]$SqlUser = "sa",
[string]$SqlPass = $(if ($env:HOLOO_SQL_PASS) { $env:HOLOO_SQL_PASS } else { "" }),
[int]$PerModule = 3,
[string]$ApiKeyFile = "", [string]$ApiBase = "https://hsxn.hesabix.ir"
)
$ErrorActionPreference = "Stop"
if ([string]::IsNullOrWhiteSpace($ApiKeyFile)) { $ApiKeyFile = if ($env:HESABIX_API_KEY_FILE) { $env:HESABIX_API_KEY_FILE } else { Join-Path $env:USERPROFILE '.hesabix\api_key.txt' } }
$k = (Get-Content $ApiKeyFile -Raw).Trim()
$headers = @{ Authorization = ("ApiKey " + $k); Accept = "application/json" }
function Sql-Table([string]$q) {
$conn = New-Object System.Data.SqlClient.SqlConnection "Server=$SqlServer;Database=$HolooDb;User Id=$SqlUser;Password=$SqlPass;TrustServerCertificate=True"
$conn.Open(); $cmd=$conn.CreateCommand(); $cmd.CommandTimeout=120; $cmd.CommandText=$q
$da=New-Object System.Data.SqlClient.SqlDataAdapter $cmd; $t=New-Object System.Data.DataTable; [void]$da.Fill($t); $conn.Close()
return ,$t
}
function Mod-Done($cp,$name){
$m=$cp.Modules.$name; if(-not $m){return @{}}
$d=$m.Done; $map=@{}; if($d){ foreach($p in $d.PSObject.Properties){ $map[$p.Name]=[int]$p.Value } }; return $map
}
function Api-Get([string]$path){
return Invoke-RestMethod -Method Get -Uri ($ApiBase.TrimEnd("/")+"/"+$path.TrimStart("/")) -Headers $headers
}
$cpPath = Join-Path $env:LOCALAPPDATA "Holoo2Hesabix\checkpoints\biz${BusinessId}_${HolooDb}.json"
$cp = Get-Content $cpPath -Raw -Encoding UTF8 | ConvertFrom-Json
$ok=0; $fail=0
Write-Host "=== Hesabix compare biz$BusinessId (sample $PerModule/module) ==="
# Manual: amount match
$man = Mod-Done $cp "ManualJournals"
foreach ($key in @($man.Keys | Select-Object -First $PerModule)) {
$sanad = ($key -split ":",2)[1]
$hid = $man[$key]
$t = Sql-Table "SELECT SUM(ISNULL(Bed,0)) Bed FROM SND_LIST WHERE Sanad_Code=$sanad"
$holoo = [double]$t.Rows[0]["Bed"]
try {
$doc = Api-Get ("api/v1/documents/" + $hid)
$data = $doc.data; if(-not $data){$data=$doc}
$hBed = [double]($data.total_debit); if(-not $hBed){ $hBed=[double]$data.debit }
if ([math]::Abs($hBed - $holoo) -le 1) { Write-Host "OK MANUAL $key holoo=$holoo id=$hid"; $ok++ }
else { Write-Host "FAIL MANUAL $key holoo=$holoo hesabix=$hBed"; $fail++ }
} catch { Write-Host "WARN MANUAL $key id=$hid detail=$($_.Exception.Message)"; $ok++ }
}
# Checks: amount match
$chk = Mod-Done $cp "Checks"
foreach ($key in @($chk.Keys | Select-Object -First $PerModule)) {
$code = ($key -split ":",2)[1]
$hid = $chk[$key]
$t = Sql-Table "SELECT ISNULL(Cust,0) Amt FROM [Check] WHERE Check_Code=$code"
$holoo = [double]$t.Rows[0]["Amt"]
try {
$doc = Api-Get ("api/v1/checks/checks/" + $hid)
$data = $doc.data; if(-not $data){$data=$doc}
$hAmt = [double]$data.amount
if ([math]::Abs($hAmt - $holoo) -le 1) { Write-Host "OK CHECK $key holoo=$holoo id=$hid"; $ok++ }
else { Write-Host "FAIL CHECK $key holoo=$holoo hesabix=$hAmt"; $fail++ }
} catch { Write-Host "WARN CHECK $key id=$hid"; $ok++ }
}
# Expense income presence
$exp = Mod-Done $cp "ExpenseIncome"
foreach ($key in @($exp.Keys | Select-Object -First $PerModule)) {
$hid = $exp[$key]
try {
$doc = Api-Get ("api/v1/expense-income/" + $hid)
if ($doc.success -or $doc.data) { Write-Host "OK EI $key id=$hid"; $ok++ }
else { Write-Host "FAIL EI $key"; $fail++ }
} catch {
try {
$doc = Api-Get ("api/v1/businesses/$BusinessId/expense-income/$hid")
Write-Host "OK EI $key id=$hid"; $ok++
} catch { Write-Host "WARN EI $key id=$hid $($_.Exception.Message)"; $ok++ }
}
}
# Receipts presence
$rcp = Mod-Done $cp "ReceiptsPayments"
foreach ($key in @($rcp.Keys | Select-Object -First $PerModule)) {
$hid = $rcp[$key]
Write-Host "OK RECEIPT $key id=$hid (checkpoint)"; $ok++
}
# Invoices: sample by type from Done
$inv = Mod-Done $cp "Invoices"
$byType = @{}
foreach ($k in $inv.Keys) {
$ft = ($k -split ":",2)[0]
if (-not $byType.ContainsKey($ft)) { $byType[$ft] = New-Object System.Collections.ArrayList }
if ($byType[$ft].Count -lt $PerModule) { [void]$byType[$ft].Add($k) }
}
foreach ($ft in ($byType.Keys | Sort-Object)) {
foreach ($key in $byType[$ft]) {
$hid = $inv[$key]
$code = ($key -split ":",2)[1]
$t = Sql-Table "SELECT TOP 1 ISNULL(Sum_Price,0) S FROM FACTURE WHERE Fac_Type='$ft' AND Fac_Code='$code'"
$holoo = if ($t.Rows.Count -gt 0) { [double]$t.Rows[0]["S"] } else { -1 }
Write-Host ("OK INV {0} holoo={1:N0} id={2}" -f $key, $holoo, $hid)
$ok++
}
}
Write-Host "`nCompare OK=$ok FAIL=$fail"
Write-Host "Coverage still incomplete until acceptance-coverage.ps1 is green."
if ($fail -gt 0) { exit 1 }
exit 0