Removed strongly typed inventory objects

Added EAV inventory types

Added EAV object handling philosophy

Added controllers

Added EF Core migration integration
This commit is contained in:
2026-05-02 19:20:34 -05:00
parent a76785e602
commit 75c381e645
44 changed files with 755 additions and 219 deletions
@@ -1,53 +0,0 @@
using WyvernInventory.Core.Interfaces.Repos;
using WyvernInventory.Core.Models;
namespace WyvernInventory.Infrastructure.Repos;
public class GenericInventoryItemRepo : IDbObjectRepo<GenericInventoryItem>
{
private List<GenericInventoryItem> _genericItemList = [];
public async Task<List<GenericInventoryItem>> GetAsync(Predicate<GenericInventoryItem>? filter = null)
{
List<GenericInventoryItem> result = [];
if (filter is null) return _genericItemList;
result.AddRange(_genericItemList.Where(item => filter(item)));
return result;
}
public async Task<(int created, int updated)> UpsertAsync(List<GenericInventoryItem> items)
{
int created = 0;
int updated = 0;
foreach (var item in items)
{
if (item.Id is not null && _genericItemList.Any(_ => _.Id == item.Id))
{
int index = _genericItemList.IndexOf(_genericItemList.Find(_ => _.Id == item.Id));
_genericItemList[index] = item;
updated++;
}
else
{
item.Id = _genericItemList.Count;
_genericItemList.Add(item);
created++;
}
}
return (created, updated);
}
public async Task DeleteAsync(List<GenericInventoryItem> items)
{
foreach (var item in items)
{
_genericItemList.Remove(_genericItemList.Find(_ => _.Id == item.Id));
}
}
}
@@ -0,0 +1,133 @@
using Microsoft.EntityFrameworkCore;
using WyvernInventory.Core.Interfaces.Repos;
using WyvernInventory.Core.Models;
using WyvernInventory.Infrastructure.Data;
namespace WyvernInventory.Infrastructure.Repos;
public class InventoryItemRepo(DBContext dbContext) : IInventoryItemRepo
{
private DBContext _dbContext = dbContext;
public async Task<List<InventoryItemDto>> GetAsync(List<InventoryItemRequest>? filterList = null)
{
return _dbContext.InventoryItems
.Include(_ => _.AttributeValues)
.Include(_ => _.Type)
.Select(_ => new InventoryItemDto
{
Id = (int)_.Id!,
Name = _.Name,
AttributeValues = _.AttributeValues.Select(x => new InventoryAttributeValueDto
{
Id = x.Id,
AttributeDefinitionId = (int)x.AttributeDefinitionId!,
AttributeDefinition = new InventoryAttributeDefinitionDto()
{
Id = x.AttributeDefinitionId,
Name = x.AttributeDefinition.Name,
DataType = x.AttributeDefinition.DataType
},
StringValue = x.StringValue,
IntValue = x.IntValue,
DecimalValue = x.DecimalValue,
BoolValue = x.BoolValue,
DateTimeValue = x.DateTimeValue
}).ToList(),
Type = new InventoryTypeDto()
{
Id = _.TypeId,
Name = _.Type.Name,
}
})
.ToList<InventoryItemDto>();
}
public async Task<(int created, int updated)> UpsertAsync(List<InventoryItemRequest> items)
{
var created = 0;
var updated = 0;
var itemsToCreate = items
.Where(_ => _.Id is null or 0)
.Select(_ => new InventoryItem
{
Name = _.Name,
AttributeValues = _.AttributeValues?.Select(x => new InventoryAttributeValue
{
Id = x.Id,
AttributeDefinitionId = x.AttributeDefinitionId,
BoolValue = x.BoolValue,
DateTimeValue = x.DateTimeValue,
DecimalValue = x.DecimalValue,
IntValue = x.IntValue,
StringValue = x.StringValue
}).ToList(),
TypeId = _.TypeId
})
.ToList();
var itemsToUpdate = items
.Where(_ => _.Id is not null and not 0)
.Select(_ => new InventoryItem
{
Id = _.Id,
Name = _.Name,
AttributeValues = _.AttributeValues?.Select(x => new InventoryAttributeValue
{
Id = x.Id,
AttributeDefinitionId = x.AttributeDefinitionId,
BoolValue = x.BoolValue,
DateTimeValue = x.DateTimeValue,
DecimalValue = x.DecimalValue,
IntValue = x.IntValue,
StringValue = x.StringValue
}).ToList(),
TypeId = _.TypeId
})
.ToList();
if (itemsToCreate.Count > 0)
{
_dbContext.InventoryItems.AddRange(itemsToCreate);
created = itemsToCreate.Count;
}
if (itemsToUpdate.Count > 0)
{
List<int> idList = itemsToUpdate.Select(_ =>
{
if (_.Id != null) return (int)_.Id;
throw new NullReferenceException();
}).ToList<int>();
var existingItems = _dbContext.InventoryItems.ToList()
.Where(_ => idList.Contains((int)_.Id!))
.ToDictionary(_ => (int)_.Id!);
foreach (var incoming in itemsToUpdate)
{
if (!existingItems.TryGetValue(incoming.Id!.Value, out var existing))
continue;
existing.Name = incoming.Name;
existing.AttributeValues = incoming.AttributeValues;
updated++;
}
}
await _dbContext.SaveChangesAsync();
return (created, updated);
}
public async Task<int> DeleteAsync(List<InventoryItemRequest> items)
{
var itemsToDelete = _dbContext.InventoryItems.Where(_ => items.Select(_ => _.Id).Contains(_.Id)).ToList();
_dbContext.InventoryItems.RemoveRange(itemsToDelete);
return await _dbContext.SaveChangesAsync();
}
}
@@ -0,0 +1,86 @@
using Microsoft.EntityFrameworkCore;
using WyvernInventory.Core.Interfaces.Repos;
using WyvernInventory.Core.Models;
using WyvernInventory.Infrastructure.Data;
namespace WyvernInventory.Infrastructure.Repos;
public class InventoryTypeRepo(DBContext dbContext) : IDbObjectRepo<InventoryType, InventoryTypeDto>
{
private readonly DBContext _dbContext = dbContext;
public async Task<List<InventoryTypeDto>> GetAsync(List<InventoryType>? filterList = null)
{
return _dbContext.InventoryTypes
.Include(_ => _.AttributeDefinitions)
.Select(_ => new InventoryTypeDto
{
Id = _.Id,
Name = _.Name,
AttributeDefinitions = _.AttributeDefinitions.Select(x => new InventoryAttributeDefinitionDto
{
Id = x.Id,
Name = x.Name,
DataType = x.DataType
}).ToList()
})
.ToList();
}
public async Task<(int created, int updated)> UpsertAsync(List<InventoryType> items)
{
var created = 0;
var updated = 0;
var itemsToCreate = items
.Where(_ => _.Id is null or 0)
.ToList();
var itemsToUpdate = items
.Where(_ => _.Id is not null and not 0)
.ToList();
if (itemsToCreate.Count > 0)
{
_dbContext.InventoryTypes.AddRange(itemsToCreate);
created = itemsToCreate.Count;
}
if (itemsToUpdate.Count > 0)
{
List<int> idList = itemsToUpdate.Select(_ =>
{
if (_.Id != null) return (int)_.Id;
throw new NullReferenceException();
}).ToList<int>();
var existingItems = _dbContext.InventoryTypes.ToList()
.Where(_ => idList.Contains((int)_.Id!))
.ToDictionary(_ => (int)_.Id!);
foreach (var incoming in itemsToUpdate)
{
if (!existingItems.TryGetValue(incoming.Id!.Value, out var existing))
continue;
existing.Name = incoming.Name;
existing.AttributeDefinitions = incoming.AttributeDefinitions;
updated++;
}
}
await _dbContext.SaveChangesAsync();
return (created, updated);
}
public async Task<int> DeleteAsync(List<InventoryType> items)
{
var itemsToDelete = _dbContext.InventoryTypes.Where(_ => items.Select(_ => _.Id).Contains(_.Id)).ToList();
_dbContext.InventoryTypes.RemoveRange(itemsToDelete);
return await _dbContext.SaveChangesAsync();
}
}