Public/Add-LedgerEntry.ps1
|
<# .SYNOPSIS Creates a new verification (journal entry) in a fiscal year. .DESCRIPTION Creates a sequentially numbered verification file (ver0001.txt, ver0002.txt, etc.) in the specified fiscal year directory. Enforces double-entry bookkeeping by requiring that the sum of all row amounts equals zero. .PARAMETER JournalPath The path to an existing journal directory. .PARAMETER FiscalYear The fiscal year identifier (e.g. '2024-01_2024-12'). Must match an existing fiscal year directory. .PARAMETER Date The date of the transaction. .PARAMETER Description A description of the transaction. .PARAMETER Rows An array of hashtables, each with 'Account' (account number) and 'Amount' (positive for debit, negative for credit). The sum of all amounts must be zero, and each amount may have at most two decimals (whole öre). Each row may optionally include a 'Comment' key with free-text describing that specific row. Rows can be supplied as an array or piped in (for example from New-LedgerEntryRow); piped rows are collected into a single verification. .PARAMETER Attachment One or more paths to files to attach to the newly created verification (e.g. a receipt or invoice). All files must exist; they are validated before the verification is written. Delegates to Add-LedgerAttachment. .PARAMETER PassThru If specified, returns an object describing the created verification, including its number, fiscal year, file path and any attached files. By default the command produces no output. .EXAMPLE $rows = @( @{ Account = '1910'; Amount = 5000 } @{ Account = '3010'; Amount = -5000 } ) Add-LedgerEntry -JournalPath .\MinFirma.ledger -FiscalYear '2024-01_2024-12' -Date '2024-03-15' -Description 'Kontantförsäljning' -Rows $rows Records a cash sale: debit 1910 (Kassa), credit 3010 (Försäljning). .EXAMPLE $rows = @( @{ Account = '5010'; Amount = 8000 } @{ Account = '2640'; Amount = 2000 } @{ Account = '2440'; Amount = -10000 } ) Add-LedgerEntry -JournalPath .\MinFirma.ledger -FiscalYear '2024-01_2024-12' -Date '2024-03-20' -Description 'Hyra kontor' -Rows $rows -Attachment .\hyresfaktura.pdf, .\betalbevis.pdf -PassThru Records a supplier invoice for office rent (8000 plus 25 % VAT): debit 5010 (Lokalhyra) and 2640 (Ingående moms), credit 2440 (Leverantörsskulder). Attaches two files to the verification and returns the created verification object. .EXAMPLE @( New-LedgerEntryRow -Debit '1910' 5000 New-LedgerEntryRow -Credit '3010' 5000 ) | Add-LedgerEntry -JournalPath .\MinFirma.ledger -FiscalYear '2024-01_2024-12' -Date '2024-03-15' -Description 'Kontantförsäljning' Builds rows with New-LedgerEntryRow and pipes them straight into Add-LedgerEntry, avoiding the signed-amount hashtable syntax. #> function Add-LedgerEntry { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', Justification = 'Write-LedgerVerification performs validation and ShouldProcess; WhatIf and Confirm are forwarded.')] [CmdletBinding(SupportsShouldProcess)] param ( [Parameter()] [string]$JournalPath, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Name')] [string]$FiscalYear, [Parameter(Mandatory)] [datetime]$Date, [Parameter(Mandatory)] [string]$Description, [Parameter(Mandatory, ValueFromPipeline)] [hashtable[]]$Rows, [Parameter()] [string[]]$Attachment, [Parameter()] [switch]$PassThru ) begin { # Rows supplied on the command line are present in $PSBoundParameters # during begin; rows arriving via the pipeline are not yet bound, so this # flag distinguishes "New-LedgerEntryRow | Add-LedgerEntry" (accumulate # into one verification) from the parameter/fiscal-year-pipeline usage. $RowsFromPipeline = -not $PSBoundParameters.ContainsKey('Rows') $RowBuffer = [System.Collections.Generic.List[hashtable]]::new() $WriterOptions = @{} foreach ($option in 'WhatIf', 'Confirm') { if ($PSBoundParameters.ContainsKey($option)) { $WriterOptions[$option] = $PSBoundParameters[$option] } } $WriteEntry = { param([hashtable[]]$EntryRows) Write-LedgerVerification -JournalPath $JournalPath -FiscalYear $FiscalYear ` -Date $Date -Description $Description -Rows $EntryRows -Attachment $Attachment -PassThru:$PassThru @WriterOptions } } process { if ($RowsFromPipeline) { foreach ($Row in $Rows) { $RowBuffer.Add($Row) } } else { & $WriteEntry $Rows } } end { if ($RowsFromPipeline) { & $WriteEntry $RowBuffer.ToArray() } } } |