Public/Add-LedgerProfitDisposition.ps1
|
<# .SYNOPSIS Books the appropriation of profit (resultatdisposition) decided by the annual general meeting. .DESCRIPTION After the årsstämma has adopted the annual report, the previous fiscal year's result standing on the result account (2099 Årets resultat) is carried to retained earnings (2091 Balanserad vinst eller förlust), and any dividend decided is booked as a liability (2898 Outtagen vinstutdelning). This command creates that verification in the fiscal year in which the meeting is held: 2099 -<result balance> (clears the result account) 2898 -<dividend> (dividend liability, only when a dividend is decided) 2091 <result balance + dividend> The result amount is the current balance of the result account in -FiscalYear, i.e. the result carried into it by Copy-LedgerOpeningBalance. The dividend and meeting date default to the ProposedDividend and AnnualMeetingDate recorded with Set-LedgerReportInput for the year being disposed (-FromFiscalYear). The command refuses to run when the result account has no balance (the disposition has most likely been booked already) or when the dividend exceeds the disposable free equity. .PARAMETER JournalPath The path to an existing journal directory. If omitted, uses the current journal set via Set-LedgerCurrentJournal. .PARAMETER FiscalYear The fiscal year in which the annual general meeting is held and the disposition is booked (normally the year after the one being disposed). If omitted, uses the current fiscal year set via Set-LedgerCurrentFiscalYear. .PARAMETER FromFiscalYear The fiscal year whose result is disposed. Defaults to the fiscal year preceding -FiscalYear. .PARAMETER Date The date of the annual general meeting. Defaults to the AnnualMeetingDate recorded for -FromFiscalYear. .PARAMETER Dividend The dividend decided by the meeting. Defaults to the ProposedDividend recorded for -FromFiscalYear (0 when not recorded). .PARAMETER Description Description for the verification. Defaults to 'Resultatdisposition enligt årsstämma <date>'. .PARAMETER ResultAccount The result account to clear. Defaults to the journal's result account (2099 for an AB). .PARAMETER RetainedEarningsAccount The retained earnings account. Defaults to 2091. .PARAMETER DividendAccount The dividend liability account. Defaults to 2898. .EXAMPLE Add-LedgerProfitDisposition -JournalPath .\HEG.ledger -FiscalYear '2025-09_2026-08' Books the disposition of the 2024/25 result on the recorded årsstämma date with the recorded proposed dividend. .EXAMPLE Add-LedgerProfitDisposition -JournalPath .\Konsult.ledger -FiscalYear '2025-01_2025-12' ` -Date '2025-05-15' -Dividend 80000 -WhatIf Previews carrying last year's profit to 2091 and booking an 80 000 kr dividend liability on 2898. #> function Add-LedgerProfitDisposition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter()] [string]$JournalPath, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Name')] [string]$FiscalYear, [Parameter()] [string]$FromFiscalYear, [Parameter()] [datetime]$Date, [Parameter()] [ValidateRange(0, [double]::MaxValue)] [decimal]$Dividend, [Parameter()] [string]$Description, [Parameter()] [ValidatePattern('^\d+$')] [string]$ResultAccount, [Parameter()] [ValidatePattern('^\d+$')] [string]$RetainedEarningsAccount = '2091', [Parameter()] [ValidatePattern('^\d+$')] [string]$DividendAccount = '2898' ) process { $JournalPath = Resolve-LedgerJournalPath -JournalPath $JournalPath -SchemaCheck Write $FiscalYear = Resolve-LedgerFiscalYear -FiscalYear $FiscalYear -JournalPath $JournalPath $Years = @(Get-LedgerFiscalYear -JournalPath $JournalPath | Sort-Object StartDate) $Names = @($Years | ForEach-Object { $_.Name }) if ($Names -notcontains $FiscalYear) { throw "Fiscal year not found: $FiscalYear" } if (-not $FromFiscalYear) { $Index = $Names.IndexOf($FiscalYear) if ($Index -lt 1) { throw "No fiscal year precedes $FiscalYear. Specify -FromFiscalYear." } $FromFiscalYear = $Names[$Index - 1] } elseif ($Names -notcontains $FromFiscalYear) { throw "Fiscal year not found: $FromFiscalYear" } $ReportInput = Get-LedgerReportInput -JournalPath $JournalPath -FiscalYear $FromFiscalYear if (-not $PSBoundParameters.ContainsKey('Date')) { if (-not $ReportInput.AnnualMeetingDate) { throw "No AnnualMeetingDate recorded for $FromFiscalYear. Specify -Date or record it with Set-LedgerReportInput." } $Date = [datetime]::ParseExact($ReportInput.AnnualMeetingDate, 'yyyy-MM-dd', [System.Globalization.CultureInfo]::InvariantCulture) } if (-not $PSBoundParameters.ContainsKey('Dividend')) { $Dividend = if ($ReportInput.ProposedDividend) { [decimal]$ReportInput.ProposedDividend } else { [decimal]0 } } $Dividend = [Math]::Round([decimal]$Dividend, 2) if (-not $ResultAccount) { $ResultAccount = Resolve-LedgerResultCarryAccount -JournalPath $JournalPath } if (-not $Description) { $Description = "Resultatdisposition enligt årsstämma $($Date.ToString('yyyy-MM-dd'))" } $Balance = @(Get-LedgerBalance -JournalPath $JournalPath -FiscalYear $FiscalYear) $ResultRow = $Balance | Where-Object { $_.AccountNumber -eq $ResultAccount } | Select-Object -First 1 $ResultBalance = if ($ResultRow) { [Math]::Round([decimal]$ResultRow.Balance, 2) } else { [decimal]0 } if ($ResultBalance -eq 0) { throw "Result account $ResultAccount has no balance in $FiscalYear. The disposition has probably been booked already (or the opening balance has not been copied)." } # The balance on the result account should be the disposed year's result. $FromResult = @(Get-LedgerEquityReconciliation -JournalPath $JournalPath -FiscalYear $FromFiscalYear | Where-Object { $_.Component -eq 'YearResult' })[0].ClosingBalance if ($null -ne $FromResult -and [Math]::Round([decimal]$FromResult, 2) -ne -$ResultBalance) { Write-Warning "The balance on $ResultAccount ($(-$ResultBalance) as a result) differs from the result of $FromFiscalYear ($FromResult)." } if ($Dividend -gt 0) { $Disposable = (Get-LedgerProfitDisposition -JournalPath $JournalPath -FiscalYear $FromFiscalYear -Dividend $Dividend).TotalDisposable if ($Dividend -gt $Disposable) { throw "Dividend $Dividend exceeds the disposable free equity of $FromFiscalYear ($Disposable)." } } $Rows = @( @{ Account = $ResultAccount; Amount = -$ResultBalance } @{ Account = $RetainedEarningsAccount; Amount = $ResultBalance + $Dividend } ) if ($Dividend -gt 0) { $Rows += @{ Account = $DividendAccount; Amount = -$Dividend } } $Rows = @($Rows | Where-Object { $_.Amount -ne 0 }) $Result = -$ResultBalance $Action = "Book resultatdisposition of $FromFiscalYear (result $Result, dividend $Dividend)" if (-not $PSCmdlet.ShouldProcess($FiscalYear, $Action)) { return } $Entry = Add-LedgerEntry -JournalPath $JournalPath -FiscalYear $FiscalYear -Date $Date ` -Description $Description -Rows $Rows -PassThru [PSCustomObject]@{ FiscalYear = $FiscalYear FromFiscalYear = $FromFiscalYear VerificationNumber = $Entry.VerificationNumber Date = $Date Description = $Description Result = $Result Dividend = $Dividend CarriedForward = $Result - $Dividend } } } |