BaryoDev / BaryoDev/barakoCMS

The money field type is a decimal with a label: no currency, no scale, no rounding rule

Open
#581 0 comments 0 reactions 0 assignees View on GitHub
core enhancement
Dominant language
C#
Stars
6
Forks
7
Avg merge
4h 42m
Merged PRs (30d)
307

Description

The field registry has a `money` type. Its validator is `IsDecimal` (`FieldTypeRegistry`), the same one `decimal` uses. The only difference between them is the editor hint.

So money today is a number with a label. It carries no currency, no scale, no rounding rule, and no invariant.

## What that costs

**No currency.** Two amounts can be added that should never have been. Nothing records which currency an amount is in, so nothing can refuse the addition or convert it.

**No scale or rounding rule.** A value arriving with four decimal places is stored with four. Whether a third is rounded half-up or half-even is decided by whatever code touches it last, which means two paths can disagree about the same total.

**No non-negative invariant.** A price of minus five is accepted.

**Totals cannot be trusted across a set.** Once the aggregate work lands, "the header total equals the sum of the lines" is only checkable if the lines and the header agree on currency and scale. With a bare decimal they might not.

For an accounting posting, an invoice or a trade, these are not edge cases. They are the reason the data is being kept.

## What to add

A real money type: an amount plus a currency, with the scale from the currency, a declared rounding rule, and an optional non-negative constraint on the field definition.

The registry is already the single source of truth for accepted types and validators, so this is an addition to an existing seam rather than a new mechanism.

## What to decide

**Whether currency is per field or per entry.** An invoice has one currency across all its lines, so per entry is usually right and per field is more flexible. Picking per field by default and letting a type declare otherwise is probably the answer, but it should be decided rather than defaulted.

**Whether multi-currency conversion is in scope.** I would say no. Storing the currency correctly is the requirement; converting between them is a separate feature with a rate source and a date, and conflating them makes both worse.

**Migration.** Existing `money` fields hold bare decimals. They need a currency from somewhere, and the honest answer may be that a host declares it once per content type and a migration stamps it.

## Done when

- A money value carries its currency and is stored at the currency's scale.
- Adding two amounts in different currencies is refused rather than silently wrong.
- The rounding rule is declared, not implied by whichever code path ran.
- A negative amount is refused where the field says it must not be.

Contributor guide

Open the contributing guide

Research direction

Start at the FieldTypeRegistry and trace how the existing money and decimal validators, editor hints, and persistence are wired. Resolve currency scope, conversion exclusion, scale and rounding, non-negative behavior, and migration treatment before defining the value and field contract. Done means the listed currency, scale, rounding, currency-mismatch, and negative-value requirements are enforced.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
backend, backend-api-design, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.