From 5fad8881e6b791154655c9af42f7e2e46e6aca22 Mon Sep 17 00:00:00 2001 From: "@royashbrook" Date: Mon, 19 Oct 2026 16:01:43 -0400 Subject: [PATCH] preserve invoice and detail input order (refs #29) --- DataAgent/CAPABILITIES.md | 2 ++ DataAgent/fmt/pdi.ps1 | 9 ++++----- tests/invoice-formats.ps1 | 12 ++++++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/DataAgent/CAPABILITIES.md b/DataAgent/CAPABILITIES.md index a9ed604..6e1c978 100644 --- a/DataAgent/CAPABILITIES.md +++ b/DataAgent/CAPABILITIES.md @@ -51,6 +51,8 @@ owned options are the keys the adapter interprets itself. other arguments belong ## custom adapters +invoice groups keep their first-seen order, and each invoice's details keep their input order. the source owns any sorting. pdi no longer sorts invoices by key or moves D records before I records. grouping still puts an invoice's rows together if the source interleaves invoice keys. + invoice substitutions without a format preserve PowerShell's string interpolation, including dates and numbers. alignment pads that string. an explicit `:format` instead formats the original typed value using .NET's current-culture formatting. set `adapter` to a `.ps1` path, relative to the job directory or absolute. no registration or core edit. each script receives `-Data` and `-Options`: diff --git a/DataAgent/fmt/pdi.ps1 b/DataAgent/fmt/pdi.ps1 index b35a00a..fd2afe4 100644 --- a/DataAgent/fmt/pdi.ps1 +++ b/DataAgent/fmt/pdi.ps1 @@ -3,12 +3,11 @@ param($Data, [hashtable] $Options) $Options = Get-InvoiceOptions $Options pdi $rows = @(Get-InvoiceRows $Data) & { - foreach ($head in ($rows | Select-Object -Property $Options.Head -Unique | Sort-Object $Options.Key)) { + foreach ($head in ($rows | Select-Object -Property $Options.Head -Unique)) { Expand-InvoiceLine $Options.H $head $Options.Values - $lines = @($rows | Where-Object -Property $Options.Key -EQ -Value $head.($Options.Key)) - foreach ($row in ($lines | Where-Object -Property $Options.Type -EQ -Value 'd')) { Expand-InvoiceLine $Options.D $row $Options.Values } - if ($Options.I) { - foreach ($row in ($lines | Where-Object -Property $Options.Type -EQ -Value 'i')) { Expand-InvoiceLine $Options.I $row $Options.Values } + foreach ($row in ($rows | Where-Object -Property $Options.Key -EQ -Value $head.($Options.Key))) { + if ($row.($Options.Type) -eq 'd') { Expand-InvoiceLine $Options.D $row $Options.Values } + elseif ($row.($Options.Type) -eq 'i' -and $Options.I) { Expand-InvoiceLine $Options.I $row $Options.Values } } } } | Set-Content -LiteralPath $Options.Path -Encoding utf8NoBOM diff --git a/tests/invoice-formats.ps1 b/tests/invoice-formats.ps1 index 694814a..9d224fa 100644 --- a/tests/invoice-formats.ps1 +++ b/tests/invoice-formats.ps1 @@ -35,14 +35,18 @@ $null = $table.Rows.Add(@('A','20261014','3','i','','C','','','1','0','1','1','F $null = $table.Rows.Add(@('A','20261014','3','d','A1','C','DSL','','1','2','2','2','FRT')) $lines = Format pdi @($table.Rows) @{Values=@{sender_id='SYN'}} $expected = @( - '"H","SYN","A","20261014",,,,,,"3","N"' - '"D","A1","C","DSL","","SYN",,"1","2","2",,"2",' - '"I","FSC","1",' '"H","SYN","B","20261014",,,,,,"2","N"' '"D","B1","C","DSL","note, one","SYN",,"1","2","2",,"2",' + '"H","SYN","A","20261014",,,,,,"3","N"' + '"I","FSC","1",' + '"D","A1","C","DSL","","SYN",,"1","2","2",,"2",' ) $expected | Set-Content "$root/expected.txt" -Encoding utf8NoBOM -Check ((Get-FileHash "$root/pdi.txt").Hash -ceq (Get-FileHash "$root/expected.txt").Hash) 'pdi DataRow input has exact H/D/I bytes, sorted invoices and D before I' +Check ((Get-FileHash "$root/pdi.txt").Hash -ceq (Get-FileHash "$root/expected.txt").Hash) 'pdi preserves first-seen invoice order and interleaved detail order byte for byte' +$lines = Format pdi @($table.Rows[2], $table.Rows[1], $table.Rows[0]) @{Values=@{sender_id='SYN'}} +Check (($lines -join '|') -ceq (($expected[2], $expected[4], $expected[3], $expected[0], $expected[1]) -join '|')) 'pdi already-sorted invoices and D-before-I input remain unchanged' +$lines = Format pdi @($table.Rows) @{Values=@{sender_id='SYN'};I=''} +Check (($lines -join '|') -ceq (($expected[0], $expected[1], $expected[2], $expected[4]) -join '|')) 'pdi can still omit I records without reordering the rest' $lines = Format pdi @([pscustomobject]@{id='A';kind='d';amount=2}) @{Key='id';Head='id';Type='kind';H='H,{id}';D='D,{amount:0.00}';I=''} Check (($lines -join '|') -ceq 'H,A|D,2.00') 'pdi record selectors and whole templates can be replaced'