feat(core): update DTOs, Trade Republic client, Yahoo scrapers, and dynamic settings
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
public class AssetDataEntity
|
||||
{
|
||||
|
||||
[Key] public string Isin { get; set; } = "";
|
||||
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
public ICollection<KeyExecutiveEntity> KeyExecutives { get; set; }
|
||||
|
||||
public ICollection<AssetEventEntity> AssetEvents { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
public class AssetEventEntity
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Main database table representing global company profile, ownership structure, analyst predictions, and corporate events.
|
||||
/// </summary>
|
||||
public class AssetFundamentalsEntity
|
||||
{
|
||||
[Key]
|
||||
[Required]
|
||||
public string Isin { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
public string PrimaryTicker { get; set; } = string.Empty;
|
||||
|
||||
// --- Static Company Profile Columns ---
|
||||
[Required]
|
||||
public string CompanyName { get; set; } = string.Empty;
|
||||
public string? BusinessSummary { get; set; }
|
||||
public string? Sector { get; set; }
|
||||
public string? Industry { get; set; }
|
||||
public string? Country { get; set; }
|
||||
public int? Employees { get; set; }
|
||||
|
||||
// --- Ownership & Sentiment Data (Company-wide) ---
|
||||
public decimal? PercentHeldByInstitutions { get; set; }
|
||||
public decimal? PercentHeldByInsiders { get; set; }
|
||||
public decimal? ShortRatio { get; set; }
|
||||
public decimal? ShortPercentOfFloat { get; set; }
|
||||
|
||||
// --- Analyst Forecasts & Targets ---
|
||||
public string? ConsensusRating { get; set; }
|
||||
public decimal? PriceTargetLow { get; set; }
|
||||
public decimal? PriceTargetHigh { get; set; }
|
||||
public decimal? PriceTargetMedian { get; set; }
|
||||
public decimal? PriceTargetMean { get; set; }
|
||||
|
||||
// --- Corporate Calendar / Catalysts ---
|
||||
public DateTime? ExDividendDate { get; set; }
|
||||
public DateTime? NextEarningsDate { get; set; }
|
||||
|
||||
// --- Cache Control Timestamps ---
|
||||
public DateTime LastUpdatedAt { get; set; } = DateTime.UtcNow;
|
||||
public DateTime LastStaticUpdatedAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
// --- Relational Collections ---
|
||||
public List<CompanyExecutiveEntity> Executives { get; set; } = [];
|
||||
public List<FinancialStatementEntity> FinancialStatements { get; set; } = [];
|
||||
public List<ForwardEstimateEntity> Estimates { get; set; } = [];
|
||||
public List<TickerFundamentalsEntity> TickerFundamentals { get; set; } = [];
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Relational executive board table linked to the main fundamentals entity by ISIN.
|
||||
/// </summary>
|
||||
public class CompanyExecutiveEntity
|
||||
{
|
||||
[Key]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
[Required]
|
||||
public string Isin { get; set; } = string.Empty;
|
||||
|
||||
[JsonIgnore]
|
||||
public AssetFundamentalsEntity? AssetFundamentals { get; set; }
|
||||
|
||||
[Required]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public int? Age { get; set; }
|
||||
public decimal? Compensation { get; set; }
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Relational statement table linking historical Income Statements, Balance Sheets, and Cash Flow metrics.
|
||||
/// </summary>
|
||||
public class FinancialStatementEntity
|
||||
{
|
||||
[Key]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
[Required]
|
||||
public string Isin { get; set; } = string.Empty;
|
||||
|
||||
[JsonIgnore]
|
||||
public AssetFundamentalsEntity? AssetFundamentals { get; set; }
|
||||
|
||||
[Required]
|
||||
public string PeriodType { get; set; } = string.Empty; // "Annual" or "Quarterly"
|
||||
|
||||
[Required]
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
// --- Income Statement Fields ---
|
||||
public decimal? TotalRevenue { get; set; }
|
||||
public decimal? CostOfRevenue { get; set; }
|
||||
public decimal? GrossProfit { get; set; }
|
||||
public decimal? OperatingExpenses { get; set; }
|
||||
public decimal? OperatingIncome { get; set; }
|
||||
public decimal? Ebitda { get; set; }
|
||||
public decimal? NetIncome { get; set; }
|
||||
public decimal? EpsBasic { get; set; }
|
||||
public decimal? EpsDiluted { get; set; }
|
||||
|
||||
// --- Balance Sheet Fields ---
|
||||
public decimal? CashAndCashEquivalents { get; set; }
|
||||
public decimal? AccountsReceivable { get; set; }
|
||||
public decimal? Inventory { get; set; }
|
||||
public decimal? TotalCurrentAssets { get; set; }
|
||||
public decimal? TotalNonCurrentAssets { get; set; }
|
||||
public decimal? CurrentLiabilities { get; set; }
|
||||
public decimal? LongTermDebt { get; set; }
|
||||
public decimal? TotalLiabilities { get; set; }
|
||||
public decimal? TotalStockholdersEquity { get; set; }
|
||||
|
||||
// --- Cash Flow Fields ---
|
||||
public decimal? OperatingCashFlow { get; set; }
|
||||
public decimal? InvestingCashFlow { get; set; }
|
||||
public decimal? CapitalExpenditures { get; set; }
|
||||
public decimal? FinancingCashFlow { get; set; }
|
||||
public decimal? FreeCashFlow { get; set; } // OperatingCashFlow - CapEx
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Relational table for analyst consensus revenue and EPS forecasts.
|
||||
/// </summary>
|
||||
public class ForwardEstimateEntity
|
||||
{
|
||||
[Key]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
[Required]
|
||||
public string Isin { get; set; } = string.Empty;
|
||||
|
||||
[JsonIgnore]
|
||||
public AssetFundamentalsEntity? AssetFundamentals { get; set; }
|
||||
|
||||
[Required]
|
||||
public string Period { get; set; } = string.Empty; // "CurrentQuarter", "NextQuarter", "CurrentYear", "NextYear"
|
||||
public decimal? ExpectedRevenue { get; set; }
|
||||
public decimal? ExpectedEps { get; set; }
|
||||
public decimal? ExpectedGrowthRate { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
public class FundamentalDataEntity
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
public class FundamentalsSettingsEntity
|
||||
{
|
||||
[Key]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public int CacheTtlHours { get; set; } = 24;
|
||||
public bool EnableYahooFallback { get; set; } = true;
|
||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
public class KeyExecutiveEntity
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
public class TickerEntity
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace FinlyticFundamentals.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Database table representing dynamic trading data, exchange-dependent valuation ratios, liquidity, and leverage stats for each traded ticker symbol.
|
||||
/// </summary>
|
||||
public class TickerFundamentalsEntity
|
||||
{
|
||||
[Key]
|
||||
[Required]
|
||||
public string Ticker { get; set; } = string.Empty; // Primary key, e.g., "POR.DE"
|
||||
|
||||
[Required]
|
||||
public string Isin { get; set; } = string.Empty;
|
||||
|
||||
[ForeignKey("Isin")]
|
||||
public AssetFundamentalsEntity? AssetFundamentals { get; set; }
|
||||
|
||||
public string? Exchange { get; set; }
|
||||
public string? TradingCurrency { get; set; }
|
||||
|
||||
// Real-time & Price Performance
|
||||
public decimal CurrentPrice { get; set; }
|
||||
public decimal DayChangeAbsolute { get; set; }
|
||||
public decimal DayChangePercent { get; set; }
|
||||
public decimal FiftyTwoWeekHigh { get; set; }
|
||||
public decimal FiftyTwoWeekLow { get; set; }
|
||||
|
||||
// Size & Enterprise Valuation
|
||||
public decimal MarketCapitalization { get; set; }
|
||||
public decimal EnterpriseValue { get; set; }
|
||||
|
||||
// Valuation Ratios
|
||||
public decimal? PeRatioTrailing { get; set; }
|
||||
public decimal? PeRatioForward { get; set; }
|
||||
public decimal? PegRatio { get; set; }
|
||||
public decimal? PbRatio { get; set; }
|
||||
public decimal? PsRatio { get; set; }
|
||||
public decimal? EvToEbitda { get; set; }
|
||||
public decimal? EvToRevenue { get; set; }
|
||||
|
||||
// Profitability & Return Ratios
|
||||
public decimal? GrossMargin { get; set; }
|
||||
public decimal? OperatingMargin { get; set; }
|
||||
public decimal? NetProfitMargin { get; set; }
|
||||
public decimal? ReturnOnEquity { get; set; }
|
||||
public decimal? ReturnOnAssets { get; set; }
|
||||
public decimal? ReturnOnInvestedCapital { get; set; }
|
||||
|
||||
// Financial Health, Solvency & Liquidity
|
||||
public decimal? DebtToEquity { get; set; }
|
||||
public decimal? CurrentRatio { get; set; }
|
||||
public decimal? QuickRatio { get; set; }
|
||||
public decimal? InterestCoverage { get; set; }
|
||||
|
||||
// Dividend Performance Metrics
|
||||
public decimal? DividendYield { get; set; }
|
||||
public decimal? PayoutRatio { get; set; }
|
||||
public DateTime? ExDividendDate { get; set; }
|
||||
|
||||
public DateTime LastUpdatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
@@ -1,446 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using FinlyticFundamentals.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FinlyticFundamentals.Migrations
|
||||
{
|
||||
[DbContext(typeof(FundamentalsDbContext))]
|
||||
[Migration("20260801073430_Init")]
|
||||
partial class Init
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.9")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.AssetFundamentalsEntity", b =>
|
||||
{
|
||||
b.Property<string>("Isin")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("BusinessSummary")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("CompanyName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ConsensusRating")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Country")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int?>("Employees")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime?>("ExDividendDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Industry")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("LastStaticUpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime>("LastUpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("NextEarningsDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<decimal?>("PercentHeldByInsiders")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PercentHeldByInstitutions")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PriceTargetHigh")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PriceTargetLow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PriceTargetMean")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PriceTargetMedian")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("PrimaryTicker")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Sector")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal?>("ShortPercentOfFloat")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ShortRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.HasKey("Isin");
|
||||
|
||||
b.HasIndex("PrimaryTicker")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AssetFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.CompanyExecutiveEntity", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int?>("Age")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<decimal?>("Compensation")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Isin")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Isin");
|
||||
|
||||
b.ToTable("CompanyExecutives");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.FinancialStatementEntity", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal?>("AccountsReceivable")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("CapitalExpenditures")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("CashAndCashEquivalents")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("CostOfRevenue")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("CurrentLiabilities")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("Ebitda")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<DateTime>("EndDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<decimal?>("EpsBasic")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("EpsDiluted")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("FinancingCashFlow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("FreeCashFlow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("GrossProfit")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("Inventory")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("InvestingCashFlow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Isin")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal?>("LongTermDebt")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("NetIncome")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("OperatingCashFlow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("OperatingExpenses")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("OperatingIncome")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("PeriodType")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal?>("TotalCurrentAssets")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("TotalLiabilities")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("TotalNonCurrentAssets")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("TotalRevenue")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("TotalStockholdersEquity")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Isin");
|
||||
|
||||
b.HasIndex("Isin", "PeriodType", "EndDate")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("FinancialStatements");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.ForwardEstimateEntity", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal?>("ExpectedEps")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ExpectedGrowthRate")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ExpectedRevenue")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Isin")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Period")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Isin");
|
||||
|
||||
b.HasIndex("Isin", "Period")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ForwardEstimates");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.FundamentalsSettingsEntity", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("CacheTtlHours")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("EnableYahooFallback")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.TickerFundamentalsEntity", b =>
|
||||
{
|
||||
b.Property<string>("Ticker")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal>("CurrentPrice")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("CurrentRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal>("DayChangeAbsolute")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal>("DayChangePercent")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("DebtToEquity")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("DividendYield")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal>("EnterpriseValue")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("EvToEbitda")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("EvToRevenue")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<DateTime?>("ExDividendDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Exchange")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal>("FiftyTwoWeekHigh")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal>("FiftyTwoWeekLow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("GrossMargin")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("InterestCoverage")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Isin")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("LastUpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<decimal>("MarketCapitalization")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("NetProfitMargin")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("OperatingMargin")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PayoutRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PbRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PeRatioForward")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PeRatioTrailing")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PegRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PsRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("QuickRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ReturnOnAssets")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ReturnOnEquity")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ReturnOnInvestedCapital")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("TradingCurrency")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Ticker");
|
||||
|
||||
b.HasIndex("Isin");
|
||||
|
||||
b.ToTable("TickerFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.CompanyExecutiveEntity", b =>
|
||||
{
|
||||
b.HasOne("FinlyticFundamentals.Entities.AssetFundamentalsEntity", "AssetFundamentals")
|
||||
.WithMany("Executives")
|
||||
.HasForeignKey("Isin")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AssetFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.FinancialStatementEntity", b =>
|
||||
{
|
||||
b.HasOne("FinlyticFundamentals.Entities.AssetFundamentalsEntity", "AssetFundamentals")
|
||||
.WithMany("FinancialStatements")
|
||||
.HasForeignKey("Isin")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AssetFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.ForwardEstimateEntity", b =>
|
||||
{
|
||||
b.HasOne("FinlyticFundamentals.Entities.AssetFundamentalsEntity", "AssetFundamentals")
|
||||
.WithMany("Estimates")
|
||||
.HasForeignKey("Isin")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AssetFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.TickerFundamentalsEntity", b =>
|
||||
{
|
||||
b.HasOne("FinlyticFundamentals.Entities.AssetFundamentalsEntity", "AssetFundamentals")
|
||||
.WithMany("TickerFundamentals")
|
||||
.HasForeignKey("Isin")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AssetFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.AssetFundamentalsEntity", b =>
|
||||
{
|
||||
b.Navigation("Estimates");
|
||||
|
||||
b.Navigation("Executives");
|
||||
|
||||
b.Navigation("FinancialStatements");
|
||||
|
||||
b.Navigation("TickerFundamentals");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,255 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FinlyticFundamentals.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Init : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AssetFundamentals",
|
||||
columns: table => new
|
||||
{
|
||||
Isin = table.Column<string>(type: "text", nullable: false),
|
||||
PrimaryTicker = table.Column<string>(type: "text", nullable: false),
|
||||
CompanyName = table.Column<string>(type: "text", nullable: false),
|
||||
BusinessSummary = table.Column<string>(type: "text", nullable: true),
|
||||
Sector = table.Column<string>(type: "text", nullable: true),
|
||||
Industry = table.Column<string>(type: "text", nullable: true),
|
||||
Country = table.Column<string>(type: "text", nullable: true),
|
||||
Employees = table.Column<int>(type: "integer", nullable: true),
|
||||
PercentHeldByInstitutions = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
PercentHeldByInsiders = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ShortRatio = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ShortPercentOfFloat = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ConsensusRating = table.Column<string>(type: "text", nullable: true),
|
||||
PriceTargetLow = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
PriceTargetHigh = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
PriceTargetMedian = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
PriceTargetMean = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ExDividendDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
NextEarningsDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
LastUpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
LastStaticUpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AssetFundamentals", x => x.Isin);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Settings",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
CacheTtlHours = table.Column<int>(type: "integer", nullable: false),
|
||||
EnableYahooFallback = table.Column<bool>(type: "boolean", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Settings", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "CompanyExecutives",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Isin = table.Column<string>(type: "text", nullable: false),
|
||||
Name = table.Column<string>(type: "text", nullable: false),
|
||||
Title = table.Column<string>(type: "text", nullable: false),
|
||||
Age = table.Column<int>(type: "integer", nullable: true),
|
||||
Compensation = table.Column<decimal>(type: "numeric", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_CompanyExecutives", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_CompanyExecutives_AssetFundamentals_Isin",
|
||||
column: x => x.Isin,
|
||||
principalTable: "AssetFundamentals",
|
||||
principalColumn: "Isin",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "FinancialStatements",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Isin = table.Column<string>(type: "text", nullable: false),
|
||||
PeriodType = table.Column<string>(type: "text", nullable: false),
|
||||
EndDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
TotalRevenue = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
CostOfRevenue = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
GrossProfit = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
OperatingExpenses = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
OperatingIncome = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
Ebitda = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
NetIncome = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
EpsBasic = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
EpsDiluted = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
CashAndCashEquivalents = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
AccountsReceivable = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
Inventory = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
TotalCurrentAssets = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
TotalNonCurrentAssets = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
CurrentLiabilities = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
LongTermDebt = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
TotalLiabilities = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
TotalStockholdersEquity = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
OperatingCashFlow = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
InvestingCashFlow = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
CapitalExpenditures = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
FinancingCashFlow = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
FreeCashFlow = table.Column<decimal>(type: "numeric", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_FinancialStatements", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_FinancialStatements_AssetFundamentals_Isin",
|
||||
column: x => x.Isin,
|
||||
principalTable: "AssetFundamentals",
|
||||
principalColumn: "Isin",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ForwardEstimates",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Isin = table.Column<string>(type: "text", nullable: false),
|
||||
Period = table.Column<string>(type: "text", nullable: false),
|
||||
ExpectedRevenue = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ExpectedEps = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ExpectedGrowthRate = table.Column<decimal>(type: "numeric", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ForwardEstimates", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ForwardEstimates_AssetFundamentals_Isin",
|
||||
column: x => x.Isin,
|
||||
principalTable: "AssetFundamentals",
|
||||
principalColumn: "Isin",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "TickerFundamentals",
|
||||
columns: table => new
|
||||
{
|
||||
Ticker = table.Column<string>(type: "text", nullable: false),
|
||||
Isin = table.Column<string>(type: "text", nullable: false),
|
||||
Exchange = table.Column<string>(type: "text", nullable: true),
|
||||
TradingCurrency = table.Column<string>(type: "text", nullable: true),
|
||||
CurrentPrice = table.Column<decimal>(type: "numeric", nullable: false),
|
||||
DayChangeAbsolute = table.Column<decimal>(type: "numeric", nullable: false),
|
||||
DayChangePercent = table.Column<decimal>(type: "numeric", nullable: false),
|
||||
FiftyTwoWeekHigh = table.Column<decimal>(type: "numeric", nullable: false),
|
||||
FiftyTwoWeekLow = table.Column<decimal>(type: "numeric", nullable: false),
|
||||
MarketCapitalization = table.Column<decimal>(type: "numeric", nullable: false),
|
||||
EnterpriseValue = table.Column<decimal>(type: "numeric", nullable: false),
|
||||
PeRatioTrailing = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
PeRatioForward = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
PegRatio = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
PbRatio = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
PsRatio = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
EvToEbitda = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
EvToRevenue = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
GrossMargin = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
OperatingMargin = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
NetProfitMargin = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ReturnOnEquity = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ReturnOnAssets = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ReturnOnInvestedCapital = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
DebtToEquity = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
CurrentRatio = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
QuickRatio = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
InterestCoverage = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
DividendYield = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
PayoutRatio = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ExDividendDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
LastUpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_TickerFundamentals", x => x.Ticker);
|
||||
table.ForeignKey(
|
||||
name: "FK_TickerFundamentals_AssetFundamentals_Isin",
|
||||
column: x => x.Isin,
|
||||
principalTable: "AssetFundamentals",
|
||||
principalColumn: "Isin",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AssetFundamentals_PrimaryTicker",
|
||||
table: "AssetFundamentals",
|
||||
column: "PrimaryTicker",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_CompanyExecutives_Isin",
|
||||
table: "CompanyExecutives",
|
||||
column: "Isin");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_FinancialStatements_Isin",
|
||||
table: "FinancialStatements",
|
||||
column: "Isin");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_FinancialStatements_Isin_PeriodType_EndDate",
|
||||
table: "FinancialStatements",
|
||||
columns: new[] { "Isin", "PeriodType", "EndDate" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ForwardEstimates_Isin",
|
||||
table: "ForwardEstimates",
|
||||
column: "Isin");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ForwardEstimates_Isin_Period",
|
||||
table: "ForwardEstimates",
|
||||
columns: new[] { "Isin", "Period" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TickerFundamentals_Isin",
|
||||
table: "TickerFundamentals",
|
||||
column: "Isin");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "CompanyExecutives");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "FinancialStatements");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ForwardEstimates");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Settings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "TickerFundamentals");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AssetFundamentals");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,443 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using FinlyticFundamentals.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FinlyticFundamentals.Migrations
|
||||
{
|
||||
[DbContext(typeof(FundamentalsDbContext))]
|
||||
partial class FundamentalsDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.9")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.AssetFundamentalsEntity", b =>
|
||||
{
|
||||
b.Property<string>("Isin")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("BusinessSummary")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("CompanyName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ConsensusRating")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Country")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int?>("Employees")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime?>("ExDividendDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Industry")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("LastStaticUpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime>("LastUpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("NextEarningsDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<decimal?>("PercentHeldByInsiders")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PercentHeldByInstitutions")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PriceTargetHigh")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PriceTargetLow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PriceTargetMean")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PriceTargetMedian")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("PrimaryTicker")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Sector")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal?>("ShortPercentOfFloat")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ShortRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.HasKey("Isin");
|
||||
|
||||
b.HasIndex("PrimaryTicker")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AssetFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.CompanyExecutiveEntity", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int?>("Age")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<decimal?>("Compensation")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Isin")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Isin");
|
||||
|
||||
b.ToTable("CompanyExecutives");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.FinancialStatementEntity", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal?>("AccountsReceivable")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("CapitalExpenditures")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("CashAndCashEquivalents")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("CostOfRevenue")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("CurrentLiabilities")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("Ebitda")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<DateTime>("EndDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<decimal?>("EpsBasic")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("EpsDiluted")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("FinancingCashFlow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("FreeCashFlow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("GrossProfit")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("Inventory")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("InvestingCashFlow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Isin")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal?>("LongTermDebt")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("NetIncome")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("OperatingCashFlow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("OperatingExpenses")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("OperatingIncome")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("PeriodType")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal?>("TotalCurrentAssets")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("TotalLiabilities")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("TotalNonCurrentAssets")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("TotalRevenue")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("TotalStockholdersEquity")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Isin");
|
||||
|
||||
b.HasIndex("Isin", "PeriodType", "EndDate")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("FinancialStatements");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.ForwardEstimateEntity", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal?>("ExpectedEps")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ExpectedGrowthRate")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ExpectedRevenue")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Isin")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Period")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Isin");
|
||||
|
||||
b.HasIndex("Isin", "Period")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ForwardEstimates");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.FundamentalsSettingsEntity", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("CacheTtlHours")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("EnableYahooFallback")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.TickerFundamentalsEntity", b =>
|
||||
{
|
||||
b.Property<string>("Ticker")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal>("CurrentPrice")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("CurrentRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal>("DayChangeAbsolute")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal>("DayChangePercent")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("DebtToEquity")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("DividendYield")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal>("EnterpriseValue")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("EvToEbitda")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("EvToRevenue")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<DateTime?>("ExDividendDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Exchange")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal>("FiftyTwoWeekHigh")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal>("FiftyTwoWeekLow")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("GrossMargin")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("InterestCoverage")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Isin")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("LastUpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<decimal>("MarketCapitalization")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("NetProfitMargin")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("OperatingMargin")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PayoutRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PbRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PeRatioForward")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PeRatioTrailing")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PegRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("PsRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("QuickRatio")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ReturnOnAssets")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ReturnOnEquity")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<decimal?>("ReturnOnInvestedCapital")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("TradingCurrency")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Ticker");
|
||||
|
||||
b.HasIndex("Isin");
|
||||
|
||||
b.ToTable("TickerFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.CompanyExecutiveEntity", b =>
|
||||
{
|
||||
b.HasOne("FinlyticFundamentals.Entities.AssetFundamentalsEntity", "AssetFundamentals")
|
||||
.WithMany("Executives")
|
||||
.HasForeignKey("Isin")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AssetFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.FinancialStatementEntity", b =>
|
||||
{
|
||||
b.HasOne("FinlyticFundamentals.Entities.AssetFundamentalsEntity", "AssetFundamentals")
|
||||
.WithMany("FinancialStatements")
|
||||
.HasForeignKey("Isin")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AssetFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.ForwardEstimateEntity", b =>
|
||||
{
|
||||
b.HasOne("FinlyticFundamentals.Entities.AssetFundamentalsEntity", "AssetFundamentals")
|
||||
.WithMany("Estimates")
|
||||
.HasForeignKey("Isin")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AssetFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.TickerFundamentalsEntity", b =>
|
||||
{
|
||||
b.HasOne("FinlyticFundamentals.Entities.AssetFundamentalsEntity", "AssetFundamentals")
|
||||
.WithMany("TickerFundamentals")
|
||||
.HasForeignKey("Isin")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AssetFundamentals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinlyticFundamentals.Entities.AssetFundamentalsEntity", b =>
|
||||
{
|
||||
b.Navigation("Estimates");
|
||||
|
||||
b.Navigation("Executives");
|
||||
|
||||
b.Navigation("FinancialStatements");
|
||||
|
||||
b.Navigation("TickerFundamentals");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
using FinlyticFundamentals.Database;
|
||||
using FinlyticFundamentals.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace FinlyticFundamentals.Services;
|
||||
|
||||
public interface ISettingsDbService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the settings.
|
||||
/// </summary>
|
||||
Task<FundamentalsSettingsEntity> GetSettingsAsync();
|
||||
/// <summary>
|
||||
/// Saves the settings.
|
||||
/// </summary>
|
||||
Task<FundamentalsSettingsEntity> SaveSettingsAsync(FundamentalsSettingsEntity settings);
|
||||
/// <summary>
|
||||
/// Updates the settings from a dictionary.
|
||||
/// </summary>
|
||||
Task UpdateSettingsFromDictionaryAsync(Dictionary<string, string> dictionary);
|
||||
}
|
||||
|
||||
public class SettingsDbService : ISettingsDbService
|
||||
{
|
||||
private readonly FundamentalsDbContext _context;
|
||||
|
||||
public SettingsDbService(FundamentalsDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the settings asynchronously.
|
||||
/// </summary>
|
||||
public async Task<FundamentalsSettingsEntity> GetSettingsAsync()
|
||||
{
|
||||
var settings = await _context.Settings.AsNoTracking().FirstOrDefaultAsync();
|
||||
if (settings == null)
|
||||
{
|
||||
settings = new FundamentalsSettingsEntity { Id = Guid.NewGuid() };
|
||||
_context.Settings.Add(settings);
|
||||
await _context.SaveChangesAsync();
|
||||
_context.ChangeTracker.Clear();
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the settings asynchronously.
|
||||
/// </summary>
|
||||
public async Task<FundamentalsSettingsEntity> SaveSettingsAsync(FundamentalsSettingsEntity settings)
|
||||
{
|
||||
var existing = await _context.Settings.FirstOrDefaultAsync();
|
||||
if (existing == null)
|
||||
{
|
||||
if (settings.Id == Guid.Empty) settings.Id = Guid.NewGuid();
|
||||
_context.Settings.Add(settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
existing.CacheTtlHours = settings.CacheTtlHours;
|
||||
existing.EnableYahooFallback = settings.EnableYahooFallback;
|
||||
existing.UpdatedAt = settings.UpdatedAt;
|
||||
_context.Settings.Update(existing);
|
||||
}
|
||||
await _context.SaveChangesAsync();
|
||||
return settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the settings from a dictionary asynchronously.
|
||||
/// </summary>
|
||||
public async Task UpdateSettingsFromDictionaryAsync(Dictionary<string, string> dictionary)
|
||||
{
|
||||
var settings = await GetSettingsAsync();
|
||||
|
||||
foreach (var (key, value) in dictionary)
|
||||
{
|
||||
if (string.Equals(key, "CacheTtlHours", StringComparison.OrdinalIgnoreCase) && int.TryParse(value, out var ttl))
|
||||
settings.CacheTtlHours = ttl;
|
||||
else if (string.Equals(key, "EnableYahooFallback", StringComparison.OrdinalIgnoreCase) && bool.TryParse(value, out var fallback))
|
||||
settings.EnableYahooFallback = fallback;
|
||||
}
|
||||
|
||||
settings.UpdatedAt = DateTime.UtcNow;
|
||||
await SaveSettingsAsync(settings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace FinlyticFundamentals.Util;
|
||||
|
||||
public class SettingKeys
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
$files = Get-ChildItem -Path "e:\Projects\Finlytic\FinlyticFundamentals" -Recurse -Include *.cs -Exclude "Migrations\*"
|
||||
|
||||
foreach ($file in $files) {
|
||||
$content = Get-Content $file.FullName -Raw
|
||||
|
||||
# regex for logger
|
||||
# match _logger.LogX("message", args)
|
||||
# The tricky part is we need to match the message string correctly.
|
||||
# $content = [regex]::Replace($content, '(_?logger\.Log(?:Information|Warning|Error))\(\s*(ex\s*,\s*)?("[^"]*")\s*(.*?)\)', {
|
||||
# param($match)
|
||||
# ...
|
||||
# })
|
||||
|
||||
# Actually, a simpler way is using a Python script via downloaded Python or just do it in powershell carefully.
|
||||
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
def process_file(filepath):
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# 1. Update logger statements
|
||||
# We want to match: _logger.LogInformation("something", args) or _logger.LogError(ex, "something", args)
|
||||
# This regex is a bit tricky, let's use a simpler approach or careful regex.
|
||||
# Pattern to match logger.Log...( optionally (ex, ) then string then args )
|
||||
|
||||
# Let's match: (logger\.Log[A-Za-z]+)\((.*?)"(.*?)"(.*?)\)
|
||||
# Wait, multi-line strings or strings with escaped quotes might break it.
|
||||
# The regex approach:
|
||||
# Match: (logger\.Log(?:Information|Warning|Error))\(([^"]*)"([^"]*)"(.*)\)
|
||||
# If the string already starts with "[{Channel}] ", skip it.
|
||||
|
||||
def replacer(m):
|
||||
func_part = m.group(1) # e.g. _logger.LogInformation
|
||||
pre_str = m.group(2) # e.g. (ex, or empty if it's the first arg)
|
||||
msg_str = m.group(3)
|
||||
post_str = m.group(4)
|
||||
|
||||
if "[{Channel}]" in msg_str:
|
||||
return m.group(0)
|
||||
|
||||
new_msg = f"[{{Channel}}] {msg_str}"
|
||||
# append "FundamentalsChannel" as the first argument after the string, or right after if there are no args
|
||||
if post_str.strip().startswith(','):
|
||||
# args exist, we need to insert our channel arg before the existing ones, but wait, the channel arg corresponds to {Channel} which is FIRST in the string, so we must pass "FundamentalsChannel" as the FIRST format argument.
|
||||
new_post = f', "FundamentalsChannel"{post_str}'
|
||||
elif post_str.strip() == '':
|
||||
# no extra args, just the closing paren
|
||||
new_post = f', "FundamentalsChannel")'
|
||||
# Note: m.group(4) didn't include the closing paren if we don't match it. Let's adjust the regex to match up to closing paren.
|
||||
else:
|
||||
new_post = f', "FundamentalsChannel"{post_str}'
|
||||
|
||||
return f'{func_part}({pre_str}"{new_msg}"{new_post}'
|
||||
|
||||
# Regex to capture the parts.
|
||||
# group 1: logger.Log...
|
||||
# group 2: anything before the first quote (like exception)
|
||||
# group 3: the string itself
|
||||
# group 4: the rest of the arguments up to the closing parenthesis
|
||||
# We need to find all instances. Let's do a line-by-line or simple regex.
|
||||
|
||||
lines = content.split('\n')
|
||||
new_lines = []
|
||||
|
||||
# 2. Add /// <summary> to public methods
|
||||
# Method pattern: public (async )?(Task|void|[A-Za-z0-9_<>]+) [A-Za-z0-9_]+\(.*\)
|
||||
method_pattern = re.compile(r'^\s*public\s+(?:async\s+)?[A-Za-z0-9_<>\[\]]+\s+[A-Za-z0-9_]+\(.*')
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
# Apply logger transformation
|
||||
# We look for _logger.LogInformation, _logger.LogWarning, _logger.LogError, logger.LogError etc.
|
||||
if '.LogInformation(' in line or '.LogWarning(' in line or '.LogError(' in line:
|
||||
# simple replacement logic
|
||||
match = re.search(r'([_a-zA-Z0-9]+\.Log(?:Information|Warning|Error))\(([^"]*)"(.*?)"(.*)\)', line)
|
||||
if match:
|
||||
func_part = match.group(1)
|
||||
pre_str = match.group(2)
|
||||
msg_str = match.group(3)
|
||||
post_str = match.group(4)
|
||||
|
||||
if "[{Channel}]" not in msg_str:
|
||||
new_msg = f"[{{Channel}}] {msg_str}"
|
||||
if post_str.strip() == ')':
|
||||
new_post = ', "FundamentalsChannel")'
|
||||
elif post_str.endswith(');'):
|
||||
new_post = ', "FundamentalsChannel");'
|
||||
# strip the ); from post_str for clean insertion
|
||||
post_str = post_str[:-2]
|
||||
new_post = f', "FundamentalsChannel"{post_str});'
|
||||
else:
|
||||
new_post = f', "FundamentalsChannel"{post_str}'
|
||||
|
||||
line = f'{line[:match.start()]}{func_part}({pre_str}"{new_msg}"{new_post}{line[match.end():]}'
|
||||
|
||||
# Check for public method to add /// <summary>
|
||||
# We need to make sure we don't add it if it already has one.
|
||||
# Also interface methods: Task<string> Something();
|
||||
if method_pattern.match(line):
|
||||
# Check previous line
|
||||
if i > 0 and '///' not in lines[i-1] and '[' not in lines[i-1]:
|
||||
indent = len(line) - len(line.lstrip())
|
||||
summary = ' ' * indent + '/// <summary>\n' + ' ' * indent + '/// \n' + ' ' * indent + '/// </summary>'
|
||||
new_lines.append(summary)
|
||||
|
||||
# Interface methods inside public interface
|
||||
if re.match(r'^\s*(?:Task|void|[A-Za-z0-9_<>\[\]]+)\s+[A-Za-z0-9_]+\(.*', line):
|
||||
if i > 0 and '///' not in lines[i-1] and '[' not in lines[i-1]:
|
||||
# check if we are in an interface
|
||||
# kinda hard with just line by line, but let's try.
|
||||
pass
|
||||
|
||||
new_lines.append(line)
|
||||
|
||||
with open(filepath, 'w', encoding='utf-8') as f:
|
||||
f.write('\n'.join(new_lines))
|
||||
|
||||
def main():
|
||||
dirs = ['Services', 'Util', '.']
|
||||
base = r'e:\Projects\Finlytic\FinlyticFundamentals'
|
||||
|
||||
for d in dirs:
|
||||
p = os.path.join(base, d)
|
||||
if os.path.isdir(p):
|
||||
for file in os.listdir(p):
|
||||
if file.endswith('.cs'):
|
||||
filepath = os.path.join(p, file)
|
||||
process_file(filepath)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user