P3: depreciation straight-line by days through the final month, schedules by day (defects 22, 9, D-37)

The final month takes what the months before leave, spread over its days;
a disposed asset stops on its disposal day. A skipped month is caught up
in the month the run is made; a reversed run un-posts its month. New
schedules spread by day; equal-months schedules must start on the 1st.
Amounts round to the currency's own minor unit. Kani and Lean proofs; an
exhaustive search over runs, reversals and disposals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-21 14:04:11 -06:00
1 parent 1304b9c0ad
commit b0a9fd8ad4
69 files changed
+10529 -841

No files matched your search

+19 -1
View File
@@ -419,10 +419,28 @@ pub enum LedgerError {
#[error("asset account links must be distinct; account id {0} is linked twice")]
DuplicateAssetAccount(u64),
/// purchase_date + useful life overflows the date range.
/// purchase_date + useful life overflows the date range: a new asset's
/// last day of depreciation is 9999-12-31 at the latest.
#[error("purchase date plus useful life overflows the calendar")]
AssetDateOverflow,
/// A depreciation run for a month that can't be run: not a month, or
/// one ending before the asset was placed in service.
#[error("invalid depreciation period: {0}")]
InvalidDepreciationPeriod(String),
/// An entry of a fixed asset's that can't be reversed (its disposal,
/// or depreciation the disposal took as final), with why.
#[error("entry {0} can't be reversed: {1}")]
AssetEntryIrreversible(u64, String),
/// A disposal refused because a depreciation run of the asset carries
/// at the end of the disposal's month other than what it carries now
/// (a run of a later month that stands; a reversal or re-instatement
/// dated after the month, not undone), with what to do.
#[error("the disposal is dated before depreciation the books carry: {0}")]
DepreciationPastDisposal(String),
/// An amortization schedule or recurring entry is invalid, unknown, or
/// already posted for that date.
#[error("invalid schedule: {0}")]