agentleFS
MatanElbazMatanElbaz/backend-skills/skills/money-handling/SKILL.md

money-handling

Skill1 starsChanged 43 days agoMITView on GitHub

Use when code stores, computes, converts, compares, or displays monetary amounts or currencies

The file

We split this skill into the rules it gives an agent

4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Never float or double. Use integer minor units (long cents) or BigDecimal with an explicit scale.

    line 17
  2. Very specific:

    Every division or scale change names its RoundingMode.

    line 20
  3. Distinctive:

    When splitting an amount (shares, installments), the parts must sum to the total.

    line 22
  4. Distinctive:

    No currency anywhere, so nothing stops a USD amount being compared with an EUR one.

    line 43

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Money handling

Money bugs are quiet. They show up as a cent off here and there, found months later by reconciliation.

When to use

  • Any field, column, or calculation that represents an amount.
  • Fees, taxes, discounts, splits, currency conversion, or comparing amounts.

Checklist

  1. Never float or double. Use integer minor units (long cents) or BigDecimal with an explicit scale.
  2. An amount always travels with its currency. Never add or compare across currencies.
  3. The number of decimal places depends on the currency (JPY has 0, KWD has 3). Take it from ISO 4217 data, for example Currency.getDefaultFractionDigits(), never from a hardcoded 2. It returns -1 for pseudo-currencies such as XXX, so reject those.
  4. Every division or scale change names its RoundingMode. BigDecimal.divide without one throws on non-terminating results. Document the business rule you chose.
  5. BigDecimal.equals compares scale, so 2.0 does not equal 2.00. Compare with compareTo.
  6. When splitting an amount (shares, installments), the parts must sum to the total. Distribute the remainder explicitly instead of rounding each part.
  7. In JSON, send amounts as strings or as integer minor units, not as floating-point numbers. In the database use numeric(p, s) or bigint, never float or double precision.
  8. For conversion, record the rate, its timestamp, and its source, and convert once at a defined point.

Bad example

double total = 0;
for (Line l : lines) {
    total += l.getPrice() * l.getQty() * 1.17;   // price + VAT
}
if (total == invoice.getAmount()) {
    markPaid();
}
return total;                                     // serialized as a JSON number

What to flag

  • double for money: 0.1 + 0.2 is not 0.3, and errors accumulate across lines.
  • == on floating-point amounts will miss equal values and may match different ones.
  • No currency anywhere, so nothing stops a USD amount being compared with an EUR one.
  • VAT applied per line with no rounding rule: the total can differ from the invoice by a cent.
  • The result is serialized as a JSON number, which clients may parse as a float.

Good example

Currency currency = invoice.currency();
BigDecimal vatFactor = new BigDecimal("1.17");   // 17% VAT as a multiplier

BigDecimal net = lines.stream()
    .map(l -> l.unitPrice().multiply(BigDecimal.valueOf(l.qty())))
    .reduce(BigDecimal.ZERO, BigDecimal::add);

// Rounding rule: HALF_EVEN here. Use whatever your jurisdiction or contract requires.
int scale = currency.getDefaultFractionDigits();
if (scale < 0) throw new IllegalArgumentException("no minor unit: " + currency);
BigDecimal gross = net.multiply(vatFactor).setScale(scale, RoundingMode.HALF_EVEN);

if (gross.compareTo(invoice.amount()) == 0) {
    markPaid();
}
return gross.toPlainString();                     // string, not a float

Rounding once, at the end, with a named mode, keeps the total predictable. If the business rule is to round per line, say so in the code and round each line with the same mode.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.