From 50ac95a7e8b822eca334a2ad066bab460fcd8243 Mon Sep 17 00:00:00 2001 From: Sorn Maksumic Date: Sun, 21 Dec 2025 15:44:05 +0100 Subject: [PATCH] #158 Create FmpMoney value object --- config/checkstyle/checkstyle-suppressions.xml | 2 + .../FmpInvalidMinorUnitException.java | 7 + .../models/FmpBalanceSheetStatement.java | 2 +- .../FmpBalanceSheetStatementGrowth.java | 2 +- .../fmp4j/models/FmpCashFlowStatement.java | 2 +- .../models/FmpCashFlowStatementGrowth.java | 2 +- .../dev/sorn/fmp4j/models/FmpCompanies.java | 2 +- .../dev/sorn/fmp4j/models/FmpCompany.java | 2 +- .../dev/sorn/fmp4j/models/FmpEtfInfo.java | 2 +- .../sorn/fmp4j/models/FmpFinancialGrowth.java | 2 +- .../sorn/fmp4j/models/FmpIncomeStatement.java | 2 +- .../models/FmpIncomeStatementGrowth.java | 2 +- .../dev/sorn/fmp4j/models/FmpKeyMetric.java | 2 +- .../java/dev/sorn/fmp4j/models/FmpRatio.java | 2 +- .../FmpRevenueGeographicSegmentation.java | 2 +- .../models/FmpRevenueProductSegmentation.java | 2 +- .../dev/sorn/fmp4j/models/FmpSearchByCik.java | 2 +- .../sorn/fmp4j/models/FmpSearchByName.java | 2 +- .../sorn/fmp4j/models/FmpSearchBySymbol.java | 2 +- .../dev/sorn/fmp4j/types/FmpCurrency.java | 3 +- .../dev/sorn/fmp4j/types/FmpMinorUnit.java | 56 ++ .../java/dev/sorn/fmp4j/types/FmpMoney.java | 129 ++++ .../java/dev/sorn/fmp4j/utils/FmpNumbers.java | 20 + .../sorn/fmp4j/types/FmpMinorUnitTest.java | 131 ++++ .../dev/sorn/fmp4j/types/FmpMoneyTest.java | 646 ++++++++++++++++++ .../FmpBalanceSheetStatement.snapshot | Bin 2923 -> 2923 bytes .../FmpBalanceSheetStatement.version | Bin 8 -> 8 bytes .../FmpBalanceSheetStatementGrowth.snapshot | Bin 3059 -> 3059 bytes .../FmpBalanceSheetStatementGrowth.version | Bin 8 -> 8 bytes .../FmpCashFlowStatement.snapshot | Bin 2513 -> 2513 bytes .../FmpCashFlowStatement.version | Bin 8 -> 8 bytes .../FmpCashFlowStatementGrowth.snapshot | Bin 2490 -> 2490 bytes .../FmpCashFlowStatementGrowth.version | Bin 8 -> 8 bytes .../serialization/FmpCompanies.snapshot | Bin 2578 -> 2578 bytes .../models/serialization/FmpCompanies.version | Bin 8 -> 8 bytes .../models/serialization/FmpCompany.snapshot | Bin 2528 -> 2528 bytes .../models/serialization/FmpCompany.version | Bin 8 -> 8 bytes .../models/serialization/FmpEtfInfo.snapshot | Bin 2287 -> 2287 bytes .../models/serialization/FmpEtfInfo.version | Bin 8 -> 8 bytes .../serialization/FmpFinancialGrowth.snapshot | Bin 2438 -> 2438 bytes .../serialization/FmpFinancialGrowth.version | Bin 8 -> 8 bytes .../serialization/FmpIncomeStatement.snapshot | Bin 2144 -> 2144 bytes .../serialization/FmpIncomeStatement.version | Bin 8 -> 8 bytes .../FmpIncomeStatementGrowth.snapshot | Bin 2029 -> 2029 bytes .../FmpIncomeStatementGrowth.version | Bin 8 -> 8 bytes .../serialization/FmpKeyMetric.snapshot | Bin 2420 -> 2420 bytes .../models/serialization/FmpKeyMetric.version | Bin 8 -> 8 bytes .../models/serialization/FmpRatio.snapshot | Bin 3164 -> 3164 bytes .../models/serialization/FmpRatio.version | Bin 8 -> 8 bytes .../FmpRevenueGeographicSegmentation.snapshot | Bin 875 -> 875 bytes .../FmpRevenueGeographicSegmentation.version | Bin 8 -> 8 bytes .../FmpRevenueProductSegmentation.snapshot | Bin 831 -> 831 bytes .../FmpRevenueProductSegmentation.version | Bin 8 -> 8 bytes .../serialization/FmpSearchByCik.snapshot | Bin 575 -> 575 bytes .../serialization/FmpSearchByCik.version | Bin 8 -> 8 bytes .../serialization/FmpSearchByName.snapshot | Bin 461 -> 461 bytes .../serialization/FmpSearchByName.version | Bin 8 -> 8 bytes .../serialization/FmpSearchBySymbol.snapshot | Bin 463 -> 463 bytes .../serialization/FmpSearchBySymbol.version | Bin 8 -> 8 bytes 59 files changed, 1010 insertions(+), 18 deletions(-) create mode 100644 src/main/java/dev/sorn/fmp4j/exceptions/FmpInvalidMinorUnitException.java create mode 100644 src/main/java/dev/sorn/fmp4j/types/FmpMinorUnit.java create mode 100644 src/main/java/dev/sorn/fmp4j/types/FmpMoney.java create mode 100644 src/main/java/dev/sorn/fmp4j/utils/FmpNumbers.java create mode 100644 src/test/java/dev/sorn/fmp4j/types/FmpMinorUnitTest.java create mode 100644 src/test/java/dev/sorn/fmp4j/types/FmpMoneyTest.java diff --git a/config/checkstyle/checkstyle-suppressions.xml b/config/checkstyle/checkstyle-suppressions.xml index d1897346..3cc6b15f 100644 --- a/config/checkstyle/checkstyle-suppressions.xml +++ b/config/checkstyle/checkstyle-suppressions.xml @@ -25,6 +25,8 @@ + + \ No newline at end of file diff --git a/src/main/java/dev/sorn/fmp4j/exceptions/FmpInvalidMinorUnitException.java b/src/main/java/dev/sorn/fmp4j/exceptions/FmpInvalidMinorUnitException.java new file mode 100644 index 00000000..c3fb473b --- /dev/null +++ b/src/main/java/dev/sorn/fmp4j/exceptions/FmpInvalidMinorUnitException.java @@ -0,0 +1,7 @@ +package dev.sorn.fmp4j.exceptions; + +public class FmpInvalidMinorUnitException extends FmpException { + public FmpInvalidMinorUnitException(String message, Object... args) { + super(message, args); + } +} diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpBalanceSheetStatement.java b/src/main/java/dev/sorn/fmp4j/models/FmpBalanceSheetStatement.java index 4539dc95..78d5e8d5 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpBalanceSheetStatement.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpBalanceSheetStatement.java @@ -74,5 +74,5 @@ public record FmpBalanceSheetStatement( Long netDebt) implements FmpModel, FmpStatement { @Serial - private static final long serialVersionUID = 5L; + private static final long serialVersionUID = 6L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpBalanceSheetStatementGrowth.java b/src/main/java/dev/sorn/fmp4j/models/FmpBalanceSheetStatementGrowth.java index da292c8d..19271446 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpBalanceSheetStatementGrowth.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpBalanceSheetStatementGrowth.java @@ -66,5 +66,5 @@ public record FmpBalanceSheetStatementGrowth( Double growthTreasuryStock) implements FmpModel, FmpStatement { @Serial - private static final long serialVersionUID = 2L; + private static final long serialVersionUID = 3L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpCashFlowStatement.java b/src/main/java/dev/sorn/fmp4j/models/FmpCashFlowStatement.java index f8617365..adaf75bf 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpCashFlowStatement.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpCashFlowStatement.java @@ -60,5 +60,5 @@ public record FmpCashFlowStatement( Long interestPaid) implements FmpModel, FmpStatement { @Serial - private static final long serialVersionUID = 5L; + private static final long serialVersionUID = 6L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpCashFlowStatementGrowth.java b/src/main/java/dev/sorn/fmp4j/models/FmpCashFlowStatementGrowth.java index 6e5ee9e3..08881263 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpCashFlowStatementGrowth.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpCashFlowStatementGrowth.java @@ -52,5 +52,5 @@ public record FmpCashFlowStatementGrowth( Double growthInterestPaid) implements FmpModel, FmpStatement { @Serial - private static final long serialVersionUID = 2L; + private static final long serialVersionUID = 3L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpCompanies.java b/src/main/java/dev/sorn/fmp4j/models/FmpCompanies.java index 3426f1be..91aaaf8b 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpCompanies.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpCompanies.java @@ -50,5 +50,5 @@ public record FmpCompanies( Boolean isFund) implements FmpModel { @Serial - private static final long serialVersionUID = 8L; + private static final long serialVersionUID = 9L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpCompany.java b/src/main/java/dev/sorn/fmp4j/models/FmpCompany.java index fc6ab4b6..0f318d3b 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpCompany.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpCompany.java @@ -49,5 +49,5 @@ public record FmpCompany( Boolean isFund) implements FmpModel { @Serial - private static final long serialVersionUID = 8L; + private static final long serialVersionUID = 9L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpEtfInfo.java b/src/main/java/dev/sorn/fmp4j/models/FmpEtfInfo.java index af529396..01b82c36 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpEtfInfo.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpEtfInfo.java @@ -30,7 +30,7 @@ public record FmpEtfInfo( List sectorsList) implements FmpModel { @Serial - private static final long serialVersionUID = 6L; + private static final long serialVersionUID = 7L; // The first parameter is sector information, however FMP API wrongly returns as "industry" // API sample return in stable/etf/info/%3Fsymbol=SPY.json diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpFinancialGrowth.java b/src/main/java/dev/sorn/fmp4j/models/FmpFinancialGrowth.java index 6b270610..f730d19e 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpFinancialGrowth.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpFinancialGrowth.java @@ -54,5 +54,5 @@ public record FmpFinancialGrowth( Double threeYBottomLineNetIncomeGrowthPerShare) implements FmpModel, FmpStatement { @Serial - private static final long serialVersionUID = 4L; + private static final long serialVersionUID = 5L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpIncomeStatement.java b/src/main/java/dev/sorn/fmp4j/models/FmpIncomeStatement.java index cdd751d4..6bb8a32f 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpIncomeStatement.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpIncomeStatement.java @@ -52,5 +52,5 @@ public record FmpIncomeStatement( Long weightedAverageShsOutDil) implements FmpModel, FmpStatement { @Serial - private static final long serialVersionUID = 5L; + private static final long serialVersionUID = 6L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpIncomeStatementGrowth.java b/src/main/java/dev/sorn/fmp4j/models/FmpIncomeStatementGrowth.java index e174c28e..3a9007bc 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpIncomeStatementGrowth.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpIncomeStatementGrowth.java @@ -44,5 +44,5 @@ public record FmpIncomeStatementGrowth( Double growthNetIncomeDeductions) implements FmpModel, FmpStatement { @Serial - private static final long serialVersionUID = 2L; + private static final long serialVersionUID = 3L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpKeyMetric.java b/src/main/java/dev/sorn/fmp4j/models/FmpKeyMetric.java index d6dbd303..6230b320 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpKeyMetric.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpKeyMetric.java @@ -57,5 +57,5 @@ public record FmpKeyMetric( Long netCurrentAssetValue) implements FmpModel { @Serial - private static final long serialVersionUID = 4L; + private static final long serialVersionUID = 5L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpRatio.java b/src/main/java/dev/sorn/fmp4j/models/FmpRatio.java index 72418d2d..8392c836 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpRatio.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpRatio.java @@ -74,5 +74,5 @@ public record FmpRatio( Double dividendPerShare) implements FmpModel { @Serial - private static final long serialVersionUID = 4L; + private static final long serialVersionUID = 5L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpRevenueGeographicSegmentation.java b/src/main/java/dev/sorn/fmp4j/models/FmpRevenueGeographicSegmentation.java index 3ce765e1..7fb81415 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpRevenueGeographicSegmentation.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpRevenueGeographicSegmentation.java @@ -17,5 +17,5 @@ public record FmpRevenueGeographicSegmentation( Map data) implements FmpModel { @Serial - private static final long serialVersionUID = 4L; + private static final long serialVersionUID = 5L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpRevenueProductSegmentation.java b/src/main/java/dev/sorn/fmp4j/models/FmpRevenueProductSegmentation.java index 38a6df14..017911b1 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpRevenueProductSegmentation.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpRevenueProductSegmentation.java @@ -17,5 +17,5 @@ public record FmpRevenueProductSegmentation( Map data) implements FmpModel { @Serial - private static final long serialVersionUID = 4L; + private static final long serialVersionUID = 5L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpSearchByCik.java b/src/main/java/dev/sorn/fmp4j/models/FmpSearchByCik.java index 8545b010..cdcec93c 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpSearchByCik.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpSearchByCik.java @@ -10,5 +10,5 @@ public record FmpSearchByCik( FmpSymbol symbol, String companyName, FmpCik cik, FmpExchange exchange, FmpCurrency currency) implements FmpModel { @Serial - private static final long serialVersionUID = 4L; + private static final long serialVersionUID = 5L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpSearchByName.java b/src/main/java/dev/sorn/fmp4j/models/FmpSearchByName.java index e49baa74..b5e9ab87 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpSearchByName.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpSearchByName.java @@ -8,5 +8,5 @@ public record FmpSearchByName(FmpSymbol symbol, String name, FmpCurrency currency, FmpExchange exchange) implements FmpModel { @Serial - private static final long serialVersionUID = 4L; + private static final long serialVersionUID = 5L; } diff --git a/src/main/java/dev/sorn/fmp4j/models/FmpSearchBySymbol.java b/src/main/java/dev/sorn/fmp4j/models/FmpSearchBySymbol.java index b7ecde59..95ba3e37 100644 --- a/src/main/java/dev/sorn/fmp4j/models/FmpSearchBySymbol.java +++ b/src/main/java/dev/sorn/fmp4j/models/FmpSearchBySymbol.java @@ -8,5 +8,5 @@ public record FmpSearchBySymbol(FmpSymbol symbol, String name, FmpCurrency currency, FmpExchange exchange) implements FmpModel { @Serial - private static final long serialVersionUID = 3L; + private static final long serialVersionUID = 4L; } diff --git a/src/main/java/dev/sorn/fmp4j/types/FmpCurrency.java b/src/main/java/dev/sorn/fmp4j/types/FmpCurrency.java index dff43f20..3aa9de77 100644 --- a/src/main/java/dev/sorn/fmp4j/types/FmpCurrency.java +++ b/src/main/java/dev/sorn/fmp4j/types/FmpCurrency.java @@ -12,6 +12,7 @@ */ public final class FmpCurrency implements Comparable, FmpValueObject { public static final Pattern FMP_CURRENCY_PATTERN = compile("^[A-Z]{3}$"); + public static final FmpCurrency EUR = currency("EUR"); public static final FmpCurrency USD = currency("USD"); private final String value; @@ -25,7 +26,7 @@ public static FmpCurrency currency(String value) { if (value == null) { throw new FmpInvalidCurrencyException("'value' is required"); } - String normalized = value.toUpperCase(); + final var normalized = value.toUpperCase(); if (!FMP_CURRENCY_PATTERN.matcher(normalized).matches()) { throw new FmpInvalidCurrencyException( "'value' [%s] does not match pattern [%s]", value, FMP_CURRENCY_PATTERN.pattern()); diff --git a/src/main/java/dev/sorn/fmp4j/types/FmpMinorUnit.java b/src/main/java/dev/sorn/fmp4j/types/FmpMinorUnit.java new file mode 100644 index 00000000..a3c4d01a --- /dev/null +++ b/src/main/java/dev/sorn/fmp4j/types/FmpMinorUnit.java @@ -0,0 +1,56 @@ +package dev.sorn.fmp4j.types; + +import static java.lang.String.valueOf; + +import dev.sorn.fmp4j.exceptions.FmpInvalidMinorUnitException; + +public final class FmpMinorUnit implements FmpValueObject { + public static final int MIN_MINOR_UNIT_VALUE = 0; + public static final int MAX_MINOR_UNIT_VALUE = 24; + private final int value; + + private FmpMinorUnit(int value) { + if (value < 0) { + throw new FmpInvalidMinorUnitException( + "[%d] is below the minimum allowed value [%d]", value, MIN_MINOR_UNIT_VALUE); + } + if (value > MAX_MINOR_UNIT_VALUE) { + throw new FmpInvalidMinorUnitException( + "[%d] exceeds the maximum allowed value [%d]", value, MAX_MINOR_UNIT_VALUE); + } + this.value = value; + } + + public static FmpMinorUnit minorUnit(int value) { + return new FmpMinorUnit(value); + } + + @Override + public Integer value() { + return value; + } + + @Override + public String toString() { + return valueOf(value); + } + + @Override + public int hashCode() { + return value; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof FmpMinorUnit that)) { + return false; + } + return this.value == that.value; + } +} diff --git a/src/main/java/dev/sorn/fmp4j/types/FmpMoney.java b/src/main/java/dev/sorn/fmp4j/types/FmpMoney.java new file mode 100644 index 00000000..08747460 --- /dev/null +++ b/src/main/java/dev/sorn/fmp4j/types/FmpMoney.java @@ -0,0 +1,129 @@ +package dev.sorn.fmp4j.types; + +import static dev.sorn.fmp4j.utils.FmpNumbers.decimal; +import static java.lang.String.format; +import static java.math.BigDecimal.ZERO; +import static java.util.Objects.hash; + +import java.math.BigDecimal; +import java.util.function.BiFunction; + +public class FmpMoney implements Comparable { + private final FmpCurrency currency; + private final BigDecimal quantity; + + private FmpMoney(FmpCurrency currency, BigDecimal quantity) { + this.currency = currency; + this.quantity = quantity; + } + + public static FmpMoney money(FmpCurrency currency, BigDecimal quantity) { + return new FmpMoney(currency, quantity); + } + + public static FmpMoney zero(FmpCurrency currency) { + return new FmpMoney(currency, decimal(0L)); + } + + public static FmpMoney unit(FmpCurrency currency) { + return new FmpMoney(currency, decimal(1L)); + } + + public static FmpMoney thousand(FmpCurrency currency) { + return new FmpMoney(currency, decimal(1_000L)); + } + + public static FmpMoney million(FmpCurrency currency) { + return new FmpMoney(currency, decimal(1_000_000L)); + } + + public FmpCurrency currency() { + return currency; + } + + public BigDecimal quantity() { + return quantity; + } + + public boolean isPositive() { + return quantity.compareTo(ZERO) > 0; + } + + public boolean isNegative() { + return quantity.compareTo(ZERO) < 0; + } + + public boolean isZero() { + return quantity.compareTo(ZERO) == 0; + } + + public FmpMoney abs() { + return new FmpMoney(currency, quantity.abs()); + } + + public FmpMoney neg() { + return new FmpMoney(currency, quantity.negate()); + } + + public FmpMoney add(FmpMoney that) { + return perform(that, "add", BigDecimal::add); + } + + public FmpMoney sub(FmpMoney that) { + return perform(that, "sub", BigDecimal::subtract); + } + + public FmpMoney mul(FmpMoney that) { + return perform(that, "mul", BigDecimal::multiply); + } + + public FmpMoney div(FmpMoney that) { + return perform(that, "div", BigDecimal::divide); + } + + public int compareTo(FmpMoney money) { + final var that = checkThat(money, "cmp"); + return this.quantity.compareTo(that.quantity); + } + + @Override + public String toString() { + return currency.toString() + " " + quantity; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof FmpMoney that)) { + return false; + } + if (!this.currency.equals(that.currency)) { + return false; + } + return this.quantity.compareTo(that.quantity) == 0; + } + + @Override + public int hashCode() { + return hash(currency.hashCode(), quantity); + } + + private FmpMoney perform(FmpMoney that, String opName, BiFunction op) { + final var money = checkThat(that, opName); + return new FmpMoney(currency, op.apply(this.quantity, money.quantity)); + } + + private FmpMoney checkThat(FmpMoney that, String opName) { + if (!this.currency.equals(that.currency)) { + throw new IllegalArgumentException(format( + "Cannot apply operation [%s] for different currencies [%s] and [%s]", + opName, this.currency, that.currency)); + } + return that; + } +} diff --git a/src/main/java/dev/sorn/fmp4j/utils/FmpNumbers.java b/src/main/java/dev/sorn/fmp4j/utils/FmpNumbers.java new file mode 100644 index 00000000..dc254d70 --- /dev/null +++ b/src/main/java/dev/sorn/fmp4j/utils/FmpNumbers.java @@ -0,0 +1,20 @@ +package dev.sorn.fmp4j.utils; + +import static java.math.RoundingMode.HALF_EVEN; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class FmpNumbers { + public static BigDecimal decimal(double value) { + return decimal(value, 2, HALF_EVEN); + } + + public static BigDecimal decimal(double value, int scale, RoundingMode mode) { + return BigDecimal.valueOf(value).setScale(scale, mode); + } + + private FmpNumbers() { + // prevent direct instantiation + } +} diff --git a/src/test/java/dev/sorn/fmp4j/types/FmpMinorUnitTest.java b/src/test/java/dev/sorn/fmp4j/types/FmpMinorUnitTest.java new file mode 100644 index 00000000..3515eb40 --- /dev/null +++ b/src/test/java/dev/sorn/fmp4j/types/FmpMinorUnitTest.java @@ -0,0 +1,131 @@ +package dev.sorn.fmp4j.types; + +import static dev.sorn.fmp4j.types.FmpLimit.limit; +import static dev.sorn.fmp4j.types.FmpMinorUnit.MAX_MINOR_UNIT_VALUE; +import static dev.sorn.fmp4j.types.FmpMinorUnit.MIN_MINOR_UNIT_VALUE; +import static dev.sorn.fmp4j.types.FmpMinorUnit.minorUnit; +import static java.lang.String.format; +import static java.lang.String.valueOf; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import dev.sorn.fmp4j.exceptions.FmpInvalidMinorUnitException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class FmpMinorUnitTest { + @ParameterizedTest(name = "[{index}]") + @ValueSource(ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}) + void valid_minor_unit(int limit) { + // given // when + var minorUnit = minorUnit(limit); + + // then + assertThat(minorUnit.value()).isEqualTo(limit); + } + + @Test + void below_minimum_minor_unit() { + // given + var minorUnit = -1; + + // when // then + assertThatThrownBy(() -> minorUnit(minorUnit)) + .isInstanceOf(FmpInvalidMinorUnitException.class) + .hasMessage(format("[%d] is below the minimum allowed value [%d]", minorUnit, MIN_MINOR_UNIT_VALUE)); + } + + @Test + void exceeds_maximum_minor_unit() { + // given + var minorUnit = 25; + + // when // then + assertThatThrownBy(() -> minorUnit(minorUnit)) + .isInstanceOf(FmpInvalidMinorUnitException.class) + .hasMessage(format("[%d] exceeds the maximum allowed value [%d]", minorUnit, MAX_MINOR_UNIT_VALUE)); + } + + @ParameterizedTest(name = "[{index}]") + @ValueSource(ints = {2, 3}) + void toString_returns_value(int limit) { + // given // when + var minorUnit = minorUnit(limit); + + // then + assertThat(minorUnit.toString()).isEqualTo(valueOf(limit)); + } + + @Test + void hash_code_value() { + // given + var i = 3; + var minorUnit = minorUnit(i); + + // when + var hc = minorUnit.hashCode(); + + // then + assertThat(hc).isEqualTo(i); + } + + @Test + void equals_same_true() { + // given + var minorUnit = minorUnit(10); + + // when + var eq = minorUnit.equals(minorUnit); + + assertThat(eq).isTrue(); + } + + @Test + void equals_identical_true() { + // given + var minorUnit1 = limit(10); + var minorUnit2 = limit(10); + + // when + var eq = minorUnit1.equals(minorUnit2); + + assertThat(eq).isTrue(); + } + + @Test + void equals_null_false() { + // given + var minorUnit1 = limit(3); + var minorUnit2 = (FmpLimit) null; + + // when + var eq = minorUnit1.equals(minorUnit2); + + assertThat(eq).isFalse(); + } + + @Test + void equals_different_false() { + // given + var minorUnit1 = limit(3); + var minorUnit2 = limit(5); + + // when + var eq = minorUnit1.equals(minorUnit2); + + assertThat(eq).isFalse(); + } + + @Test + void equals_wrong_instance_false() { + // given + var minorUnit1 = limit(1); + var minorUnit2 = 3; + + // when + var eq = minorUnit1.equals(minorUnit2); + + assertThat(eq).isFalse(); + } +} diff --git a/src/test/java/dev/sorn/fmp4j/types/FmpMoneyTest.java b/src/test/java/dev/sorn/fmp4j/types/FmpMoneyTest.java new file mode 100644 index 00000000..e7968a48 --- /dev/null +++ b/src/test/java/dev/sorn/fmp4j/types/FmpMoneyTest.java @@ -0,0 +1,646 @@ +package dev.sorn.fmp4j.types; + +import static dev.sorn.fmp4j.types.FmpCurrency.EUR; +import static dev.sorn.fmp4j.types.FmpCurrency.USD; +import static dev.sorn.fmp4j.types.FmpMoney.million; +import static dev.sorn.fmp4j.types.FmpMoney.money; +import static dev.sorn.fmp4j.types.FmpMoney.thousand; +import static dev.sorn.fmp4j.types.FmpMoney.unit; +import static dev.sorn.fmp4j.types.FmpMoney.zero; +import static dev.sorn.fmp4j.utils.FmpNumbers.decimal; +import static java.util.Objects.hash; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; + +import java.util.function.BiFunction; +import org.junit.jupiter.api.Test; + +class FmpMoneyTest { + @Test + void creates_money() { + // given + var currency = USD; + var quantity = decimal(1000); + + // when + var money = money(currency, quantity); + + // then + assertThat(money.currency()).isEqualTo(currency); + assertThat(money.quantity()).isEqualTo(decimal(1000L)); + } + + @Test + void zero_quantity_from_currency() { + // given + var currency = USD; + + // when + var money = zero(currency); + + // then + assertThat(money.currency()).isEqualTo(USD); + assertThat(money.quantity()).isEqualTo(decimal(0L)); + } + + @Test + void unit_quantity_from_currency() { + // given + var currency = USD; + + // when + var money = unit(currency); + + // then + assertThat(money.currency()).isEqualTo(USD); + assertThat(money.quantity()).isEqualTo(decimal(1L)); + } + + @Test + void thousand_from_currency() { + // given + var currency = USD; + + // when + var money = thousand(currency); + + // then + assertThat(money.currency()).isEqualTo(USD); + assertThat(money.quantity()).isEqualTo(decimal(1_000L)); + } + + @Test + void million_from_currency() { + // given + var currency = USD; + + // when + var money = million(currency); + + // then + assertThat(money.currency()).isEqualTo(USD); + assertThat(money.quantity()).isEqualTo(decimal(1_000_000L)); + } + + @Test + void is_positive_returns_true_only_when_positive() { + // given + var positive = money(USD, decimal(1)); + var negative = money(USD, decimal(-1)); + var zero = zero(USD); + + // when // then + assertThat(positive.isPositive()).isTrue(); + assertThat(negative.isPositive()).isFalse(); + assertThat(zero.isPositive()).isFalse(); + } + + @Test + void is_negative_returns_true_only_when_negative() { + // given + var positive = money(USD, decimal(1)); + var negative = money(USD, decimal(-1)); + var zero = zero(USD); + + // when // then + assertThat(positive.isNegative()).isFalse(); + assertThat(negative.isNegative()).isTrue(); + assertThat(zero.isNegative()).isFalse(); + } + + @Test + void is_zero_returns_true_only_when_zero() { + // given + var positive = money(USD, decimal(1)); + var negative = money(USD, decimal(-1)); + var zero = zero(USD); + + // when // then + assertThat(positive.isZero()).isFalse(); + assertThat(negative.isZero()).isFalse(); + assertThat(zero.isZero()).isTrue(); + } + + @Test + void equals_returns_true_when_equal() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(1)); + + // when + var eq = money1.equals(money2); + + // then + assertThat(eq).isTrue(); + } + + @Test + void equals_returns_false_when_not_equal() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(2)); + + // when + var eq = money1.equals(money2); + + // then + assertThat(eq).isFalse(); + } + + @Test + void abs_of_positive_returns_positive() { + // given + var money = money(USD, decimal(1)); + + // when + var abs = money.abs(); + + // then + assertThat(abs).isEqualTo(money(USD, decimal(1))); + } + + @Test + void abs_of_negative_returns_positive() { + // given + var money = money(USD, decimal(-1)); + + // when + var abs = money.abs(); + + // then + assertThat(abs).isEqualTo(money(USD, decimal(1))); + } + + @Test + void abs_of_zero_returns_zero() { + // given + var money = zero(USD); + + // when + var abs = money.abs(); + + // then + assertThat(abs).isEqualTo(zero(USD)); + } + + @Test + void abs_of_negative_zero_returns_zero() { + // given + var money = money(USD, decimal(-0)); + + // when + var abs = money.abs(); + + // then + assertThat(abs).isEqualTo(zero(USD)); + } + + @Test + void neg_of_positive_returns_negative() { + // given + var money = money(USD, decimal(1)); + + // when + var neg = money.neg(); + + // then + assertThat(neg).isEqualTo(money(USD, decimal(-1))); + } + + @Test + void neg_of_negative_returns_positive() { + // given + var money = money(USD, decimal(-1)); + + // when + var neg = money.neg(); + + // then + assertThat(neg).isEqualTo(money(USD, decimal(1))); + } + + @Test + void neg_of_zero_returns_zero() { + // given + var money = zero(USD); + + // when + var neg = money.neg(); + + // then + assertThat(neg).isEqualTo(money); + } + + @Test + void add_positive_with_positive() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(2)); + + // when + var sum = money1.add(money2); + + // then + assertThat(sum).isEqualTo(money(USD, decimal(3))); + } + + @Test + void add_positive_with_negative() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(-2)); + + // when + var sum = money1.add(money2); + + // then + assertThat(sum).isEqualTo(money(USD, decimal(-1))); + } + + @Test + void add_negative_with_positive() { + // given + var money1 = money(USD, decimal(-1)); + var money2 = money(USD, decimal(2)); + + // when + var sum = money1.add(money2); + + // then + assertThat(sum).isEqualTo(money(USD, decimal(1))); + } + + @Test + void add_positive_with_zero() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(0)); + + // when + var sum = money1.add(money2); + + // then + assertThat(sum).isEqualTo(money1); + } + + @Test + void add_negative_with_zero() { + // given + var money1 = money(USD, decimal(-1)); + var money2 = money(USD, decimal(0)); + + // when + var sum = money1.add(money2); + + // then + assertThat(sum).isEqualTo(money1); + } + + @Test + void add_different_units_throws() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(EUR, decimal(1)); + + // when + BiFunction f = FmpMoney::add; + + // then + assertThatThrownBy(() -> f.apply(money1, money2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Cannot apply operation [add] for different currencies [USD] and [EUR]"); + } + + @Test + void sub_positive_with_positive() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(2)); + + // when + var diff = money1.sub(money2); + + // then + assertThat(diff).isEqualTo(money(USD, decimal(-1))); + } + + @Test + void sub_positive_with_negative() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(-2)); + + // when + var diff = money1.sub(money2); + + // then + assertThat(diff).isEqualTo(money(USD, decimal(3))); + } + + @Test + void sub_negative_with_positive() { + // given + var money1 = money(USD, decimal(-1)); + var money2 = money(USD, decimal(2)); + + // when + var diff = money1.sub(money2); + + // then + assertThat(diff).isEqualTo(money(USD, decimal(-3))); + } + + @Test + void sub_positive_with_zero() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(0)); + + // when + var diff = money1.sub(money2); + + // then + assertThat(diff).isEqualTo(money1); + } + + @Test + void sub_negative_with_zero() { + // given + var money1 = money(USD, decimal(-1)); + var money2 = money(USD, decimal(0)); + + // when + var diff = money1.sub(money2); + + // then + assertThat(diff).isEqualTo(money1); + } + + @Test + void sub_different_units_throws() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(EUR, decimal(1)); + + // when + BiFunction f = FmpMoney::sub; + + // then + assertThatThrownBy(() -> f.apply(money1, money2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Cannot apply operation [sub] for different currencies [USD] and [EUR]"); + } + + @Test + void mul_positive_with_positive() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(2)); + + // when + var product = money1.mul(money2); + + // then + assertThat(product).isEqualTo(money(USD, decimal(2))); + } + + @Test + void mul_negative_with_negative() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(-2)); + + // when + var product = money1.mul(money2); + + // then + assertThat(product).isEqualTo(money(USD, decimal(-2))); + } + + @Test + void mul_different_units_throws() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(EUR, decimal(1)); + + // when + BiFunction f = FmpMoney::mul; + + // then + assertThatThrownBy(() -> f.apply(money1, money2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Cannot apply operation [mul] for different currencies [USD] and [EUR]"); + } + + @Test + void div_positive_with_positive() { + // given + var money1 = money(USD, decimal(420)); + var money2 = money(USD, decimal(28)); + + // when + var quotient = money1.div(money2); + + // then + assertThat(quotient).isEqualTo(money(USD, decimal(15))); + } + + @Test + void div_positive_with_negative() { + // given + var money1 = money(USD, decimal(20)); + var money2 = money(USD, decimal(-10)); + + // when + var quotient = money1.div(money2); + + // then + assertThat(quotient).isEqualTo(money(USD, decimal(-2))); + } + + @Test + void div_positive_by_zero_amount_throws() { + // given + var money1 = money(USD, decimal(1)); + var money2 = zero(USD); + + // when + BiFunction f = FmpMoney::div; + + // then + assertThatThrownBy(() -> f.apply(money1, money2)) + .isInstanceOf(RuntimeException.class) + .hasMessage("Division by zero"); + } + + @Test + void div_different_units_throws() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(EUR, decimal(1)); + + // when + BiFunction f = FmpMoney::div; + + // then + assertThatThrownBy(() -> f.apply(money1, money2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Cannot apply operation [div] for different currencies [USD] and [EUR]"); + } + + @Test + void to_string_returns_currency_code_space_quantity() { + // given + var money = money(USD, decimal(42)); + + // when + var str = money.toString(); + + // then + assertThat(str).isEqualTo("USD 42.00"); + } + + @Test + void hash_code_is_hash_of_currency_and_quantity() { + // given + var money = money(USD, decimal(42)); + + // when + var hc = money.hashCode(); + + // then + assertThat(hc).isEqualTo(hash(USD, decimal(42L))); + } + + @Test + void equals_same_true() { + // given + var money = money(USD, decimal(42)); + + // when + var eq = money.equals(money); + + // then + assertThat(eq).isTrue(); + } + + @Test + void equals_identical_true() { + // given + var money1 = money(USD, decimal(42)); + var money2 = money(USD, decimal(42)); + + // when + var eq = money1.equals(money2); + + // then + assertThat(eq).isTrue(); + } + + @Test + void equals_null_false() { + // given + var money1 = money(USD, decimal(13)); + var money2 = (FmpMoney) null; + + // when + var eq = money1.equals(money2); + + // then + assertThat(eq).isFalse(); + } + + @Test + void equals_different_currency_false() { + // given + var money1 = money(USD, decimal(13)); + var money2 = money(EUR, decimal(13)); + + // when + var eq = money1.equals(money2); + + // then + assertThat(eq).isFalse(); + } + + @Test + void equals_different_quantity_false() { + // given + var money1 = money(USD, decimal(13)); + var money2 = money(USD, decimal(23)); + + // when + var eq = money1.equals(money2); + + // then + assertThat(eq).isFalse(); + } + + @Test + void equals_wrong_instance_false() { + // given + var money1 = money(USD, decimal(13)); + var money2 = mock(Object.class); + + // when + var eq = money1.equals(money2); + + // then + assertThat(eq).isFalse(); + } + + @Test + void compare_to_greater_than() { + // given + var money1 = money(USD, decimal(2)); + var money2 = money(USD, decimal(1)); + + // when + var cmp = money1.compareTo(money2); + + // then + assertThat(cmp).isEqualTo(1); + } + + @Test + void compare_to_less_than() { + // given + var money1 = money(USD, decimal(1)); + var money2 = money(USD, decimal(2)); + + // when + var cmp = money1.compareTo(money2); + + // then + assertThat(cmp).isEqualTo(-1); + } + + @Test + void compare_to_equal() { + // given + var money1 = money(USD, decimal(42)); + var money2 = money(USD, decimal(42)); + + // when + var cmp = money1.compareTo(money2); + + // then + assertThat(cmp).isEqualTo(0); + } + + @Test + void compare_to_different_units_throws() { + // given + var money1 = money(USD, decimal(13)); + var money2 = money(EUR, decimal(13)); + + // when + BiFunction f = Comparable::compareTo; + + // then + assertThatThrownBy(() -> f.apply(money1, money2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Cannot apply operation [cmp] for different currencies [USD] and [EUR]"); + } +} diff --git a/src/testFixtures/resources/models/serialization/FmpBalanceSheetStatement.snapshot b/src/testFixtures/resources/models/serialization/FmpBalanceSheetStatement.snapshot index fcbfe162c36665b7b45952544fa1a1bc4a8302a6..c7e7e4220e2ea6580ff0ebdc044478420a696e09 100644 GIT binary patch delta 26 icmaDY_F8O$EhF1TyX%}BYnx{zF8#Gmd9y5+A0q&i913s% delta 26 icmaDY_F8O$EhFnjyX%}B-R|4+6^_4`-z>}J#|Qw7zX`$s diff --git a/src/testFixtures/resources/models/serialization/FmpBalanceSheetStatement.version b/src/testFixtures/resources/models/serialization/FmpBalanceSheetStatement.version index 62f3e6fff7af10a35059124bcb1c4f486e18abed..fa902fa8b4ec3b0b75d9e4917b34547e68e2913d 100644 GIT binary patch literal 8 LcmZQz00TAv01f~L literal 8 LcmZQz00UM401W^J diff --git a/src/testFixtures/resources/models/serialization/FmpBalanceSheetStatementGrowth.snapshot b/src/testFixtures/resources/models/serialization/FmpBalanceSheetStatementGrowth.snapshot index 11f64d26efc0fdb32168bce6ca7b453a740a8014..a91a4c4c6677c29840ffc2a0919c1f3f84c281fc 100644 GIT binary patch delta 25 hcmew?{#ks2Gb8gx7aMMlwaqgUm;PF(Jh_8A8vujj3R(aF delta 25 hcmew?{#ks2Gb7VR7aMMlZuf2Z3di5ePwwE(1^|6D39JAB diff --git a/src/testFixtures/resources/models/serialization/FmpBalanceSheetStatementGrowth.version b/src/testFixtures/resources/models/serialization/FmpBalanceSheetStatementGrowth.version index ccfcbf4136d7788a93b96bb14565bcc4ddf6c4d7..29ce11cc9c2acfbfd357e04485500314b13afbb5 100644 GIT binary patch literal 8 LcmZQz00U+K01E&F literal 8 LcmZQz00Slf015yD diff --git a/src/testFixtures/resources/models/serialization/FmpCashFlowStatement.snapshot b/src/testFixtures/resources/models/serialization/FmpCashFlowStatement.snapshot index adf103a2f14d45d71d623882fb135a482f2d9301..bb7d48687eeb09e623885ffeaa22f2fe4f1a2246 100644 GIT binary patch delta 25 hcmca8d{KCUB_rELD=toswaqgUm;PF(JlTh{6##ef38er4 delta 25 hcmca8d{KCUB_r!bD=tosZuf2Z3di5ePxj$#1pskE2=@R0 diff --git a/src/testFixtures/resources/models/serialization/FmpCashFlowStatement.version b/src/testFixtures/resources/models/serialization/FmpCashFlowStatement.version index 62f3e6fff7af10a35059124bcb1c4f486e18abed..fa902fa8b4ec3b0b75d9e4917b34547e68e2913d 100644 GIT binary patch literal 8 LcmZQz00TAv01f~L literal 8 LcmZQz00UM401W^J diff --git a/src/testFixtures/resources/models/serialization/FmpCashFlowStatementGrowth.snapshot b/src/testFixtures/resources/models/serialization/FmpCashFlowStatementGrowth.snapshot index 450f63284af6b67965f145b9a4284f09ee379b26..cf10f85ec1484f4903a4754db171d8dfac177721 100644 GIT binary patch delta 25 hcmdlbyi0h3JtOl*2X;=5waqgUm;PF(JlUT!8vt|#31$EQ delta 25 hcmdlbyi0h3JtNab2X;=5Zuf2Z3di5ePxj}`1^{hV2)F!OAFip delta 30 mcmbOvGD&2DAtT2|qjM}A-R|4+6^_4`pZt+SWU~zGHx>YhDtqX?$ delta 26 icmaDL{6KhuJ|o9QgKaDv-R|4+6^_4`-~5i{6AJ)}Pzu=q diff --git a/src/testFixtures/resources/models/serialization/FmpCompany.version b/src/testFixtures/resources/models/serialization/FmpCompany.version index d9e6aa615b956553ed1ed6dae0706469d4755209..9a6f654a2b1fe7f7cba4b266715a7a764968b486 100644 GIT binary patch literal 8 LcmZQz00T|{01*HR literal 8 LcmZQz00RyH01yBP diff --git a/src/testFixtures/resources/models/serialization/FmpEtfInfo.snapshot b/src/testFixtures/resources/models/serialization/FmpEtfInfo.snapshot index 91c40749a4b0ae7cc5d79df92f357c246c5053ef..55fea872f236feb8c40bf2f7f975ee70f3b68f99 100644 GIT binary patch delta 30 mcmaDa_+D^=J|p`^107b5waqgUm;PF(Joy8Q$mR;xa%KRx;|st5 delta 30 mcmaDa_+D^=J|o*k107b5Zuf2Z3di5ePyWCnvbln_oEZSE&I=L% diff --git a/src/testFixtures/resources/models/serialization/FmpEtfInfo.version b/src/testFixtures/resources/models/serialization/FmpEtfInfo.version index fa902fa8b4ec3b0b75d9e4917b34547e68e2913d..379d85ced69049230006887a8ba1241e30c6e7df 100644 GIT binary patch literal 8 LcmZQz00VXa01p5N literal 8 LcmZQz00TAv01f~L diff --git a/src/testFixtures/resources/models/serialization/FmpFinancialGrowth.snapshot b/src/testFixtures/resources/models/serialization/FmpFinancialGrowth.snapshot index 45a2d65cf6669ab51080783a38769dbcfaf3828a..958e806d5c9223bcf9803160429ee1057d4a984d 100644 GIT binary patch delta 26 icmZn@ZWEqh&d9paLX?AJZS#!8rN7oGZw}=!WCQ?nObF=! delta 26 hcmZn@ZWEqh&d9RSLX?A}+kIQU!twX=n?pGa83AkW2s;1( diff --git a/src/testFixtures/resources/models/serialization/FmpFinancialGrowth.version b/src/testFixtures/resources/models/serialization/FmpFinancialGrowth.version index eb529631c5a3c8b3de17f3b5aa25a95498f74e2e..62f3e6fff7af10a35059124bcb1c4f486e18abed 100644 GIT binary patch literal 8 LcmZQz00UM401W^J literal 8 LcmZQz00R~P01N;H diff --git a/src/testFixtures/resources/models/serialization/FmpIncomeStatement.snapshot b/src/testFixtures/resources/models/serialization/FmpIncomeStatement.snapshot index ffaef516db86489c1f74d4c8dd00533cff61d53b..4427d27295275322a44060d08de2a8bec87c1f08 100644 GIT binary patch delta 25 hcmaDL@IYXKIV0OfiyU^2waqgUm;PF(Jb4ZK765?U3Z?)6 delta 25 hcmaDL@IYXKIV0;viyU^2Zuf2Z3di5ePhP{m1ps<23HSg2 diff --git a/src/testFixtures/resources/models/serialization/FmpIncomeStatement.version b/src/testFixtures/resources/models/serialization/FmpIncomeStatement.version index 62f3e6fff7af10a35059124bcb1c4f486e18abed..fa902fa8b4ec3b0b75d9e4917b34547e68e2913d 100644 GIT binary patch literal 8 LcmZQz00TAv01f~L literal 8 LcmZQz00UM401W^J diff --git a/src/testFixtures/resources/models/serialization/FmpIncomeStatementGrowth.snapshot b/src/testFixtures/resources/models/serialization/FmpIncomeStatementGrowth.snapshot index fa78c697cc88b8f628e688f6397b3687da38a040..0df0c32c6f09e617d5bb952017d1f806dc591c2e 100644 GIT binary patch delta 25 hcmaFM|CWD(EhFxDlwaqgUm;PF(Jb5nnegJ>v3YY)@ delta 25 hcmca3aYtf;E+flEy>xDlZuf2Z3di5ePoB%Y9{_na3F-g< diff --git a/src/testFixtures/resources/models/serialization/FmpRatio.version b/src/testFixtures/resources/models/serialization/FmpRatio.version index eb529631c5a3c8b3de17f3b5aa25a95498f74e2e..62f3e6fff7af10a35059124bcb1c4f486e18abed 100644 GIT binary patch literal 8 LcmZQz00UM401W^J literal 8 LcmZQz00R~P01N;H diff --git a/src/testFixtures/resources/models/serialization/FmpRevenueGeographicSegmentation.snapshot b/src/testFixtures/resources/models/serialization/FmpRevenueGeographicSegmentation.snapshot index eebdbf731e30528b7d98d9bc07ba0f877c89870c..d2d730990da709c46bda8c7ef73496a104df7000 100644 GIT binary patch delta 12 TcmaFO_L^;iD+J=RZsU9O493 delta 12 Tcmdnbwx4Z+6C=w;=RZsU9Nh#| diff --git a/src/testFixtures/resources/models/serialization/FmpRevenueProductSegmentation.version b/src/testFixtures/resources/models/serialization/FmpRevenueProductSegmentation.version index eb529631c5a3c8b3de17f3b5aa25a95498f74e2e..62f3e6fff7af10a35059124bcb1c4f486e18abed 100644 GIT binary patch literal 8 LcmZQz00UM401W^J literal 8 LcmZQz00R~P01N;H diff --git a/src/testFixtures/resources/models/serialization/FmpSearchByCik.snapshot b/src/testFixtures/resources/models/serialization/FmpSearchByCik.snapshot index 7382ec5dd2ed8e541683fef169dd234a2742c77d..9f345944a97ace8e510f5fa8412e77f5c88a0dbd 100644 GIT binary patch delta 25 hcmdnbvY%ywF(d0nlR!p}waqgUm;PF(Jh_)~699FN3Hty5 delta 25 hcmdnbvY%ywF(b=HlR!p}Zuf2Z3di5ePwr*h1ORT|2~7Y1 diff --git a/src/testFixtures/resources/models/serialization/FmpSearchByCik.version b/src/testFixtures/resources/models/serialization/FmpSearchByCik.version index eb529631c5a3c8b3de17f3b5aa25a95498f74e2e..62f3e6fff7af10a35059124bcb1c4f486e18abed 100644 GIT binary patch literal 8 LcmZQz00UM401W^J literal 8 LcmZQz00R~P01N;H diff --git a/src/testFixtures/resources/models/serialization/FmpSearchByName.snapshot b/src/testFixtures/resources/models/serialization/FmpSearchByName.snapshot index 2ad891ac002a3ea1e842f9a42cd946343ac51ab3..272742471942fbbe24a8236ddbf6ac3a8b8ea78f 100644 GIT binary patch delta 24 gcmX@he3p5F2_x%7(~BHyn`b00{k2YcG9Tl90C)rn1ONa4 delta 24 gcmX@he3p5F2_wry(~BJ4?%VPej=z_m%*VJN0C83cRsaA1 diff --git a/src/testFixtures/resources/models/serialization/FmpSearchByName.version b/src/testFixtures/resources/models/serialization/FmpSearchByName.version index eb529631c5a3c8b3de17f3b5aa25a95498f74e2e..62f3e6fff7af10a35059124bcb1c4f486e18abed 100644 GIT binary patch literal 8 LcmZQz00UM401W^J literal 8 LcmZQz00R~P01N;H diff --git a/src/testFixtures/resources/models/serialization/FmpSearchBySymbol.snapshot b/src/testFixtures/resources/models/serialization/FmpSearchBySymbol.snapshot index 26b6ced820f15e8f94f91fffaa59cb67f963fe39..0be558e3175e08d3eb72e304b2d182bb4dfe7af5 100644 GIT binary patch delta 24 gcmX@le4crN86(R?^NSp7n`b00{k2YcvH;_L0C<@S4FCWD delta 24 gcmX@le4crN86)#V^NSqa?%VPej=z_mEWo%Q0CDRHUjP6A diff --git a/src/testFixtures/resources/models/serialization/FmpSearchBySymbol.version b/src/testFixtures/resources/models/serialization/FmpSearchBySymbol.version index 29ce11cc9c2acfbfd357e04485500314b13afbb5..eb529631c5a3c8b3de17f3b5aa25a95498f74e2e 100644 GIT binary patch literal 8 LcmZQz00R~P01N;H literal 8 LcmZQz00U+K01E&F