ores.refdata.currency

Table of Contents

ISO 4217 currency definitions used for reference data. Currencies are managed per-tenant and drive financial calculations, rounding, and display formatting across the system.

1. Flags

2. Columns

2.1. iso_code

ISO 4217 alpha-3 code (e.g., "USD", "EUR", "GBP").

The :name generator block below only supplies the literal "X" prefix consumed by the template's counter-based generate_synthetic_currency codepath (X + counter, e.g. "X0", "X1"); the fictional generator (generate_fictional_currencies, injected via custom generator sections below) remains the authoritative test-data source and does not depend on this synthetic path.

std::string("X")

2.2. name

Human-readable currency name (e.g., "US Dollar", "Euro").

"Test Currency " + std::to_string(faker::number::integer(1000, 9999))

2.3. numeric_code

ISO 4217 numeric code (e.g., "840", "978").

std::to_string(faker::number::integer(10001, 99999))

2.4. symbol

Currency symbol displayed in the UI (e.g., "$", "€", "£").

faker::finance::currencySymbol() can return an empty string for some locales; fall back to "$" rather than violate the non-nullable constraint.

[] {
    const auto sym = faker::finance::currencySymbol();
    return sym.empty() ? std::string("$") : std::string(sym);
}()

2.5. fraction_symbol

Symbol for the fractional unit (e.g., "¢" for cents, "p" for pence).

std::string("c")

2.6. fractions_per_unit

Number of fractional units per whole unit (e.g., 100 for centesimal, 0 for zero-decimal).

100

2.7. rounding_type

Rounding method code; soft FK to ores_refdata_rounding_types_tbl.

std::string("Closest")

2.8. rounding_precision

Number of decimal places for rounding (e.g., 2 for centesimal currencies).

2

2.9. format

Boost.Format pattern for displaying amounts (e.g., "%3% %1$.2f").

std::string("%3% %1$.2f")

2.10. monetary_nature

Nature classification; soft FK to ores_refdata_monetary_natures_tbl (e.g., "fiat", "commodity").

std::string("fiat")

2.11. market_tier

Market tier classification; soft FK to ores_refdata_currency_market_tiers_tbl (e.g., "g10", "emerging").

std::string("g10")

2.12. image_id

Optional reference to a flag or logo image in the images table.

std::nullopt

2.13. spot_days

Business days to settlement for a spot trade in this currency (USD is 1, most others are 2). Used to derive currency_pair.spot_days as the max of the two legs' values.

faker::helper::randomElement(std::vector<int>{1, 2})

2.14. day_basis

Day-count convention code (e.g. "ACT/360", "ACT/365"). Free-text for now — no aux-type table exists yet; see Currency pair support in reference data for the open question.

std::string("ACT/360")

2.15. base_precedence

Ordinal rank in the base-currency precedence table used to determine canonical base/quote order for a pair (lower = takes precedence as base currency).

faker::number::integer(1, 100)

3. Artefact columns

The ISO import carries holiday_calendar, which refdata_currency_calendars_seed_populate.sql reads from this table to derive currency-to-calendar assignments. coding_scheme_code is left out: the publish takes it from the dataset it is publishing.

3.1. iso_code

3.2. version

3.3. name

3.4. numeric_code

3.5. symbol

3.6. fraction_symbol

3.7. fractions_per_unit

3.8. rounding_type

3.9. rounding_precision

3.10. format

3.11. monetary_nature

3.12. market_tier

3.13. image_id

3.14. spot_days

3.15. day_basis

3.16. base_precedence

3.17. holiday_calendar

4. SQL

4.1. Flags

4.2. Extra drops

drop function if exists ores_refdata_validate_currency_fn;

5. Validation function

6. Insert trigger

6.1. Validations

column validation_function
rounding_type ores_refdata_validate_rounding_type_fn
monetary_nature ores_refdata_validate_monetary_nature_fn
market_tier ores_refdata_validate_currency_market_tier_fn
change_reason_code ores_dq_validate_change_reason_fn

7. C++

7.1. Flags

7.2. Repository

7.3. Domain includes

#include <boost/uuid/uuid.hpp>
#include <chrono>
#include <optional>
#include <string>

7.4. Entity includes

#include <optional>
#include <string>

7.5. Conventions

7.6. Table display

column header
iso_code Code
name Currency Name
numeric_code Numeric Code
symbol Symbol
fraction_symbol Fraction
fractions_per_unit Per Unit
rounding_type Rounding Type
rounding_precision Precision
format Format
monetary_nature Monetary Nature
market_tier Market Tier
spot_days Spot Days
day_basis Day Basis
base_precedence Base Precedence
modified_by Modified By
version Version

7.7. Presentation

7.7.1. Detail fields

All 11 fields currently exposed in CurrencyDetailDialog.ui (3 new domain columns — spot_days, day_basis, base_precedence — aren't in the UI yet; out of scope for this sync, tracked separately). image_id isn't a detail field either (handled generically via has_flag_icon, matching every other flag entity).

field label widget type is_key is_required placeholder spin_min spin_max combo_domain_type combo_fetch_include combo_fetch_fn combo_watcher_name combo_code_field combo_tooltip_field combo_sort_field combo_label combo_setter_pascal badge_key view_group tooltip
iso_code ISO Code isoCodeEdit line_edit true true Enter ISO 4217 code                         General ISO 4217 alpha-3 code used to reference this currency throughout the system.
name Name nameEdit line_edit   true Enter currency name                         General Full descriptive name of the currency.
numeric_code Numeric Code numericCodeEdit line_edit   true Enter numeric code                         General ISO 4217 numeric code, required by some external interfaces and standards.
monetary_nature Asset Class monetaryNatureCombo dynamic_combo           refdata::domain::monetary_nature   fetch_monetary_natures monetaryNatureWatcher code description display_order monetary natures MonetaryNatureCombo monetary_nature General Classifies the underlying nature of the currency (e.g. fiat, commodity), driving nature-specific business rules.
market_tier Market Tier marketTierCombo dynamic_combo           refdata::domain::currency_market_tier   fetch_currency_market_tiers marketTierWatcher code description display_order currency market tiers MarketTierCombo currency_market_tier General Classifies the market liquidity/importance tier of the currency (e.g. G10, emerging), used for tiering-based rules and reporting.
symbol Symbol symbolEdit line_edit   true Enter currency symbol                         Formatting Symbol used when formatting monetary amounts in this currency (e.g. $, €, £).
fraction_symbol Fraction Symbol fractionSymbolEdit line_edit     Enter fraction symbol                         Formatting Symbol for the fractional sub-unit of the currency (e.g. cents, pence).
fractions_per_unit Fractions Per Unit fractionsPerUnitSpinBox spin_box       0 10000                     Formatting Number of fractional sub-units per whole unit (e.g. 100 for centesimal currencies, 0 for zero-decimal currencies like JPY).
format Format formatEdit line_edit     Enter display format                         Formatting Boost.Format pattern controlling how amounts in this currency are displayed.
rounding_type Rounding Type roundingTypeCombo dynamic_combo           refdata::domain::rounding_type   fetch_rounding_types roundingTypeWatcher code description display_order rounding types RoundingTypeCombo   Rounding Rounding method applied to amounts in this currency (e.g. round to closest).
rounding_precision Rounding Precision roundingPrecisionSpinBox spin_box       0 10                     Rounding Number of decimal places amounts in this currency are rounded to.

7.7.2. Columns

enum_name field header type width import_preview is_badge badge_key hidden_by_default tooltip
IsoCode iso_code Code string auto true       ISO 4217 alpha-3 code used to reference this currency throughout the system.
CurrencyName name Currency Name string auto true       Full descriptive name of the currency.
NumericCode numeric_code Numeric Code string 70       true ISO 4217 numeric code, required by some external interfaces and standards.
Symbol symbol Symbol string 60 true       Symbol used when formatting monetary amounts in this currency (e.g. $, €, £).
FractionSymbol fraction_symbol Fraction string 60 true     true Symbol for the fractional sub-unit of the currency (e.g. cents, pence).
FractionsPerUnit fractions_per_unit Per Unit int 70 true     true Number of fractional sub-units per whole unit (0 for zero-decimal currencies like JPY).
RoundingType rounding_type Rounding Type string auto       true Rounding method applied to amounts in this currency.
RoundingPrecision rounding_precision Precision int 70         Number of decimal places amounts in this currency are rounded to.
Format format Format string auto       true Boost.Format pattern controlling how amounts in this currency are displayed.
MonetaryNature monetary_nature Monetary Nature string auto   true monetary_nature   Classifies the underlying nature of the currency (e.g. fiat, commodity).
MarketTier market_tier Market Tier string auto   true currency_market_tier   Classifies the market liquidity/importance tier of the currency (e.g. G10, emerging).
SpotDays spot_days Spot Days int 70       true Number of business days to this currency's spot value date.
DayBasis day_basis Day Basis string 80         This currency's day-count convention code (e.g. ACT/360, ACT/365).
BasePrecedence base_precedence Base Precedence int 100       true This currency's ordinal rank in the base-currency precedence table, used to determine canonical base/quote order for a pair.
Version version Version int 70        
ModifiedBy modified_by Modified By string auto  
RecordedAt recorded_at Recorded At timestamp auto  

7.7.3. Related entity shortcuts

signal icon label tooltip
RoundingTypes Tag Rounding Open Rounding Types list
MonetaryNatures Classification Monetary Natures Open Monetary Natures list
MarketTiers Chart Market Tiers Open Currency Market Tiers list

7.8. Custom service constructor init

, junction_repo_(ctx_)

7.9. Custom service includes

#include <boost/uuid/uuid.hpp>
#include "ores.refdata.core/repository/party_currency_repository.hpp"

7.10. Custom service .cpp includes

#include <algorithm>
#include <boost/uuid/uuid_io.hpp>
#include <unordered_set>

7.11. Custom service methods

/**
 * @brief Lists currencies visible to a specific party, with pagination.
 *
 * Uses the party_currencies junction to filter the full currency list
 * to only those the given party is permitted to see.
 *
 * @param party_id The UUID of the party.
 * @param offset Number of records to skip.
 * @param limit Maximum number of records to return.
 * @return Vector of visible currencies for the requested page.
 */
std::vector<domain::currency> list_currencies_for_party(const boost::uuids::uuid& party_id,
                                                        std::uint32_t offset,
                                                        std::uint32_t limit);

/**
 * @brief Gets the total count of currencies visible to a specific party.
 *
 * @param party_id The UUID of the party.
 * @return Number of currencies the party is permitted to see.
 */
std::uint32_t count_currencies_for_party(const boost::uuids::uuid& party_id);

7.12. Custom service members

repository::party_currency_repository junction_repo_;

7.13. Custom service implementations

std::vector<domain::currency> currency_service::list_currencies_for_party(
    const boost::uuids::uuid& party_id, std::uint32_t offset, std::uint32_t limit) {
    BOOST_LOG_SEV(lg(), debug) << "Listing currencies for party: " << party_id
                               << " offset=" << offset << " limit=" << limit;

    const auto junctions = junction_repo_.read_latest_by_party(party_id);
    std::unordered_set<std::string> visible;
    visible.reserve(junctions.size());
    for (const auto& j : junctions)
        visible.insert(j.currency_iso_code);

    auto all = repo_.read_latest(ctx_);
    std::vector<domain::currency> filtered;
    filtered.reserve(visible.size());
    for (auto& c : all) {
        if (visible.count(c.iso_code))
            filtered.push_back(std::move(c));
    }

    if (offset >= filtered.size())
        return {};
    const auto end = std::min<std::size_t>(offset + limit, filtered.size());
    return std::vector<domain::currency>(filtered.begin() + offset, filtered.begin() + end);
}

std::uint32_t currency_service::count_currencies_for_party(const boost::uuids::uuid& party_id) {
    BOOST_LOG_SEV(lg(), debug) << "Counting currencies for party: " << party_id;
    const auto junctions = junction_repo_.read_latest_by_party(party_id);
    return static_cast<std::uint32_t>(junctions.size());
}

7.14. Custom generator declarations

/**
 * @brief Generates a set of currencies using Unicode symbols.
 *
 * Used for testing internationalisation and symbol rendering.
 */
ORES_REFDATA_API_EXPORT std::vector<domain::currency>
generate_synthetic_unicode_currencies(utility::generation::generation_context& ctx);

/**
 * @brief Generates N synthetic currencies with unique ISO codes.
 */
ORES_REFDATA_API_EXPORT std::vector<domain::currency>
generate_unique_synthetic_currencies(std::size_t n, utility::generation::generation_context& ctx);

/**
 * @brief Generates a set of fictional currencies.
 *
 * These are intentionally fake currencies with made-up ISO codes that do not
 * correspond to any real ISO 4217 codes. Useful for testing and demo
 * purposes where real currency data should not be used.
 *
 * @param n Number of currencies to generate. If n is 0 or greater than the
 *          available set (50), returns all available fictional currencies.
 */
ORES_REFDATA_API_EXPORT std::vector<domain::currency>
generate_fictional_currencies(std::size_t n, utility::generation::generation_context& ctx);

7.15. Custom generator implementations

std::vector<domain::currency>
generate_synthetic_unicode_currencies(utility::generation::generation_context& ctx) {
    const auto modified_by = ctx.env().get_or(generation_keys::modified_by, "system");
    const auto tid = ctx.env().get_or(generation_keys::tenant_id, "system");
    const auto parsed_tid = utility::uuid::tenant_id::from_string(tid);
    const auto tenant_id =
        parsed_tid.has_value() ? parsed_tid.value() : utility::uuid::tenant_id::system();

    static std::atomic<std::size_t> batch{0};
    const auto b = ++batch;
    const auto suffix = "_" + std::to_string(b);
    const auto now = ctx.past_timepoint();

    std::vector<domain::currency> r;
    r.push_back({.tenant_id = tenant_id,
                 .iso_code = "XU" + std::to_string(b),
                 .name = "Test Dollar" + suffix,
                 .numeric_code = "90001",
                 .symbol = "$",
                 .fraction_symbol = "\xC2\xA2",
                 .fractions_per_unit = 100,
                 .rounding_type = "Closest",
                 .rounding_precision = 2,
                 .format = "%3% %1$.2f",
                 .monetary_nature = "fiat",
                 .market_tier = "g10",
                 .modified_by = modified_by,
                 .change_reason_code = "system.test",
                 .change_commentary = "Synthetic test data",
                 .recorded_at = now});

    r.push_back({.tenant_id = tenant_id,
                 .iso_code = "XE" + std::to_string(b),
                 .name = "Test Euro" + suffix,
                 .numeric_code = "90002",
                 .symbol = "\xE2\x82\xAC",
                 .fraction_symbol = "\xC2\xA2",
                 .fractions_per_unit = 100,
                 .rounding_type = "Closest",
                 .rounding_precision = 2,
                 .format = "%3% %1$.2f",
                 .monetary_nature = "fiat",
                 .market_tier = "g10",
                 .modified_by = modified_by,
                 .change_reason_code = "system.test",
                 .change_commentary = "Synthetic test data",
                 .recorded_at = now});

    r.push_back({.tenant_id = tenant_id,
                 .iso_code = "XG" + std::to_string(b),
                 .name = "Test Pound" + suffix,
                 .numeric_code = "90003",
                 .symbol = "\xC2\xA3",
                 .fraction_symbol = "p",
                 .fractions_per_unit = 100,
                 .rounding_type = "Closest",
                 .rounding_precision = 2,
                 .format = "%3% %1$.2f",
                 .monetary_nature = "fiat",
                 .market_tier = "g10",
                 .modified_by = modified_by,
                 .change_reason_code = "system.test",
                 .change_commentary = "Synthetic test data",
                 .recorded_at = now});

    r.push_back({.tenant_id = tenant_id,
                 .iso_code = "XJ" + std::to_string(b),
                 .name = "Test Yen" + suffix,
                 .numeric_code = "90004",
                 .symbol = "\xC2\xA5",
                 .fraction_symbol = "",
                 .fractions_per_unit = 0,
                 .rounding_type = "Closest",
                 .rounding_precision = 0,
                 .format = "%3% %1$.2f",
                 .monetary_nature = "fiat",
                 .market_tier = "g10",
                 .modified_by = modified_by,
                 .change_reason_code = "system.test",
                 .change_commentary = "Synthetic test data",
                 .recorded_at = now});

    r.push_back({.tenant_id = tenant_id,
                 .iso_code = "XI" + std::to_string(b),
                 .name = "Test Rupee" + suffix,
                 .numeric_code = "90005",
                 .symbol = "\xE2\x82\xB9",
                 .fraction_symbol = "\xE0\xA4\xAA",
                 .fractions_per_unit = 100,
                 .rounding_type = "Closest",
                 .rounding_precision = 2,
                 .format = "%3% %1$.2f",
                 .monetary_nature = "fiat",
                 .market_tier = "g10",
                 .modified_by = modified_by,
                 .change_reason_code = "system.test",
                 .change_commentary = "Synthetic test data",
                 .recorded_at = now});

    r.push_back({.tenant_id = tenant_id,
                 .iso_code = "XB" + std::to_string(b),
                 .name = "Test Crypto" + suffix,
                 .numeric_code = "90006",
                 .symbol = "\xE2\x82\xBF",
                 .fraction_symbol = "s",
                 .fractions_per_unit = 100000000,
                 .rounding_type = "Closest",
                 .rounding_precision = 2,
                 .format = "%3% %1$.2f",
                 .monetary_nature = "fiat",
                 .market_tier = "g10",
                 .modified_by = modified_by,
                 .change_reason_code = "system.test",
                 .change_commentary = "Synthetic test data",
                 .recorded_at = now});

    r.push_back({.tenant_id = tenant_id,
                 .iso_code = "XR" + std::to_string(b),
                 .name = "Test Ruble" + suffix,
                 .numeric_code = "90007",
                 .symbol = "\xE2\x82\xBD",
                 .fraction_symbol = "\xD0\xBA",
                 .fractions_per_unit = 100,
                 .rounding_type = "Closest",
                 .rounding_precision = 2,
                 .format = "%3% %1$.2f",
                 .monetary_nature = "fiat",
                 .market_tier = "g10",
                 .modified_by = modified_by,
                 .change_reason_code = "system.test",
                 .change_commentary = "Synthetic test data",
                 .recorded_at = now});
    return r;
}

std::vector<domain::currency>
generate_unique_synthetic_currencies(std::size_t n, utility::generation::generation_context& ctx) {
    std::unordered_set<std::string> seen;
    seen.reserve(n);

    std::vector<domain::currency> r;
    r.reserve(n);

    std::size_t suffix = 0;
    while (r.size() < n) {
        auto currency = generate_synthetic_currency(ctx);
        if (!seen.insert(currency.iso_code).second) {
            auto base_code = currency.iso_code;
            do {
                currency.iso_code = base_code + std::to_string(++suffix);
            } while (!seen.insert(currency.iso_code).second);
        }
        r.push_back(std::move(currency));
    }
    return r;
}

std::vector<domain::currency>
generate_fictional_currencies(std::size_t n, utility::generation::generation_context& ctx) {
    const auto modified_by = ctx.env().get_or(generation_keys::modified_by, "system");
    const auto tid = ctx.env().get_or(generation_keys::tenant_id, "system");
    const auto parsed_tid = utility::uuid::tenant_id::from_string(tid);
    const auto tenant_id =
        parsed_tid.has_value() ? parsed_tid.value() : utility::uuid::tenant_id::system();
    const auto now = ctx.past_timepoint();

    std::vector<domain::currency> all;
    all.reserve(50);

    // Fictional currencies intentionally omit fraction_symbol. These are
    // synthetic test data; no real sub-unit symbol is needed, and
    // fractions_per_unit controls numeric precision in calculations only.
    all.push_back({.tenant_id = tenant_id, .iso_code = "XAE", .name = "Aerilonian Dollar",
                   .numeric_code = "10001", .symbol = "A$", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XAR", .name = "Arcturian Arct",
                   .numeric_code = "10002", .symbol = "Ar", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XBL", .name = "Balthorian Florin",
                   .numeric_code = "10003", .symbol = "Bf", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XBE", .name = "Bellorian Bell",
                   .numeric_code = "10004", .symbol = "Bb", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XCA", .name = "Calandrian Crown",
                   .numeric_code = "10005", .symbol = "Cc", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XCL", .name = "Caledonian Caled",
                   .numeric_code = "10006", .symbol = "Cd", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XDA", .name = "Daelorian Dinar",
                   .numeric_code = "10007", .symbol = "Dd", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XDL", .name = "Delvadian Delv",
                   .numeric_code = "10008", .symbol = "De", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XER", .name = "Eriadoran Euro",
                   .numeric_code = "10009", .symbol = "Er", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XES", .name = "Esterian Est",
                   .numeric_code = "10010", .symbol = "Es", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XFE", .name = "Felorian Franc",
                   .numeric_code = "10011", .symbol = "Ff", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XFN", .name = "Fendarian Fen",
                   .numeric_code = "10012", .symbol = "Fn", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XGA", .name = "Galdorian Galleon",
                   .numeric_code = "10013", .symbol = "Gg", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XGR", .name = "Grendorian Grend",
                   .numeric_code = "10014", .symbol = "Gr", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XHE", .name = "Helvetian Franc",
                   .numeric_code = "10015", .symbol = "Hf", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XHY", .name = "Hydronian Hyd",
                   .numeric_code = "10016", .symbol = "Hy", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XIR", .name = "Iridian Dollar",
                   .numeric_code = "10017", .symbol = "I$", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XIT", .name = "Ithacan Ith",
                   .numeric_code = "10018", .symbol = "It", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XJE", .name = "Jethronian Jet",
                   .numeric_code = "10019", .symbol = "Je", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XJO", .name = "Jorvikian Krona",
                   .numeric_code = "10020", .symbol = "Jk", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XKA", .name = "Kaelorian Krown",
                   .numeric_code = "10021", .symbol = "Kk", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XKR", .name = "Krynnish Krynn",
                   .numeric_code = "10022", .symbol = "Kr", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XLU", .name = "Luminian Lum",
                   .numeric_code = "10023", .symbol = "Lu", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XLY", .name = "Lysandrian Lira",
                   .numeric_code = "10024", .symbol = "Ly", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XMA", .name = "Maldorian Mal",
                   .numeric_code = "10025", .symbol = "Mm", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XMR", .name = "Mariposan Peso",
                   .numeric_code = "10026", .symbol = "Mp", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XNE", .name = "Nektonian Nek",
                   .numeric_code = "10027", .symbol = "Ne", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XNT", .name = "Netharian Naira",
                   .numeric_code = "10028", .symbol = "Nt", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XOR", .name = "Orinocan Bolivar",
                   .numeric_code = "10029", .symbol = "Ob", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XOL", .name = "Orlanthian Orl",
                   .numeric_code = "10030", .symbol = "Ol", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XPL", .name = "Paldorian Peso",
                   .numeric_code = "10031", .symbol = "Pp", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XPY", .name = "Pyrrhian Pyr",
                   .numeric_code = "10032", .symbol = "Py", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XQU", .name = "Quentarian Quen",
                   .numeric_code = "10033", .symbol = "Qu", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XQN", .name = "Quinarian Quetzal",
                   .numeric_code = "10034", .symbol = "Qn", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XRE", .name = "Rendellian Rend",
                   .numeric_code = "10035", .symbol = "Re", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XRI", .name = "Rivenian Ruble",
                   .numeric_code = "10036", .symbol = "Ri", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XSE", .name = "Serendian Shilling",
                   .numeric_code = "10037", .symbol = "Ss", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XSI", .name = "Sildorian Sild",
                   .numeric_code = "10038", .symbol = "Si", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XTA", .name = "Tandorian Taka",
                   .numeric_code = "10039", .symbol = "Ta", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XTE", .name = "Tenebrian Ten",
                   .numeric_code = "10040", .symbol = "Te", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XUL", .name = "Uldorian Uld",
                   .numeric_code = "10041", .symbol = "Ul", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XUT", .name = "Utopian Unit",
                   .numeric_code = "10042", .symbol = "Ut", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XVA", .name = "Valorian Valt",
                   .numeric_code = "10043", .symbol = "Vv", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XVL", .name = "Valtarian Val",
                   .numeric_code = "10044", .symbol = "Vl", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XWI", .name = "Wintervalean Won",
                   .numeric_code = "10045", .symbol = "Ww", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XWY", .name = "Wysterian Wys",
                   .numeric_code = "10046", .symbol = "Wy", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XAN", .name = "Xandrian Xan",
                   .numeric_code = "10047", .symbol = "Xa", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XEN", .name = "Xenorian Xen",
                   .numeric_code = "10048", .symbol = "Xe", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XYS", .name = "Yslandian Yen",
                   .numeric_code = "10049", .symbol = "Ys", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});
    all.push_back({.tenant_id = tenant_id, .iso_code = "XZE", .name = "Zephyrian Zephyr",
                   .numeric_code = "10050", .symbol = "Ze", .fractions_per_unit = 100,
                   .rounding_type = "Closest", .rounding_precision = 2, .format = "%3% %1$.2f",
                   .monetary_nature = "fiat", .market_tier = "g10", .modified_by = modified_by,
                   .change_reason_code = "system.test", .change_commentary = "Synthetic test data",
                   .recorded_at = now});

    if (n == 0 || n >= all.size())
        return all;

    return std::vector<domain::currency>(all.begin(), all.begin() + n);
}

7.16. Custom repository methods

7.16.1. Repository impl includes

No extra includes needed — <sqlgen/postgres.hpp>, bitemporal_operations.hpp, and helpers.hpp are already in the standard template output.


7.16.2. Repository implementations

Note: pagination (read_latest with offset/limit), get_total_currency_count, filtered read_all and batch remove are generated natively by the base repository template, tenant-aware. Only the unfiltered read_all (used by the CLI's export --all-versions without --key) has no native equivalent and remains a custom paste.

std::vector<domain::currency> currency_repository::read_all(context ctx) {
    const auto tid = ctx.tenant_id().to_string();
    const auto query = sqlgen::read<std::vector<currency_entity>> |
                       where("tenant_id"_c == tid) | order_by("valid_from"_c.desc());

    return execute_read_query<currency_entity, domain::currency>(
        ctx,
        query,
        [](const auto& entities) { return currency_mapper::map(entities); },
        lg(),
        "Reading all currencies.");
}

7.16.3. read_all (unfiltered)

/**
 * @brief Reads all currencies (all versions), unfiltered.
 */
std::vector<domain::currency> read_all(context ctx);

8. See also

Emacs 29.3 (Org mode 9.6.15)