Repository navigation
Store money as integer cents - #348
Merged
Merged
Conversation
eirvandelden
marked this pull request as ready for review
October 17, 2026 06:29
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The tools find_uncategorized_transactions and charge_to_appropriation convert cents to euros. No test proved it. A regression to raw cents would have passed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The partial shows the amount in euros. No test read it. The test stubs two account columns the partial still reads, so the existing bug there stays out of scope. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
An unreadable amount also failed the presence and comparison checks. The form printed three messages. Now only 'is not an amount' stays. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
printf turned a NULL amount into 0.00, so a search for 0 found it. The match now needs an amount. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Two tests get the Proof name. Three new tests cover the comma amount, the paid amount and the packing slip cents. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
eirvandelden
force-pushed
the
cents-instead-of-decimals
branch
from
October 22, 2026 06:55
b50d22d to
f14e8f0
Compare
Main added appropriation tests in euros while this branch moved money to cents. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
eirvandelden
force-pushed
the
cents-instead-of-decimals
branch
from
October 22, 2026 07:36
f14e8f0 to
9159722
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Amounts live in decimal columns, so half cents can enter the books through arithmetic such as splits and receipt lines. A half cent changes a total that a user sees, and no bank statement has one.
Every money amount is stored as a whole number of cents: what is 1,5 today becomes 150. Users still type and read 1,50 in the interface. No amount that a user sees goes up or down because of the change.
Implementation
New:
app/models/cents.rb—Cents.parse,Cents.from_euros,Cents.to_euros.app/models/cents/type.rb—Cents::Type.app/models/concerns/monetary.rb—monetarymacro and the unreadable-amount validation.app/helpers/money_helper.rb—cents_to_currency,cents_field_value.db/migrate/20261016120000_convert_money_to_cents.rb— the migration.test/models/cents_test.rb,test/models/cents/type_test.rb,test/models/concerns/monetary_test.rb,test/models/money_fixtures_test.rb,test/helpers/money_helper_test.rb,test/migrations/convert_money_to_cents_test.rb,test/integration/transaction_amounts_test.rb,test/tools/assistant/budget_status_test.rb.docs/changes/cents-instead-of-decimals/verify/dump_before.rb,verify/dump_after.rb,verify/dump_raw.sql— the real-data check scripts. They leave with the change folder at delivery.Changed:
db/schema.rb— ten columns becomeinteger.appropriation.rb,budget_category.rb,chattel.rb,receipt.rb,receipt_line.rb,transaction_split.rb,transaction.rb—include Monetary,monetary ...,numericality→comparison, search SQL,amount_was.to_i, return-type doc comments (@return [Integer] cents).app/models/concerns/splittable.rb,linkable.rb— doc comments to Integer cents;Cents.parseinsearchable_transfers.app/models/budget.rb—suggested_amountsrounds to Integer cents.app/models/dashboard.rb—budget_amountsandhistorical_averagesin Integer cents; doc comments.app/models/importing/ing/row.rb,app/models/importing/albert_heijn/packing_slip.rb— cents.products_helper.rb(to_ddivision),todos_helper.rb(cents_to_currency).number_to_currencybecomescents_to_currency:appropriations/{index,show,_balance},budgets/show,chattels/_table,dashboard/_balance,product_types/show,products/{show,_price_chart},receipts/{index,show,_basket},searches/_result_transaction,shared/_recent_transactions,transaction_links/{_balance_table,_search_results,_suggestions},transaction_splits/_table,transactions/{_table,show}.value: cents_field_value(...):appropriations/_form,budgets/_budget_category_fields,chattels/_form,transaction_splits/_table,transactions/_form.dashboard/index.html.erb— chart data converted to euros.transactions/_transaction.json.jbuilder—amountin euros.budget_status.rb,charge_to_appropriation.rb,find_uncategorized_transactions.rb,list_appropriations.rb,set_appropriation.rb,set_budget_amount.rb.en.yml,nl.yml,it.yml—activerecord.errors.messages.not_an_amount(en "is not an amount", nl "is geen bedrag", it "non è un importo"); thenbundle exec i18n-tasks normalize.test/fixtures/{appropriations,budget_categories,chattels,receipt_lines,receipts,transaction_splits,transactions}.yml— values in cents.test/models,test/integration,test/helpers,test/jobs,test/tools,test/views,test/system(56 files mention an amount; only those whose literals or expectations break change).test/system/budgets_test.rbformats the expected field value withformat("%.2f", Cents.to_euros(amount)).Proof
test/migrations/convert_money_to_cents_test.rb"up stores a transaction of 1,5 as 150 cents" andtest/integration/transaction_amounts_test.rb"a transaction of 150 cents shows as 1,50"test/integration/transaction_amounts_test.rb"typing 1,50 stores 150 cents and the form shows 1,50 again"test/integration/transaction_amounts_test.rb"typing 1,5 or 1.50 stores 150 cents"test/integration/transaction_splits_test.rb"splitting 12,34 into 10,00 and 2,34 leaves nothing unsplit"test/migrations/convert_money_to_cents_test.rb"receipt lines that add up to the total still do after up"test/integration/dashboard_test.rbandtest/integration/budgets_test.rbexisting figure assertions, green on cent fixtures; and check: the real-data comparison below, dashboard and budget sectiontest/tools/assistant/budget_status_test.rb"reports a plan of 1250 cents as 12.50"test/migrations/convert_money_to_cents_test.rb"down restores the original decimal values"; and check: after the real-data run,bin/rails db:rollback, thensqlite3 storage/db/development.sqlite3 < docs/changes/cents-instead-of-decimals/verify/dump_raw.sql > tmp/raw_after_rollback.txt, anddiff tmp/raw_before.txt tmp/raw_after_rollback.txtprints nothing. This raw dump needs no app code, so the branch's cent-based code cannot distort it. Migrate up again afterwards.