moonbit-accounting

Generate financial statements from normalized accounting entries.

accounting
financial-report
ledger
moonbit
moon add mhlagent/moonbit-accounting@0.2.0
Download zip
Author
Version
0.2.0
License
Apache-2.0
Last updated
3 hours ago
Downloads
2
README

#moonbit-accounting

Deterministic financial reporting for MoonBit applications. It accepts normalized entries and explicit mappings, then produces stable reports.

///|
test "readme example" {
let mappings = [AccountMapping::new("sales", "Revenue", IncomeStatement)]
let entries = [Entry::new("sales", "2026-Q2", 0, 1200)]
let report = generate(IncomeStatement, "2026-Q2", entries, mappings)
assert_eq(report.total, 1200)
assert_eq(report.line("Revenue"), Some(1200))
}

Amounts are integer minor units. Reports can be rendered as CSV, JSON, Markdown, or HTML. Validation, comparison periods, dimensions, budgets, consolidation, ratios, trends, anomaly detection, and account catalogues are available from the same dependency-free package.

moon check --target all --deny-warn moon test --target all moon run cmd/main

See README.md for architecture, CLI, benchmark, CI, and license details.

#
Amount

type Amount = Int

A signed amount in the smallest currency unit (for example, cents).

#
AccountClass

pub enum AccountClass {
Asset
Liability
Equity
Revenue
Expense
} derive(Eq,
Debug
)

A compact standard chart helps applications bootstrap mappings.

#
AccountDefinition

pub struct AccountDefinition {
code : String
name : String
class : AccountClass
normal_debit : Bool
} derive(Eq,
Debug
)

#
AccountDefinition::new

fn AccountDefinition::new(code : String, name : String, class : AccountClass, normal_debit : Bool) -> AccountDefinition

#
AccountMapping

pub struct AccountMapping {
account : String
line : String
kind : StatementKind
factor : Int
} derive(Eq,
Debug
)

#
AccountMapping::new

fn AccountMapping::new(account : String, line : String, kind : StatementKind, factor? : Int) -> AccountMapping

#
Anomaly

pub struct Anomaly {
kind : AnomalyKind
account : String
period : String
amount : Int
detail : String
} derive(Eq,
Debug
)

#
AnomalyKind

pub(all) enum AnomalyKind {
LargeDebit
LargeCredit
UnmappedAccount
InvalidPeriod
DuplicateEntry
} derive(Eq,
Debug
)

#
BatchValidation

pub enum BatchValidation {
BalancedBatch
UnbalancedBatch(Int)
EmptyBatch
} derive(Eq,
Debug
)

#
BenchmarkResult

pub struct BenchmarkResult {
entries : Int
mappings : Int
lines : Int
total : Int
elapsed_ms : Int
} derive(Eq,
Debug
)

Deterministic fixture generation keeps benchmark comparisons meaningful.

#
BudgetLine

pub struct BudgetLine {
line : String
amount : Int
} derive(Eq,
Debug
)

#
BudgetLine::new

fn BudgetLine::new(line : String, amount : Int) -> BudgetLine

#
BudgetVariance

pub struct BudgetVariance {
line : String
budget : Int
actual : Int
variance : Int
favorable : Bool
} derive(Eq,
Debug
)

#
CashFlowKind

pub(all) enum CashFlowKind {
Operating
Investing
Financing
Unclassified
} derive(Eq,
Debug
)

#
CashFlowLine

pub struct CashFlowLine {
kind : CashFlowKind
amount : Int
entries : Int
} derive(Eq,
Debug
)

#
CashFlowRule

pub struct CashFlowRule {
account : String
kind : CashFlowKind
factor : Int
} derive(Eq,
Debug
)

#
CashFlowRule::new

fn CashFlowRule::new(account : String, kind : CashFlowKind, factor? : Int) -> CashFlowRule

#
Currency

pub struct Currency {
code : String
name : String
minor_units : Int
} derive(Eq,
Debug
)

ISO-like currency metadata used by callers that need explicit scale.

#
Currency::new

fn Currency::new(code : String, name : String, minor_units : Int) -> Currency

#
DimensionLine

pub struct DimensionLine {
dimension : String
amount : Int
entries : Int
} derive(Eq,
Debug
)

#
Entity

pub struct Entity {
name : String
entries : Array[Entry]
} derive(Eq,
Debug
)

#
Entity::new

fn Entity::new(name : String, entries : Array[Entry]) -> Entity

#
Entry

pub struct Entry {
account : String
period : String
debit : Int
credit : Int
cash : Bool
dimension : String
} derive(Eq,
Debug
)

#
Entry::new

fn Entry::new(account : String, period : String, debit : Int, credit : Int, cash? : Bool) -> Entry

#
Entry::new_with_dimension

fn Entry::new_with_dimension(account : String, period : String, debit : Int, credit : Int, dimension : String, cash? : Bool) -> Entry

#
HealthScore

pub struct HealthScore {
liquidity : Int
profitability : Int
leverage : Int
overall : Int
} derive(Eq,
Debug
)

#
LineItem

pub struct LineItem {
line : String
amount : Int
entries : Int
} derive(Eq,
Debug
)

#
MappingValidation

pub enum MappingValidation {
ValidMappings
DuplicateAccount(String)
} derive(Eq,
Debug
)

#
PeriodResult

pub enum PeriodResult {
ValidPeriod(String)
InvalidPeriod(String)
} derive(Eq,
Debug
)

#
RatioSet

pub struct RatioSet {
current_ratio : Int?
quick_ratio : Int?
gross_margin : Int?
operating_margin : Int?
debt_ratio : Int?
return_on_assets : Int?
} derive(Eq,
Debug
)

Financial analysis primitives operate on integer minor units.

#
Report

pub struct Report {
kind : StatementKind
period : String
lines : Array[LineItem]
total : Int
} derive(Eq,
Debug
)

#
Report::line

fn Report::line(self : Report, name : String) -> Int?

#
Report::to_csv

fn Report::to_csv(self : Report) -> String

#
Report::to_html

fn Report::to_html(self : Report) -> String

#
Report::to_json

fn Report::to_json(self : Report) -> String

#
Report::to_markdown

fn Report::to_markdown(self : Report) -> String

#
ReportComparison

pub struct ReportComparison {
current : Report
prior : Report
total_variance : Int
} derive(Eq,
Debug
)

#
StatementKind

pub(all) enum StatementKind {
BalanceSheet
IncomeStatement
CashFlowStatement
Management
} derive(Eq,
Debug
)

#
TrendPoint

pub struct TrendPoint {
period : String
amount : Int
change : Int
direction : String
} derive(Eq,
Debug
)

#
Variance

pub struct Variance {
line : String
current : Int
prior : Int
absolute : Int
percent : Int?
} derive(Eq,
Debug
)

#
analyze_ratios

fn analyze_ratios(assets : Int, current_assets : Int, inventory : Int, liabilities : Int, revenue : Int, cost : Int, operating_expense : Int, net_income : Int) -> RatioSet

#
benchmark_fixture

fn benchmark_fixture(size : Int) -> (Array[Entry], Array[AccountMapping])

#
benchmark_summary

fn benchmark_summary(result : BenchmarkResult) -> String

#
budget_variance

fn budget_variance(budget : Array[BudgetLine], actual : Array[BudgetLine]) -> Array[BudgetVariance]

#
cash_flow

fn cash_flow(period : String, entries : Array[Entry], rules : Array[CashFlowRule]) -> Array[CashFlowLine]

#
compare_period

fn compare_period(left : String, right : String) -> Int

#
compare_reports

fn compare_reports(kind : StatementKind, current_period : String, prior_period : String, entries : Array[Entry], mappings : Array[AccountMapping]) -> ReportComparison

#
compound_change

fn compound_change(first : Int, last : Int, periods : Int) -> Int?

#
consolidate

fn consolidate(period : String, entities : Array[Entity], mappings : Array[AccountMapping]) -> Report

#
convert_minor

fn convert_minor(amount : Int, from : Currency, to : Currency, rate_numerator : Int, rate_denominator : Int) -> Int?

#
currency

fn currency(code : String) -> Currency?

#
currency_codes

fn currency_codes() -> Array[String]

#
detect_invalid_periods

fn detect_invalid_periods(entries : Array[Entry]) -> Array[Anomaly]

#
detect_large_entries

fn detect_large_entries(entries : Array[Entry], threshold : Int) -> Array[Anomaly]

#
detect_unmapped

fn detect_unmapped(entries : Array[Entry], mappings : Array[AccountMapping]) -> Array[Anomaly]

#
escape_html

fn escape_html(value : String) -> String

Escape text for HTML contexts without relying on a runtime or DOM.

#
extended_chart

fn extended_chart() -> Array[AccountDefinition]

A deterministic, broad account directory for importers and mapping UIs. Each record has a stable code, display name, normal balance, and class.

#
extended_chart_for_class

fn extended_chart_for_class(class : AccountClass) -> Array[AccountDefinition]

#
find_extended_account

fn find_extended_account(code : String) -> AccountDefinition?

#
generate

fn generate(kind : StatementKind, period : String, entries : Array[Entry], mappings : Array[AccountMapping], comparison? : String) -> Report

#
generate_by_dimension

fn generate_by_dimension(kind : StatementKind, period : String, entries : Array[Entry], mappings : Array[AccountMapping]) -> Array[DimensionLine]

#
generate_many

fn generate_many(kind : StatementKind, periods : Array[String], entries : Array[Entry], mappings : Array[AccountMapping]) -> Array[Report]

Build a stable report for each requested period.

#
health_score

fn health_score(ratios : RatioSet) -> HealthScore

#
latest_report

fn latest_report(reports : Array[Report]) -> Report?

#
lowest_report

fn lowest_report(reports : Array[Report]) -> Report?

#
moving_average

fn moving_average(values : Array[Int], window : Int) -> Array[Int]

#
period_delta

fn period_delta(reports : Array[Report]) -> Array[Int]

#
period_totals

fn period_totals(reports : Array[Report]) -> Array[(String, Int)]

#
regional_chart

fn regional_chart() -> Array[AccountDefinition]

Regional account templates support multi-entity setup without a database.

#
regional_chart_for_region

fn regional_chart_for_region(region : String) -> Array[AccountDefinition]

#
regional_chart_size

fn regional_chart_size() -> Int

#
render_variances

fn render_variances(variances : Array[Variance]) -> String

#
report_document

fn report_document(report : Report, title : String) -> String

#
report_variances

fn report_variances(current : Report, prior : Report) -> Array[Variance]

#
run_benchmark

fn run_benchmark(size : Int) -> BenchmarkResult

#
safe_ratio

fn safe_ratio(numerator : Int, denominator : Int) -> Int?

#
standard_account

fn standard_account(code : String) -> AccountDefinition?

#
standard_chart

fn standard_chart() -> Array[AccountDefinition]

#
trend_points

fn trend_points(values : Array[(String, Int)]) -> Array[TrendPoint]

#
validate_batch

fn validate_batch(entries : Array[Entry]) -> BatchValidation

#
validate_mappings

fn validate_mappings(mappings : Array[AccountMapping]) -> MappingValidation

#
validate_period

fn validate_period(period : String) -> PeriodResult

#
variance

fn variance(line : String, current : Int, prior : Int) -> Variance

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io