233 lines
9.9 KiB
C#
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;
|
|
}
|
|
}
|