Public/Copy-LedgerOpeningBalance.ps1
|
<# .SYNOPSIS Copies closing balances as opening balances into a new fiscal year. .DESCRIPTION Reads the trial balance from a source fiscal year, takes all balance-sheet accounts (1xxx assets and 2xxx equity/liabilities), and writes them as the opening balance metadata (ib.txt) of the target fiscal year. The opening balance is stored as metadata, not as a verification, so verification numbering starts at ver0001 for the first real entry. The target fiscal year must not be closed. The opening balance is sealed in the target year's integrity chain. Replace it with -Force, for example after correcting the source year; the new version is sealed too, while a hand edit of ib.txt is reported by Test-LedgerIntegrity. .PARAMETER JournalPath The path to an existing journal directory. .PARAMETER FromFiscalYear The source fiscal year to read closing balances from. .PARAMETER ToFiscalYear The target fiscal year where the opening balance entry will be created. .PARAMETER Force Replaces an existing opening balance in the target fiscal year. .EXAMPLE Copy-LedgerOpeningBalance -JournalPath .\MinFirma.ledger -FromFiscalYear '2024-01_2024-12' -ToFiscalYear '2025-01_2025-12' Writes the 2025 opening balance (ib.txt) from 2024's closing balances. .EXAMPLE Close-LedgerFiscalYear -JournalPath .\MinFirma.ledger -FiscalYear '2024-01_2024-12' New-LedgerFiscalYear -JournalPath .\MinFirma.ledger -StartDate '2025-01-01' -EndDate '2025-12-31' Copy-LedgerOpeningBalance -JournalPath .\MinFirma.ledger -FromFiscalYear '2024-01_2024-12' -ToFiscalYear '2025-01_2025-12' Typical year-end workflow: close old year, create new, copy balances. .EXAMPLE Add-LedgerEntry -JournalPath .\MinFirma.ledger -FiscalYear '2024-01_2024-12' -Date '2024-12-31' ` -Description 'Periodisering hyra' -Rows @( @{ Account = '1710'; Amount = 12000 } @{ Account = '5010'; Amount = -12000 } ) Copy-LedgerOpeningBalance -JournalPath .\MinFirma.ledger -FromFiscalYear '2024-01_2024-12' -ToFiscalYear '2025-01_2025-12' -Force Replaces a preliminary 2025 opening balance after a late adjustment in 2024. #> function Copy-LedgerOpeningBalance { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter()] [string]$JournalPath, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Name')] [string]$FromFiscalYear, [Parameter(Mandatory)] [string]$ToFiscalYear, [Parameter()] [switch]$Force ) process { $JournalPath = Resolve-LedgerJournalPath -JournalPath $JournalPath -SchemaCheck Write $journalLock = $null try { $journalLock = Enter-LedgerJournalLock -JournalPath $JournalPath Assert-LedgerJournalSchema -Path $JournalPath -Write $FromFiscalYear = Resolve-LedgerFiscalYear -FiscalYear $FromFiscalYear -JournalPath $JournalPath # Validate source fiscal year $FromDir = Join-Path $JournalPath $FromFiscalYear if (-not (Test-Path $FromDir -PathType Container)) { throw "Source fiscal year not found: $FromFiscalYear" } # Validate target fiscal year $ToDir = Join-Path $JournalPath $ToFiscalYear if (-not (Test-Path $ToDir -PathType Container)) { throw "Target fiscal year not found: $ToFiscalYear" } Assert-LedgerFiscalYearOpen -YearDir $ToDir -FiscalYear $ToFiscalYear -Action 'change its opening balance' # Check target has no opening balance yet $ExistingIb = Get-LedgerOpeningBalancePath -YearDir $ToDir if (-not $Force -and (Test-Path $ExistingIb -PathType Leaf)) { throw "Target fiscal year $ToFiscalYear already has an opening balance (ib.txt). Use -Force to replace it." } # Get balance accounts from source year $Balance = Get-LedgerBalance -JournalPath $JournalPath -FiscalYear $FromFiscalYear if (-not $Balance) { throw "No entries found in source fiscal year $FromFiscalYear." } # Filter to balance sheet accounts (1xxx and 2xxx) $BalanceAccounts = $Balance | Where-Object { $_.AccountNumber -match '^[12]' -and $_.Balance -ne 0 } # Calculate year's result from P&L accounts (3xxx-8xxx) and carry it into # the equity result account. The account depends on the journal's # CompanyType (AB -> 2099, EF -> 2019), falling back to 2099. $PLAccounts = $Balance | Where-Object { $_.AccountNumber -match '^[3-8]' } $YearResult = if ($PLAccounts) { ($PLAccounts | Measure-Object -Property Balance -Sum).Sum } else { [decimal]0 } if (-not $BalanceAccounts -and $YearResult -eq 0) { throw "No balance sheet accounts with non-zero balances in $FromFiscalYear." } # Merge year's result into the equity result account if ($YearResult -ne 0) { $ResultAccount = Resolve-LedgerResultCarryAccount -JournalPath $JournalPath $ExistingResult = $BalanceAccounts | Where-Object { $_.AccountNumber -eq $ResultAccount } if ($ExistingResult) { $BalanceAccounts = $BalanceAccounts | Where-Object { $_.AccountNumber -ne $ResultAccount } $YearResult += $ExistingResult.Balance } $BalanceAccounts = @($BalanceAccounts) + @([PSCustomObject]@{ AccountNumber = $ResultAccount AccountName = 'Årets resultat' Debit = [decimal]0 Credit = [decimal]0 Balance = $YearResult }) } if (-not $BalanceAccounts) { throw "No balance sheet accounts with non-zero balances in $FromFiscalYear." } # Write the opening balance as metadata (ib.txt), not as a verification. $IbRows = foreach ($Acc in $BalanceAccounts) { [PSCustomObject]@{ Account = $Acc.AccountNumber; Amount = $Acc.Balance } } if ($PSCmdlet.ShouldProcess($ToFiscalYear, "Copy opening balance from $FromFiscalYear")) { Write-LedgerOpeningBalance -YearDir $ToDir -Rows $IbRows Register-LedgerYearMetadata -YearDir $ToDir -Name 'ib.txt' } } finally { Exit-LedgerJournalLock -Lock $journalLock } } } |