Files
StockHistory/StockHistory/Services/StockEquityServices.cs
2026-09-28 10:53:51 +02:00

233 lines
9.9 KiB
C#

using Microsoft.EntityFrameworkCore;
using StockHistory.Data;
using StockHistory.Models;
using System.Diagnostics;
namespace StockHistory.Services;
public class StockEquityServices : IStockEquityServices
{
private readonly AppDbContext _dbContext;
private readonly ITransactionNotesServices _notesServices;
public StockEquityServices(AppDbContext dbContext, ITransactionNotesServices notesServices)
{
_dbContext = dbContext;
_notesServices = notesServices;
}
public async Task<List<StockEquity>> GetAllAsync()
{
return await _dbContext.Stocks.ToListAsync();
}
public async Task<List<StockEquity>> GetAllAsync(DateTime equityDate)
{
return await _dbContext.Stocks
.Where(s => s.Bought <= equityDate && (s.Sold > equityDate || s.SoldQuant == 0))
.ToListAsync();
}
public async Task<List<StockEquity>> GetByCodeAsync(string stockCode)
{
var searchedNotes = await _notesServices.GetByStockCodeAsync(stockCode);
return await _dbContext.Stocks
.Where(s => s.StockCode == stockCode)
.OrderBy(s => s.Bought)
.ToListAsync();
}
public async Task<List<StockEquity>> GetLatestSoldInfoAsync()
{
var today = DateTime.Today;
var maxPerCode = _dbContext.Stocks
.Where(s => s.Sold < today)
.GroupBy(s => s.StockCode)
.Select(g => new { StockCode = g.Key, MaxSold = g.Max(x => x.Sold) });
var minBoughtPerCodeAndSold = _dbContext.Stocks
.Where(s => s.Sold < today)
.Join(maxPerCode,
s => new { s.StockCode, s.Sold },
m => new { m.StockCode, Sold = m.MaxSold },
(s, m) => new { s.StockCode, s.Sold, s.BoughtPrice })
.GroupBy(x => new { x.StockCode, x.Sold })
.Select(g => new { g.Key.StockCode, g.Key.Sold, MinBought = g.Min(x => (double)x.BoughtPrice) });
var result = from s in _dbContext.Stocks
where s.Sold < today
join mm in minBoughtPerCodeAndSold
on new { s.StockCode, s.Sold, BoughtPrice = (double)s.BoughtPrice }
equals new { mm.StockCode, Sold = mm.Sold, BoughtPrice = mm.MinBought }
select s;
return await result.ToListAsync();
//var query =
// from s in _dbContext.Stocks
// where s.Sold < today
// group s by s.StockCode into g
// let maxSold = g.Max(x => x.Sold)
// let minBought = g.Where(x => x.Sold == maxSold).Min(x => x.BoughtPrice)
// from row in g
// where row.Sold == maxSold && row.BoughtPrice == minBought
// select row;
//return await query.ToListAsync();
}
/// <summary>
/// Skapar en ny lista med aktieinnehav baserat på transaktionsnoteringar.
/// Den rensar först den befintliga listan och bygger sedan upp den igen genom att
/// utgående från alla befintliga notor skapa en lista med aktieinnehav.
/// </summary>
/// <returns></returns>
public async Task<List<StockEquity>> GenerateStockVision()
{
var oldStock = "OldStock";
var nyAktie = false;
List<StockEquity> equityWarningList = new List<StockEquity>();
await _dbContext.Stocks.ExecuteDeleteAsync();
await _dbContext.SaveChangesAsync();
var existingNotes = await _notesServices.GetAllAsync();
foreach (var note in existingNotes
.OrderBy(e => e.StockCode)
.ThenBy(e => e.TransactionDate)
//.OrderBy(e => e.TransactionType)
.ToList())
{
// Kontrollera om TransactionType är null och StockCode inte är null
// (om det är fallet, hoppa över denna iteration)
Debug.WriteLine(note.ToString());
nyAktie = false;
if (note.StockCode != null &&
note.StockCode != oldStock)
{
oldStock = note.StockCode;
nyAktie = true;
}
if (note.TransactionType == null && note.StockCode != null) { }
else
{
// Kontrollera om TransactionType är en köpnotering
// (ignorera null-värden)
if (note.TransactionType.ToLower() == "köp")
{
// Skapa en ny aktieinnehavspost baserat på köpnoteringen
var equity = new StockEquity
{
StockCode = note.StockCode,
StockISIN = note.StockISIN,
Bought = note.TransactionDate,
BoughtPrice = note.StockPrice,
Quantity = note.StockQuantity,
Sold = DateTime.MinValue,
SoldPrice = 0m,
SoldQuant = 0
};
_dbContext.Stocks.Add(equity);
await _dbContext.SaveChangesAsync();
// Debug.WriteLine($"Köpnotering: {equity.StockCode} | {equity.Bought} | {equity.BoughtPrice} | {equity.Quantity} | {equity.BoughtPrice * equity.Quantity}");
}
// Kontrollera om TransactionType är en säljnotering
else if (note.TransactionType.ToLower() == "sälj")
{
if (nyAktie)
{
Debug.WriteLine("<--" + note.ToString());
if (note.StockCode != null)
{
equityWarningList.Add(new StockEquity
{
//StockCode = note.StockCode,
//Bought = DateTime.MinValue,
//BoughtPrice = 0,
//Quantity = 0,
//Sold = note.TransactionDate,
//SoldPrice = note.StockPrice,
//SoldQuant = note.StockQuantity
StockCode = note.StockCode,
StockISIN = note.StockISIN,
Bought = note.TransactionDate,
BoughtPrice = note.StockPrice * -1,
Quantity = note.StockQuantity,
Sold = DateTime.MinValue,
SoldPrice = 0m,
SoldQuant = 0
});
}
;
}
else
{
var equityList = await _dbContext.Stocks
.Where(s => s.StockCode == note.StockCode && s.SoldQuant == 0)
.OrderBy(s => s.Quantity).ToListAsync();
if (equityList != null)
{
var soldQuant = Math.Abs(note.StockQuantity);
foreach (var eq in equityList.OrderBy(e => e.Quantity))
{
if (soldQuant == 0)
{
break;
}
else
{
if (eq.Quantity <= soldQuant)
{
eq.Sold = note.TransactionDate;
eq.SoldPrice = note.StockPrice;
eq.SoldQuant = eq.Quantity;
soldQuant -= eq.Quantity;
_dbContext.Stocks.Update(eq);
await _dbContext.SaveChangesAsync();
//Debug.WriteLine($"Säljnotering: {eq.StockCode} | {eq.Sold} | {eq.SoldPrice} | {eq.SoldQuant}");
}
else
{
var splitEquity = new StockEquity
{
StockCode = eq.StockCode,
StockISIN = eq.StockISIN,
Bought = eq.Bought,
BoughtPrice = eq.BoughtPrice,
Quantity = soldQuant,
Sold = note.TransactionDate,
SoldPrice = note.StockPrice,
SoldQuant = soldQuant
};
_dbContext.Stocks.Add(splitEquity);
await _dbContext.SaveChangesAsync();
//Debug.WriteLine($"Säljnotering (split): {splitEquity.StockCode} | {splitEquity.Bought} | {splitEquity.BoughtPrice} | {splitEquity.SoldQuant} | {splitEquity.Sold} | {splitEquity.SoldPrice} | {splitEquity.SoldQuant}");
eq.Quantity -= soldQuant;
_dbContext.Stocks.Update(eq);
await _dbContext.SaveChangesAsync();
//Debug.WriteLine($"Säljnotering (split): {eq.StockCode} | {eq.Bought} | {eq.BoughtPrice} | {eq.SoldQuant} | {eq.Sold} | {eq.SoldPrice} | {eq.SoldQuant}");
soldQuant = 0;
}
}
}
}
}
}
}
}
return equityWarningList;
}
}