Files
Finlytic/FinlyticApp/lib/features/asset_detail/models/fundamental_data_model.dart
T

305 lines
13 KiB
Dart

import 'package:equatable/equatable.dart';
import 'ticker_model.dart';
import 'company_officer_model.dart';
import 'financial_statement_model.dart';
import 'forward_estimate_model.dart';
export 'ticker_model.dart';
export 'company_officer_model.dart';
export 'financial_statement_model.dart';
export 'forward_estimate_model.dart';
class FundamentalDataModel extends Equatable {
final String isin;
final String primaryTicker;
final String ticker;
final String companyName;
final String? exchange;
final String? tradingCurrency;
final String? businessSummary;
final String? sector;
final String? industry;
final String? country;
final int? employees;
final double currentPrice;
final double dayChangeAbsolute;
final double dayChangePercent;
final double? fiftyTwoWeekHigh;
final double? fiftyTwoWeekLow;
final double? marketCapitalization;
final double? enterpriseValue;
final double? peRatioTrailing;
final double? peRatioForward;
final double? pegRatio;
final double? pbRatio;
final double? psRatio;
final double? evToEbitda;
final double? evToRevenue;
final double? totalRevenue;
final double? revenueGrowthYoY;
final double? grossProfit;
final double? ebitda;
final double? dilutedEps;
final double? totalCash;
final double? totalDebt;
final double? operatingCashFlow;
final double? freeCashFlow;
final double? grossMargin;
final double? operatingMargin;
final double? netProfitMargin;
final double? returnOnEquity;
final double? returnOnAssets;
final double? returnOnInvestedCapital;
final double? debtToEquity;
final double? currentRatio;
final double? quickRatio;
final double? interestCoverage;
final double? dividendYield;
final double? payoutRatio;
final String? exDividendDate;
final String? nextEarningsDate;
final double? percentHeldByInstitutions;
final double? percentHeldByInsiders;
final double? shortRatio;
final double? shortPercentOfFloat;
final String? consensusRating;
final double? priceTargetLow;
final double? priceTargetHigh;
final double? priceTargetMedian;
final double? priceTargetMean;
final List<CompanyExecutiveModel> executives;
final List<FinancialStatementModel> financialStatements;
final List<ForwardEstimateModel> estimates;
final List<TickerModel> availableTickers;
const FundamentalDataModel({
required this.isin,
required this.primaryTicker,
required this.ticker,
required this.companyName,
this.exchange,
this.tradingCurrency,
this.businessSummary,
this.sector,
this.industry,
this.country,
this.employees,
required this.currentPrice,
required this.dayChangeAbsolute,
required this.dayChangePercent,
this.fiftyTwoWeekHigh,
this.fiftyTwoWeekLow,
this.marketCapitalization,
this.enterpriseValue,
this.peRatioTrailing,
this.peRatioForward,
this.pegRatio,
this.pbRatio,
this.psRatio,
this.evToEbitda,
this.evToRevenue,
this.totalRevenue,
this.revenueGrowthYoY,
this.grossProfit,
this.ebitda,
this.dilutedEps,
this.totalCash,
this.totalDebt,
this.operatingCashFlow,
this.freeCashFlow,
this.grossMargin,
this.operatingMargin,
this.netProfitMargin,
this.returnOnEquity,
this.returnOnAssets,
this.returnOnInvestedCapital,
this.debtToEquity,
this.currentRatio,
this.quickRatio,
this.interestCoverage,
this.dividendYield,
this.payoutRatio,
this.exDividendDate,
this.nextEarningsDate,
this.percentHeldByInstitutions,
this.percentHeldByInsiders,
this.shortRatio,
this.shortPercentOfFloat,
this.consensusRating,
this.priceTargetLow,
this.priceTargetHigh,
this.priceTargetMedian,
this.priceTargetMean,
required this.executives,
required this.financialStatements,
required this.estimates,
this.availableTickers = const [],
});
factory FundamentalDataModel.fromJson(Map<String, dynamic> json) {
double? parseNullableDouble(dynamic val) {
if (val == null) return null;
if (val is num) return val.toDouble();
return double.tryParse(val.toString());
}
final assetMap = json['asset'] is Map<String, dynamic> ? json['asset'] as Map<String, dynamic> : null;
final fundMap = json['fundamentals'] is Map<String, dynamic> ? json['fundamentals'] as Map<String, dynamic> : null;
String extractTickerStr(dynamic val) {
if (val == null) return '';
if (val is Map<String, dynamic>) {
return val['ticker']?.toString() ?? '';
}
return val.toString();
}
String? extractExchangeStr(dynamic val) {
if (val == null) return null;
if (val is Map<String, dynamic>) {
return val['exchange']?.toString();
}
return null;
}
final isinVal = assetMap?['isin']?.toString() ?? json['isin']?.toString() ?? '';
final primaryTickerVal = extractTickerStr(assetMap?['primaryTicker'] ?? json['primaryTicker']);
final tickerVal = extractTickerStr(fundMap?['ticker'] ?? json['ticker']).isNotEmpty
? extractTickerStr(fundMap?['ticker'] ?? json['ticker'])
: primaryTickerVal;
final companyNameVal = assetMap?['name']?.toString() ?? json['companyName']?.toString() ?? tickerVal;
final businessSummaryVal = assetMap?['description']?.toString() ?? json['businessSummary']?.toString();
final exchangeVal = extractExchangeStr(fundMap?['ticker']) ??
extractExchangeStr(assetMap?['primaryTicker']) ??
json['exchange']?.toString();
final rawTickers = assetMap?['availableTickers'] ?? json['availableTickers'];
List<TickerModel> availableTickersList = [];
if (rawTickers is List) {
availableTickersList = rawTickers
.whereType<Map<String, dynamic>>()
.map((t) => TickerModel.fromJson(t))
.toList();
}
final totalRev = parseNullableDouble(fundMap?['totalRevenue'] ?? json['totalRevenue']);
final grossProf = parseNullableDouble(fundMap?['grossProfit'] ?? json['grossProfit']);
double? grossMarginVal = parseNullableDouble(fundMap?['grossMargin'] ?? json['grossMargin']);
if (grossMarginVal == null && grossProf != null) {
if (grossProf <= 1.0 && grossProf >= 0.0) {
grossMarginVal = grossProf;
} else if (totalRev != null && totalRev > 0) {
grossMarginVal = grossProf / totalRev;
}
}
final evVal = parseNullableDouble(fundMap?['enterpriseValue'] ?? json['enterpriseValue']);
double? evToRevVal = parseNullableDouble(fundMap?['evToRevenue'] ?? fundMap?['enterpriseValueToRevenue'] ?? json['evToRevenue']);
if (evToRevVal == null && evVal != null && totalRev != null && totalRev > 0) {
evToRevVal = evVal / totalRev;
}
return FundamentalDataModel(
isin: isinVal,
primaryTicker: primaryTickerVal,
ticker: tickerVal,
companyName: companyNameVal,
exchange: exchangeVal,
tradingCurrency: fundMap?['currency']?.toString() ?? json['tradingCurrency']?.toString(),
businessSummary: businessSummaryVal,
sector: assetMap?['sector']?.toString() ?? json['sector']?.toString(),
industry: assetMap?['industry']?.toString() ?? json['industry']?.toString(),
country: assetMap?['country']?.toString() ?? json['country']?.toString(),
employees: (assetMap?['employees'] ?? json['employees']) is int
? (assetMap?['employees'] ?? json['employees']) as int
: int.tryParse((assetMap?['employees'] ?? json['employees'])?.toString() ?? ''),
currentPrice: parseNullableDouble(fundMap?['currentPrice'] ?? json['currentPrice']) ?? 0.0,
dayChangeAbsolute: parseNullableDouble(fundMap?['dayChangeAbsolute'] ?? json['dayChangeAbsolute']) ?? 0.0,
dayChangePercent: parseNullableDouble(fundMap?['dayChangePercent'] ?? json['dayChangePercent']) ?? 0.0,
fiftyTwoWeekHigh: parseNullableDouble(fundMap?['fiftyTwoWeekHigh'] ?? json['fiftyTwoWeekHigh']),
fiftyTwoWeekLow: parseNullableDouble(fundMap?['fiftyTwoWeekLow'] ?? json['fiftyTwoWeekLow']),
marketCapitalization: parseNullableDouble(fundMap?['marketCap'] ?? fundMap?['marketCapitalization'] ?? json['marketCapitalization']),
enterpriseValue: evVal,
peRatioTrailing: parseNullableDouble(fundMap?['trailingPE'] ?? fundMap?['peRatioTrailing'] ?? json['peRatioTrailing']),
peRatioForward: parseNullableDouble(fundMap?['forwardPE'] ?? fundMap?['peRatioForward'] ?? json['peRatioForward']),
pegRatio: parseNullableDouble(fundMap?['pegRatio'] ?? json['pegRatio']),
pbRatio: parseNullableDouble(fundMap?['priceToBook'] ?? fundMap?['pbRatio'] ?? json['pbRatio']),
psRatio: parseNullableDouble(fundMap?['priceToSalesTrailing12Months'] ?? fundMap?['psRatio'] ?? json['psRatio']),
evToEbitda: parseNullableDouble(fundMap?['enterpriseToEbitda'] ?? fundMap?['evToEbitda'] ?? json['evToEbitda']),
evToRevenue: evToRevVal,
totalRevenue: totalRev,
revenueGrowthYoY: parseNullableDouble(fundMap?['revenueGrowth'] ?? fundMap?['revenueGrowthYoY'] ?? json['revenueGrowthYoY']),
grossProfit: grossProf,
ebitda: parseNullableDouble(fundMap?['ebitda'] ?? json['ebitda']),
dilutedEps: parseNullableDouble(fundMap?['trailingEps'] ?? fundMap?['dilutedEps'] ?? json['dilutedEps']),
totalCash: parseNullableDouble(fundMap?['totalCash'] ?? json['totalCash']),
totalDebt: parseNullableDouble(fundMap?['totalDebt'] ?? json['totalDebt']),
operatingCashFlow: parseNullableDouble(fundMap?['operatingCashflow'] ?? fundMap?['operatingCashFlow'] ?? json['operatingCashFlow']),
freeCashFlow: parseNullableDouble(fundMap?['freeCashflow'] ?? fundMap?['freeCashFlow'] ?? json['freeCashFlow']),
grossMargin: grossMarginVal,
operatingMargin: parseNullableDouble(fundMap?['operatingMargins'] ?? fundMap?['operatingMargin'] ?? json['operatingMargin']),
netProfitMargin: parseNullableDouble(fundMap?['profitMargins'] ?? fundMap?['netProfitMargin'] ?? json['netProfitMargin']),
returnOnEquity: parseNullableDouble(fundMap?['returnOnEquity'] ?? json['returnOnEquity']),
returnOnAssets: parseNullableDouble(fundMap?['returnOnAssets'] ?? json['returnOnAssets']),
returnOnInvestedCapital: parseNullableDouble(fundMap?['returnOnInvestedCapital'] ?? json['returnOnInvestedCapital']),
debtToEquity: parseNullableDouble(fundMap?['debtToEquity'] ?? json['debtToEquity']),
currentRatio: parseNullableDouble(fundMap?['currentRatio'] ?? json['currentRatio']),
quickRatio: parseNullableDouble(fundMap?['quickRatio'] ?? json['quickRatio']),
interestCoverage: parseNullableDouble(fundMap?['interestCoverage'] ?? json['interestCoverage']),
dividendYield: parseNullableDouble(fundMap?['dividendYield'] ?? json['dividendYield']),
payoutRatio: parseNullableDouble(fundMap?['payoutRatio'] ?? json['payoutRatio']),
exDividendDate: fundMap?['exDividendDate']?.toString() ?? json['exDividendDate']?.toString(),
nextEarningsDate: fundMap?['nextEarningsDate']?.toString() ?? json['nextEarningsDate']?.toString(),
percentHeldByInstitutions: parseNullableDouble(fundMap?['percentHeldByInstitutions'] ?? json['percentHeldByInstitutions']),
percentHeldByInsiders: parseNullableDouble(fundMap?['percentHeldByInsiders'] ?? json['percentHeldByInsiders']),
shortRatio: parseNullableDouble(fundMap?['shortRatio'] ?? json['shortRatio']),
shortPercentOfFloat: parseNullableDouble(fundMap?['shortPercentOfFloat'] ?? json['shortPercentOfFloat']),
consensusRating: fundMap?['consensusRating']?.toString() ?? json['consensusRating']?.toString(),
priceTargetLow: parseNullableDouble(fundMap?['priceTargetLow'] ?? json['priceTargetLow']),
priceTargetHigh: parseNullableDouble(fundMap?['priceTargetHigh'] ?? json['priceTargetHigh']),
priceTargetMedian: parseNullableDouble(fundMap?['priceTargetMedian'] ?? json['priceTargetMedian']),
priceTargetMean: parseNullableDouble(fundMap?['priceTargetMean'] ?? json['priceTargetMean']),
executives: (json['executives'] as List?)
?.whereType<Map<String, dynamic>>()
.map((e) => CompanyExecutiveModel.fromJson(e))
.toList() ??
[],
financialStatements: (json['financialStatements'] as List?)
?.whereType<Map<String, dynamic>>()
.map((e) => FinancialStatementModel.fromJson(e))
.toList() ??
[],
estimates: (json['estimates'] as List?)
?.whereType<Map<String, dynamic>>()
.map((e) => ForwardEstimateModel.fromJson(e))
.toList() ??
[],
availableTickers: availableTickersList,
);
}
@override
List<Object?> get props => [
isin, primaryTicker, ticker, companyName, exchange, tradingCurrency,
businessSummary, sector, industry, country, employees, currentPrice,
dayChangeAbsolute, dayChangePercent, fiftyTwoWeekHigh, fiftyTwoWeekLow,
marketCapitalization, enterpriseValue, peRatioTrailing, peRatioForward,
pegRatio, pbRatio, psRatio, evToEbitda, evToRevenue, grossMargin,
operatingMargin, netProfitMargin, returnOnEquity, returnOnAssets,
returnOnInvestedCapital, debtToEquity, currentRatio, quickRatio,
dividendYield, payoutRatio, exDividendDate, nextEarningsDate,
percentHeldByInstitutions, percentHeldByInsiders, shortRatio,
shortPercentOfFloat, consensusRating, priceTargetLow, priceTargetHigh,
priceTargetMedian, priceTargetMean, executives, financialStatements,
estimates, availableTickers,
];
}