Skip to content

Alpha Version - #1

Merged
gocanto merged 84 commits into
mainfrom
chore/money
Dec 15, 2025
Merged

gocanto merged 84 commits into
mainfrom
chore/money

Conversation

@gocanto

@gocanto gocanto commented Dec 6, 2025

Copy link
Copy Markdown
Owner

No description provided.

@gocanto gocanto changed the title wip Framework Dec 6, 2025
@gocanto
gocanto marked this pull request as ready for review December 6, 2025 08:44
@gocanto
gocanto marked this pull request as draft December 6, 2025 08:46
@gocanto
gocanto marked this pull request as ready for review December 6, 2025 08:46
@coderabbitai

coderabbitai Bot commented Dec 6, 2025 •

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added comprehensive currency management with support for multiple currencies and numeric codes.
    • Introduced money factory functions for convenient creation across 200+ currencies.
    • Added currency exchange conversion with rate management.
    • Implemented decimal amount parser supporting multiple formats and separators.
    • Added database serialization for Money values.
  • Refactor

    • Reorganised codebase into modular packages: calculator, currency, exchange, parser, and format for improved maintainability.
  • Documentation

    • Updated README with project overview and guidance.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Restructures the repository into focused packages (calculator, currency, exchange, parser, exception, format, money), removes legacy base/ files, adds Manager and Converter abstractions, implements DB/JSON hooks, extensive factory and aggregator helpers, introduces comprehensive tests and CI workflows, and adds tooling/Makefile and .gitignore updates.

Changes

Cohort / File(s) Summary
Build & Repo config
\.gitignore`, `Makefile``
Update ignore rules for build artifacts and binaries; add Makefile with targets for tests, pretty-test, format, build-examples and run-examples with per-package reporting.
Documentation
\README.md``
Replace README content and rename project header to "Money".
CI / GitHub workflows
\.github/FUNDING.yml`, `.github/workflows/gofmt.yml`, `.github/workflows/tests.yml``
Add funding file; add Go formatting workflow (auto-commit for same-repo PRs); add tests workflow with per-package coverage and Go version matrix.
Removed legacy base/
Removed files:
\base/.go`, `base/.go (tests/examples)``
Delete legacy base implementation and tests (calculator.go, money.go, mutator.go, db.go, tests and examples).
New calculator package
\calculator/calculator.go`, `calculator/ration.go`, `calculator/*.go (tests)``
Add Amount alias, Calculator type with Add/Subtract/Multiply/Divide/Modulus/Allocate/Absolute/Negative/Round, plus SafeAdd/Ration/SafeMultiply helpers and corresponding tests.
New exception package
\exception/exception.go`, `exception/exception_test.go``
Introduce sentinel errors (many exported), All() enumerator and NewErrInvalidJSONUnmarshalFrom wrapper; tests validate messages, uniqueness and wrapping.
New exchange package
\exchange/exchange.go`, `exchange/converter.go`, `exchange/*_test.go``
Add concurrency-safe Exchange with AddRate/GetRate/ConvertAmount/ConvertAmountWithRate and Converter wrapper; include inverse-rate lookup and concurrency tests.
New parser package
\parser/parser.go`, `parser/parser_test.go``
Add Parser to parse amounts with multi-locale support (decimal/comma handling, thousands validation), currency detection (symbols/ISO), and helpers; tests exercise many formats and edge cases.
Currency package
\currency/.go`, `currency/_test.go``
New Currency type with Formatter/DbValue/DbScan, Map and Manager for dataset/singleton handling, ISOCodePattern, Provider (DefaultProvider), dataset and extensive tests.
Format package
\format/format.go`, `format/format_test.go``
Move/adjust Formatter implementation (package renamed to format), change abs receiver to pointer; tests extended for many formatting scenarios.
Money package core
\money/type.go`, `money/money.go`, `money/manager.go`, `money/db.go`, `money/exchange.go`, `money/json.go`, `money/aggregator.go`, `money/factory.go``
Add Money struct (amount, currency), Manager coordinating parser/currency/calculator, DB Value/Scan with configurable separator, Converter integration, JSON marshal/unmarshal framework with pluggable hooks, Aggregator (Sum/Min/Max/Avg), and ~170 From factory functions.
Money tests & helpers
\money/*_test.go`, `money/test_helpers_test.go``
Add extensive unit tests covering Money, Manager, Converter, JSON, DB round-trips, aggregator, factories and concurrency; test helpers for require semantics.
Examples / Misc
\main.go``
Remove trivial main program ("Hello, World!").

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Caller
    participant Manager as money.Manager
    participant Parser
    participant CurrencyMgr as currency.Manager
    participant Exchange
    participant Calculator

    Caller->>Manager: CreateFromString("1,234.56", "USD")
    Manager->>Parser: ParseAmount("1,234.56", "USD")
    Parser-->>Manager: (amountFloat, "USD")
    Manager->>CurrencyMgr: Resolve("USD")
    CurrencyMgr-->>Manager: *Currency (fraction=2)
    Manager->>Calculator: Parse float -> minor units (int64) using fraction
    Calculator-->>Manager: amount (int64)
    Manager-->>Caller: *Money(amount, currency)

    Caller->>Manager: Convert(money, "EUR")
    Manager->>Exchange: GetRate("USD","EUR")
    Exchange-->>Manager: rate (float64)
    Manager->>Calculator: ConvertAmount(amount,int fractions,rate)
    Calculator-->>Manager: convertedAmount (int64)
    Manager->>CurrencyMgr: Resolve("EUR")
    Manager-->>Caller: *Money(convertedAmount, EUR)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Areas to prioritise during review:

  • Calculator overflow/edge-case logic (SafeAdd, Ration, SafeMultiply, Round).
  • Exchange concurrency (nested map writes/reads and lock discipline).
  • Parser ambiguity resolution for comma-only inputs and thousands-grouping validation.
  • Currency Map/Manager singleton initialisation (NewCurrenciesMap / NewCurrenciesMapFrom) and sync.Once usage.
  • Money Manager CreateFromString precision, sign handling and fraction conversion.
  • DB Value/Scan thread-safety when changing separator (SetDBMoneyValueSeparator).
  • JSON (un)marshal hook safety, default behaviour and error wrapping.
  • Large number of factory functions for correctness and potential duplicate code issues.

Possibly related PRs

  • WorK on CI oullin/api#19 — Adds the same .github/FUNDING.yml and a Go formatting workflow; relates to repository meta-configuration and CI formatting changes.

Pre-merge checks and finishing touches

❌ Failed checks (2 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Alpha Version' is vague and generic, using a non-descriptive term that does not convey meaningful information about the changeset's primary purpose or scope. Replace with a specific, descriptive title that summarises the main change, such as 'Refactor money package with new architecture' or 'Restructure codebase with calculator, currency, and exchange packages'.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to assess whether the description relates to the changeset. Add a detailed pull request description explaining the objectives, scope of changes, and any breaking changes or migration notes for reviewers.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d6c94d and 51026f6.

📒 Files selected for processing (32)
  • .github/workflows/gofmt.yml (1 hunks)
  • .github/workflows/tests.yml (1 hunks)
  • calculator/calculator.go (1 hunks)
  • calculator/calculator_test.go (1 hunks)
  • calculator/ration.go (1 hunks)
  • calculator/ration_test.go (1 hunks)
  • currency/currency.go (1 hunks)
  • currency/dataset.go (1 hunks)
  • currency/iso.go (1 hunks)
  • currency/iso_test.go (1 hunks)
  • currency/manager.go (1 hunks)
  • currency/map.go (1 hunks)
  • currency/metal.go (1 hunks)
  • currency/uat_test.go (1 hunks)
  • exception/exception.go (1 hunks)
  • exception/exception_test.go (1 hunks)
  • exchange/converter.go (1 hunks)
  • exchange/exchange_test.go (1 hunks)
  • money/aggregator.go (1 hunks)
  • money/aggregator_test.go (1 hunks)
  • money/exchange.go (1 hunks)
  • money/exchange_test.go (1 hunks)
  • money/factory.go (1 hunks)
  • money/factory_test.go (1 hunks)
  • money/json.go (1 hunks)
  • money/json_test.go (1 hunks)
  • money/manager.go (1 hunks)
  • money/manager_test.go (1 hunks)
  • money/money.go (1 hunks)
  • money/money_test.go (1 hunks)
  • parser/parser.go (1 hunks)
  • parser/parser_test.go (1 hunks)

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 32

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
money/db.go (1)

25-69: Add support for []byte input in Money.Scan to handle database drivers that pass textual columns as bytes

The current Scan implementation only accepts string types, but many database/sql drivers (including go-sql-driver/mysql and lib/pq) pass textual column values as []byte. This causes scanning to fail with valid data like "1234|USD" from TEXT/VARCHAR columns, even though the content is correct.

The Currency.DbScan method has the same limitation. To fix, add a []byte case to the type switch that converts to string first:

-	switch src.(type) {
-	case string:
-		parts := strings.Split(src.(string), DBMoneyValueSeparator)
+	switch v := src.(type) {
+	case string:
+		parts = strings.Split(v, DBMoneyValueSeparator)
+	case []byte:
+		parts = strings.Split(string(v), DBMoneyValueSeparator)

Move the validation and remaining logic outside the switch. This preserves error messages while supporting both string and []byte inputs from real-world database drivers.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f0cb27 and 4c86b8a.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (41)
  • .gitignore (1 hunks)
  • Makefile (1 hunks)
  • README.md (1 hunks)
  • base/Makefile (0 hunks)
  • base/calculator.go (0 hunks)
  • base/currency_test.go (0 hunks)
  • base/db_test.go (0 hunks)
  • base/money.go (0 hunks)
  • base/money_example_test.go (0 hunks)
  • base/money_test.go (0 hunks)
  • base/mutator.go (0 hunks)
  • calculator/calculator.go (1 hunks)
  • calculator/calculator_test.go (1 hunks)
  • currencies/constants.go (4 hunks)
  • currencies/currency.go (1 hunks)
  • currencies/type.go (5 hunks)
  • exception/exception.go (1 hunks)
  • exchange/converter.go (1 hunks)
  • exchange/exchange.go (1 hunks)
  • exchange/tests/converter_test.go (1 hunks)
  • exchange/tests/exchange_test.go (1 hunks)
  • exchange/type.go (1 hunks)
  • formatter/formatter.go (3 hunks)
  • formatter/formatter_test.go (9 hunks)
  • main.go (0 hunks)
  • money/aggregator.go (1 hunks)
  • money/db.go (3 hunks)
  • money/exchange.go (1 hunks)
  • money/factory.go (1 hunks)
  • money/json.go (1 hunks)
  • money/money.go (1 hunks)
  • money/tests/aggregator_test.go (1 hunks)
  • money/tests/db_test.go (1 hunks)
  • money/tests/exchange_test.go (1 hunks)
  • money/tests/extreme_edge_cases_test.go (1 hunks)
  • money/tests/factory_test.go (1 hunks)
  • money/tests/money_methods_test.go (1 hunks)
  • money/type.go (1 hunks)
  • parser/parser.go (1 hunks)
  • parser/parser_test.go (1 hunks)
  • parser/symbols.go (1 hunks)
💤 Files with no reviewable changes (9)
  • base/money_example_test.go
  • base/mutator.go
  • base/db_test.go
  • base/money_test.go
  • main.go
  • base/currency_test.go
  • base/Makefile
  • base/money.go
  • base/calculator.go
🧰 Additional context used
🧬 Code graph analysis (20)
money/tests/factory_test.go (3)
money/type.go (2)
  • Money (13-16)
  • Amount (9-9)
money/factory.go (36)
  • FromUSD (6-8)
  • FromEUR (11-13)
  • FromGBP (16-18)
  • FromJPY (21-23)
  • FromCHF (26-28)
  • FromCAD (31-33)
  • FromAUD (36-38)
  • FromCNY (41-43)
  • FromINR (46-48)
  • FromBRL (51-53)
  • FromMXN (56-58)
  • FromNZD (61-63)
  • FromSGD (66-68)
  • FromHKD (71-73)
  • FromNOK (76-78)
  • FromSEK (81-83)
  • FromDKK (86-88)
  • FromRUB (91-93)
  • FromZAR (96-98)
  • FromTRY (101-103)
  • FromKRW (106-108)
  • FromPLN (111-113)
  • FromTHB (116-118)
  • FromIDR (121-123)
  • FromMYR (126-128)
  • FromPHP (131-133)
  • FromCZK (136-138)
  • FromHUF (141-143)
  • FromILS (146-148)
  • FromCLP (151-153)
  • FromAED (156-158)
  • FromSAR (161-163)
  • FromARS (166-168)
  • FromCOP (171-173)
  • FromTWD (176-178)
  • FromVND (181-183)
currencies/constants.go (36)
  • USD (153-153)
  • EUR (53-53)
  • GBP (56-56)
  • JPY (76-76)
  • CHF (34-34)
  • CAD (31-31)
  • AUD (12-12)
  • CNY (38-38)
  • INR (70-70)
  • BRL (25-25)
  • MXN (103-103)
  • NZD (112-112)
  • SGD (131-131)
  • HKD (64-64)
  • NOK (110-110)
  • SEK (130-130)
  • DKK (47-47)
  • RUB (124-124)
  • ZAR (181-181)
  • TRY (147-147)
  • KRW (82-82)
  • PLN (119-119)
  • THB (142-142)
  • IDR (68-68)
  • MYR (105-105)
  • PHP (117-117)
  • CZK (45-45)
  • HUF (67-67)
  • ILS (69-69)
  • CLP (37-37)
  • AED (5-5)
  • SAR (126-126)
  • ARS (11-11)
  • COP (39-39)
  • TWD (149-149)
  • VND (160-160)
money/tests/exchange_test.go (4)
money/money.go (1)
  • NewMoney (12-17)
currencies/constants.go (2)
  • USD (153-153)
  • EUR (53-53)
money/exchange.go (2)
  • Convert (8-25)
  • ConvertWithRate (28-43)
exception/exception.go (2)
  • ErrCurrencyConversionNotFound (9-9)
  • ErrInvalidExchangeRate (8-8)
money/tests/aggregator_test.go (5)
money/aggregator.go (4)
  • Sum (9-23)
  • Min (27-48)
  • Max (52-73)
  • Avg (77-98)
exception/exception.go (2)
  • ErrNoMoneyToSum (10-10)
  • ErrCurrencyMismatch (6-6)
money/money.go (1)
  • NewMoney (12-17)
currencies/constants.go (2)
  • USD (153-153)
  • EUR (53-53)
money/type.go (1)
  • Amount (9-9)
exception/exception.go (3)
parser/parser.go (1)
  • New (13-15)
formatter/formatter.go (1)
  • New (17-25)
exchange/exchange.go (1)
  • New (9-13)
parser/symbols.go (1)
currencies/constants.go (9)
  • BRL (25-25)
  • CAD (31-31)
  • AUD (12-12)
  • USD (153-153)
  • EUR (53-53)
  • GBP (56-56)
  • JPY (76-76)
  • INR (70-70)
  • CHF (34-34)
money/aggregator.go (2)
money/type.go (1)
  • Money (13-16)
exception/exception.go (1)
  • ErrNoMoneyToSum (10-10)
exchange/converter.go (1)
exchange/type.go (2)
  • Exchange (23-25)
  • Converter (28-30)
formatter/formatter_test.go (1)
formatter/formatter.go (1)
  • New (17-25)
money/db.go (1)
money/type.go (2)
  • Money (13-16)
  • Amount (9-9)
parser/parser_test.go (2)
currencies/constants.go (5)
  • USD (153-153)
  • EUR (53-53)
  • CAD (31-31)
  • AUD (12-12)
  • BRL (25-25)
parser/parser.go (2)
  • New (13-15)
  • ParseDecimal (65-69)
money/tests/money_methods_test.go (5)
money/money.go (2)
  • NewMoney (12-17)
  • NewFromFloat (21-27)
currencies/constants.go (3)
  • USD (153-153)
  • JPY (76-76)
  • EUR (53-53)
money/type.go (2)
  • Amount (9-9)
  • Money (13-16)
exception/exception.go (2)
  • ErrCurrencyMismatch (6-6)
  • ErrInvalidJSONUnmarshal (7-7)
money/json.go (2)
  • MarshalJSON (14-14)
  • UnmarshalJSON (13-13)
money/json.go (2)
exception/exception.go (1)
  • ErrInvalidJSONUnmarshal (7-7)
money/money.go (1)
  • NewMoney (12-17)
money/tests/db_test.go (3)
money/money.go (1)
  • NewMoney (12-17)
money/type.go (2)
  • Money (13-16)
  • Amount (9-9)
currencies/currency.go (1)
  • NewCurrency (56-58)
exchange/exchange.go (2)
exchange/type.go (1)
  • Exchange (23-25)
exception/exception.go (2)
  • ErrInvalidExchangeRate (8-8)
  • ErrCurrencyConversionNotFound (9-9)
money/tests/extreme_edge_cases_test.go (5)
money/money.go (1)
  • NewMoney (12-17)
currencies/constants.go (3)
  • JPY (76-76)
  • USD (153-153)
  • EUR (53-53)
money/type.go (1)
  • Amount (9-9)
money/exchange.go (1)
  • ConvertWithRate (28-43)
money/db.go (1)
  • DBMoneyValueSeparator (16-16)
currencies/currency.go (2)
currencies/type.go (2)
  • Currencies (14-14)
  • Currency (4-12)
formatter/formatter.go (1)
  • Formatter (9-15)
calculator/calculator_test.go (1)
calculator/calculator.go (3)
  • NewCalculator (12-14)
  • Amount (6-6)
  • Calculator (9-9)
money/money.go (5)
money/type.go (2)
  • Money (13-16)
  • Amount (9-9)
currencies/currency.go (1)
  • NewCurrency (56-58)
exception/exception.go (2)
  • ErrCurrencyMismatch (6-6)
  • ErrNoMultipliersProvided (13-13)
calculator/calculator.go (1)
  • NewCalculator (12-14)
formatter/formatter.go (1)
  • Formatter (9-15)
exchange/tests/converter_test.go (3)
exchange/exchange.go (1)
  • New (9-13)
exchange/converter.go (1)
  • NewConverter (3-7)
exchange/type.go (1)
  • Converter (28-30)
money/factory.go (3)
money/type.go (1)
  • Money (13-16)
money/money.go (1)
  • NewMoney (12-17)
currencies/constants.go (36)
  • USD (153-153)
  • EUR (53-53)
  • GBP (56-56)
  • JPY (76-76)
  • CHF (34-34)
  • CAD (31-31)
  • AUD (12-12)
  • CNY (38-38)
  • INR (70-70)
  • BRL (25-25)
  • MXN (103-103)
  • NZD (112-112)
  • SGD (131-131)
  • HKD (64-64)
  • NOK (110-110)
  • SEK (130-130)
  • DKK (47-47)
  • RUB (124-124)
  • ZAR (181-181)
  • TRY (147-147)
  • KRW (82-82)
  • PLN (119-119)
  • THB (142-142)
  • IDR (68-68)
  • MYR (105-105)
  • PHP (117-117)
  • CZK (45-45)
  • HUF (67-67)
  • ILS (69-69)
  • CLP (37-37)
  • AED (5-5)
  • SAR (126-126)
  • ARS (11-11)
  • COP (39-39)
  • TWD (149-149)
  • VND (160-160)
🪛 checkmake (0.2.2)
Makefile

[warning] 1-1: Missing required phony target "all"

(minphony)


[warning] 1-1: Missing required phony target "clean"

(minphony)

🪛 LanguageTool
README.md

[uncategorized] ~292-~292: Possible missing comma found.
Context: ...ies This library supports all ISO 4217 currencies including: - Major: USD, EUR, GBP,...

(AI_HYDRA_LEO_MISSING_COMMA)


[locale-violation] ~370-~370: License must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ...ystem with explicit rate management ## License This project is licensed under the MIT...

(LICENCE_LICENSE_NOUN_SINGULAR)


[locale-violation] ~372-~372: License must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ... This project is licensed under the MIT License - see the LICENSE file for d...

(LICENCE_LICENSE_NOUN_SINGULAR)


[locale-violation] ~372-~372: LICENSE must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ...censed under the MIT License - see the LICENSE file for details. ## Credits...

(LICENCE_LICENSE_NOUN_SINGULAR)


[style] ~380-~380: Consider using a less common alternative to make your writing sound more unique and professional.
Context: ...ontributing Contributions are welcome! Please feel free to submit a Pull Request. ## Resources -...

(FEEL_FREE_TO_STYLE_ME)

🔇 Additional comments (39)
.gitignore (1)

11-11: Good placement in the Go artifacts section.

The addition of .gocache is logically grouped with other Go workspace files. However, please verify that .gocache is the correct cache directory pattern used by your project's tooling, as the standard Go build cache typically resides at $HOME/.cache/go-build rather than a project-relative .gocache directory.

exception/exception.go (1)

5-14: Centralised error definitions look appropriate

The shared error values cover the main failure modes (currency mismatch, parsing, JSON, exchange, aggregation) and will make it easier to compare errors across packages. The messages are clear and neutral; no changes needed here.

parser/parser.go (1)

11-15: LGTM!

The Parser struct and New() constructor are simple and appropriate for this use case.

currencies/type.go (4)

16-17: LGTM!

Renaming currencies to currenciesMap avoids shadowing the package name and improves clarity. The variable naming convention is appropriate.


37-53: LGTM!

The added ISO 4217 fund codes (BOV, CHE, CHW, COU) are valid additions that expand the library's coverage for specialised financial instruments.


167-170: LGTM!

USN (US Dollar Next Day), UYI (Uruguay Peso en Unidades Indexadas), and UYW (Unidad Previsional) are valid ISO 4217 fund codes.


179-192: LGTM!

The precious metals (XPD, XPT), bond market units (XBA-XBD), and special codes (XSU, XTS, XUA, XXX) are valid ISO 4217 additions. XXX (no currency) and XTS (testing) are particularly useful for edge case handling.

exchange/converter.go (1)

9-15: LGTM!

The nil receiver check in GetExchange is a defensive pattern that prevents panics when called on a nil Converter.

exchange/tests/converter_test.go (1)

9-20: LGTM!

Good test coverage verifying that NewConverter returns a non-nil Converter and that GetExchange returns the correct exchange instance.

money/tests/exchange_test.go (1)

12-46: Conversion tests cover core success and error paths well

The test cases exercise same‑currency behaviour, missing conversion rate handling, explicit‑rate conversion and invalid‑rate errors in a clear way using errors.Is; this looks solid and aligned with the money/exchange APIs.

money/type.go (1)

8-16: Amount alias and Money struct wiring look sound

Aliasing Amount to calculator.Amount and embedding *currencies.Currency with DB tags gives a clean, cohesive core type for the money package, with unexported fields enforcing use of helpers.

money/tests/db_test.go (2)

10-89: Money DB serialisation / scan tests give good coverage

The Money.Value and Money.Scan tests cover happy paths (including negatives) and key failure modes (missing separator, empty components, wrong type), which matches the Value/Scan contract and should catch most persistence regressions.


91-150: Currency DbValue/DbScan tests accurately capture expected behaviour

The currency tests validate upper‑casing, handling of lower‑case input, and appropriate errors for invalid types or codes, which aligns well with a strict currency model and centralises assumptions around valid codes.

formatter/formatter_test.go (1)

1-188: Formatter tests provide strong coverage and robust float comparisons

The expanded table‑driven tests for Format and ToMajorUnits exercise a wide range of formats and edge cases, and switching ToMajorUnits to an epsilon‑based check with math.Abs is a sensible way to avoid fragile float equality.

currencies/constants.go (1)

1-184: LGTM!

The expanded ISO 4217 currency constant set is well-structured and correctly includes funds, precious metals, bond market units, supranational currencies, and test codes. The alphabetical ordering is maintained throughout.

formatter/formatter.go (1)

1-71: LGTM!

The refactoring improves consistency:

  • Constructor renamed to New following Go conventions
  • Pointer receivers are now consistent across all methods
  • Field documentation enhances readability
  • math.Pow10 simplifies the calculation in ToMajorUnits
money/tests/money_methods_test.go (2)

1-446: Comprehensive test coverage.

The test suite thoroughly covers:

  • Constructors and accessors
  • Currency validation and comparison
  • Arithmetic operations with error handling
  • Sign checks and absolute/negative conversions
  • Splitting and allocation
  • JSON marshalling/unmarshalling with error cases
  • Comparison edge cases

Good use of table-driven tests and errors.Is for error assertions.


350-352: Remove the suggestion to change the JSON format in the test.

The MarshalJSON implementation in money/json.go:86 explicitly uses fmt.Sprintf(\{"amount": %d, "currency": "%s"}`, ...)` which produces JSON with spaces after colons. The test assertion at lines 350-352 correctly matches this actual output format.

Likely an incorrect or invalid review comment.

money/tests/extreme_edge_cases_test.go (1)

61-76: Test expectation is correct.

The conversion calculation is accurate: 123 minor units USD (Fraction: 2) × 1.5 = 184.5 minor units USD → 1.845 major units USD. When converting to JPY (Fraction: 0), the conversion yields 1.845 major JPY, which truncates to 1 JPY via int64() cast. Since JPY has no decimal fraction, result.Amount() == 1 is the correct expected value.

money/exchange.go (1)

17-17: No validation required—Get() safely returns a default Currency struct.

The concern is unfounded. NewCurrency(toCurrency).Get() never returns nil or a zero-value struct. The Get() method checks if the currency exists in currenciesMap and returns it if found; otherwise, it returns a default Currency struct with Fraction: 2 via GetDefault(). Therefore, accessing .Fraction at lines 17 and 34 is safe and cannot cause a nil pointer dereference, even with invalid currency codes.

Likely an incorrect or invalid review comment.

exchange/exchange.go (3)

9-13: LGTM!

Constructor correctly initialises the nested map structure for storing exchange rates.


15-27: LGTM!

AddRate properly validates the receiver and rate, lazily initialises the inner map, and stores the rate. The validation for rate <= 0 correctly rejects zero and negative rates.


29-52: LGTM!

GetRate handles identity conversion (same currency), direct lookup, and inverse rate calculation correctly. The fallback chain is well-structured.

money/json.go (2)

11-25: LGTM!

The overridable hooks pattern allows runtime customisation of JSON behaviour without modifying the type methods. The delegation is clean.


80-89: LGTM!

The marshalling correctly handles zero-value Money by substituting with a properly initialised instance before formatting. The output format is consistent.

currencies/currency.go (4)

22-38: LGTM!

CurrencyByCode correctly uses map lookup, and Add properly updates the currencies map. The fluent return of Currencies enables method chaining.


40-54: LGTM!

AddCurrency provides a convenient way to define custom currencies with all formatting parameters and automatically registers them in the global map.


56-70: LGTM!

NewCurrency and GetCurrency correctly handle case normalisation with strings.ToUpper. GetCurrencyByNumericCode delegates appropriately.


107-131: LGTM!

Database serialisation is well-implemented. DbScan correctly validates the source type and handles the case where GetCurrency returns nil for unknown codes.

money/money.go (9)

12-17: LGTM!

NewMoney correctly initialises the Money struct with the amount and retrieves the full currency details via NewCurrency(code).Get().


29-47: LGTM!

Accessor methods and currency comparison are straightforward and correct.


49-98: LGTM!

Comparison methods correctly check currency consistency before comparing amounts. The CompareAmount switch pattern is idiomatic.


100-124: LGTM!

Sign check methods and Absolute/Negative transformations are correctly implemented, delegating arithmetic to the calculator.


126-170: LGTM!

Add and Subtract correctly validate currency consistency for each operand and accumulate values using the calculator. Empty operand handling returns self, which is sensible.


172-188: LGTM!

Multiply correctly rejects empty multiplier lists and compounds all multipliers before applying to the amount.


199-229: LGTM!

Split correctly handles the division with leftover distribution using round-robin allocation. The sign handling for negative amounts ensures leftovers are distributed correctly in either direction.


231-286: LGTM!

Allocate has comprehensive validation (negative ratios, overflow protection) and correctly distributes leftovers. The early return for zero-sum ratios is a good edge case handling.


288-299: LGTM!

Display and AsMajorUnits correctly delegate to the currency's formatter for consistent output.

money/factory.go (1)

1-58: LGTM!

Factory functions provide convenient currency-specific constructors. The pattern is consistent and delegates correctly to NewMoney.

Comment thread calculator/calculator_test.go
Comment thread calculator/calculator.go
Comment thread exchange/currency.go Outdated
Comment thread exchange/currency.go Outdated
Comment thread exchange/converter.go Outdated
Comment thread parser/parser.go Outdated
Comment thread parser/parser.go
Comment thread parser/parser.go
Comment thread parser/symbols.go Outdated
Comment thread README.md Outdated
@gocanto
gocanto marked this pull request as draft December 6, 2025 08:58

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review continued from previous batch...

Comment thread money/factory.go
Comment thread money/manager.go
Comment thread money/manager.go
Comment thread money/manager.go
@gocanto
gocanto marked this pull request as draft December 15, 2025 01:54
@gocanto gocanto added testing and removed testing labels Dec 15, 2025
@gocanto
gocanto marked this pull request as ready for review December 15, 2025 07:09
@gocanto
gocanto merged commit 1a35f0e into main Dec 15, 2025
3 of 4 checks passed
@gocanto
gocanto deleted the chore/money branch December 15, 2025 07:10
@coderabbitai coderabbitai Bot mentioned this pull request Dec 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant