first commit

This commit is contained in:
2025-02-26 23:42:19 +01:00
commit 777ea98be1
283 changed files with 88266 additions and 0 deletions
@@ -0,0 +1,20 @@
using OpenWarehouse.warehouse.api.Services;
namespace OpenWarehouse.warehouse.api.Common.ItemTagManager;
public interface IItemTagManager
{
public Task<bool> CreateTag(string name, Guid? parentId);
public Task<ItemCategoryTag?> GetTagByName(string name);
public Task<ItemCategoryTag?> GetTagById(Guid id);
public Task<ItemCategoryTag?> GetTagById(string id);
public Task<bool> DeleteTag(ItemCategoryTag tag);
public Task<bool> DeleteTag(Guid id);
public Task<int> DeleteTagsByNames(List<Model.Item.ItemCategoryTag> names);
public Task<bool> DeleteTag(String id);
public Task<int> CreateTagTree(List<Model.Item.ItemCategoryTag> itemCategoryTags);
public Task<bool> DeleteAllChild(Guid id);
public Task<bool> DeleteAllChild(String id);
public Task<ItemCategoryTag?> GetTagTree(string root);
public Task<List<ItemCategoryTag>> GetFullTagTree();
}
@@ -0,0 +1,339 @@
namespace OpenWarehouse.warehouse.api.Common.ItemTagManager;
public class ItemTagManager(ApplicationDbContext applicationDbContext, ILogger<ItemManager> logger) : IItemTagManager
{
public async Task<bool> CreateTag(string name, Guid? parentId)
{
logger.LogDebug("Attempting to create a new tag with name {TagName} and parent ID {ParentId}", name, parentId);
ItemCategoryTag? parent = null;
if (parentId != null)
{
parent = await applicationDbContext.ItemCategoryTags
.FirstOrDefaultAsync(q => q.Id == parentId);
if (parent == null)
{
logger.LogWarning("Parent tag with ID {ParentId} not found.", parentId);
return false;
}
}
var newTag = new ItemCategoryTag()
{
Name = name,
ParentTag = parent
};
applicationDbContext.ItemCategoryTags.Add(newTag);
bool isSaved = (await applicationDbContext.SaveChangesAsync()) > 0;
if (isSaved)
{
logger.LogInformation("Successfully created tag {Name} with ID {TagId}.", name, newTag.Id);
}
else
{
logger.LogError("Failed to save the new tag {Name}.", name);
}
return isSaved;
}
public async Task<ItemCategoryTag?> GetTagByName(string name)
{
logger.LogDebug("Fetching tags with name {TagName}.", name);
var tags = await applicationDbContext.ItemCategoryTags
.Where(tag => tag.Name != null && tag.Name.Equals(name)).FirstOrDefaultAsync();
if (tags == null)
{
logger.LogWarning("No tags found with name {Name}.", name);
}
return tags;
}
public async Task<ItemCategoryTag?> GetTagById(Guid id)
{
logger.LogDebug("Fetching tag with ID {TagId}.", id);
var tag = await applicationDbContext.ItemCategoryTags
.Where(tag => tag.Id == id).FirstOrDefaultAsync();
if (tag == null)
{
logger.LogWarning("No tag found with ID {Id}.", id);
}
return tag;
}
public async Task<ItemCategoryTag?> GetTagById(string id)
{
logger.LogDebug("Fetching tag with string ID {TagId}.", id);
return await GetTagById(Guid.Parse(id));
}
public async Task<bool> DeleteTag(ItemCategoryTag tag)
{
logger.LogDebug("Attempting to delete tag with object reference {Tag}.", tag);
return await DeleteTag(tag.Id);
}
public async Task<bool> DeleteTag(Guid id)
{
logger.LogDebug("Attempting to delete tag with ID {TagId}.", id);
bool isDeleted = await applicationDbContext.ItemCategoryTags.Where(q => q.Id == id)
.ExecuteDeleteAsync() > 0;
if (isDeleted)
{
logger.LogInformation("Successfully deleted tag with ID {TagId}.", id);
}
else
{
logger.LogError("Failed to delete tag with ID {TagId}.", id);
}
return isDeleted;
}
public async Task<int> DeleteTagsByNames(List<Model.Item.ItemCategoryTag> names)
{
logger.LogDebug("Attempting to delete tags by names.");
if (!names.Any())
{
logger.LogWarning("No tags provided for deletion.");
return 0;
}
try
{
var res = 0;
foreach (var tag in names)
{
logger.LogDebug("Deleting tag with name {TagName}.", tag.Name);
res += await applicationDbContext.ItemCategoryTags
.Where(q => q.Name == tag.Name)
.ExecuteDeleteAsync();
}
logger.LogInformation("{Count} tags were successfully deleted.", res);
return res;
}
catch (Exception ex)
{
logger.LogError(ex, "An error occurred while deleting tags.");
throw;
}
}
public async Task<bool> DeleteTag(string id)
{
logger.LogDebug("Attempting to delete tag with string ID {TagId}.", id);
return await DeleteTag(Guid.Parse(id));
}
public async Task<int> CreateTagTree(List<Model.Item.ItemCategoryTag> itemCategoryTags)
{
logger.LogDebug("Attempting to create a tag tree.");
var result = 0;
try
{
if (itemCategoryTags.All(q => q.ParentName != null))
{
logger.LogError("Tag tree must have at least one root node.");
throw new InvalidOperationException("Tag tree must have at least one root node.");
}
var tempParent = new List<ItemCategoryTag>();
while (itemCategoryTags.Count > 0)
{
var currentLevel = itemCategoryTags
.Where(q => q.ParentName == null || itemCategoryTags.All(qq => qq.Name != q.ParentName))
.ToList();
itemCategoryTags.RemoveAll(q => currentLevel.Contains(q));
foreach (var tag in currentLevel)
{
logger.LogDebug("Processing tag {TagName} with parent {ParentName}.", tag.Name, tag.ParentName);
var exists = await applicationDbContext.ItemCategoryTags
.AnyAsync(t => t.Name == tag.Name && t.ParentTag != null && (t.ParentTag.Name == tag.ParentName ||
(t.ParentTag == null && tag.ParentName == null)));
if (exists)
{
logger.LogInformation("Tag with name {TagName} already exists.", tag.Name);
continue;
}
ItemCategoryTag? parent = null;
if (tag.ParentName != null)
{
parent = await applicationDbContext.ItemCategoryTags
.Where(q => q.Name == tag.ParentName).FirstOrDefaultAsync();
if (parent == null)
{
if (tempParent.Any(q => q.Name == tag.ParentName))
{
parent = tempParent.FirstOrDefault(q => q.Name == tag.ParentName);
}
else
{
logger.LogWarning("Parent tag with name {ParentName} not found for child {Name}.",
tag.ParentName, tag.Name);
continue;
}
}
}
var tagNew = new ItemCategoryTag()
{
Name = tag.Name,
ParentTag = parent
};
applicationDbContext.ItemCategoryTags.Add(tagNew);
tempParent.Add(tagNew);
logger.LogDebug("Added new tag {TagName} with parent {ParentName}.", tagNew.Name,
parent?.Name);
}
result += await applicationDbContext.SaveChangesAsync();
}
logger.LogInformation("Successfully created tag tree with {Changes} changes.", result);
return result;
}
catch (Exception ex)
{
logger.LogError(ex, "An error occurred while creating the tag tree.");
throw;
}
}
public async Task<bool> DeleteAllChild(Guid id)
{
logger.LogDebug("Attempting to delete all children for tag ID {TagId}.", id);
var parentTag = await GetTagById(id);
if (parentTag == null)
{
logger.LogWarning("Parent tag with ID {Id} not found.", id);
return false;
}
var childTags = await applicationDbContext.ItemCategoryTags
.Where(q => q.ParentTagId == id).ToListAsync();
if (!childTags.Any())
{
logger.LogInformation("No child tags found for parent tag with ID {Id}.", id);
return true;
}
applicationDbContext.ItemCategoryTags.RemoveRange(childTags);
bool isDeleted = (await applicationDbContext.SaveChangesAsync()) > 0;
if (isDeleted)
{
logger.LogInformation("Successfully deleted all child tags for parent tag with ID {Id}.", id);
}
else
{
logger.LogError("Failed to delete child tags for parent tag with ID {Id}.", id);
}
return isDeleted;
}
public async Task<bool> DeleteAllChild(string id)
{
logger.LogDebug("Attempting to delete all children for tag string ID {TagId}.", id);
return await DeleteAllChild(Guid.Parse(id));
}
public async Task<ItemCategoryTag?> GetTagTree(string root)
{
logger.LogDebug("Fetching tag tree starting from root {RootName}.", root);
var rootElement = await applicationDbContext.ItemCategoryTags
.Where(q => q.Name != null && q.Name.Equals(root))
.AsNoTracking()
.FirstOrDefaultAsync();
if (rootElement == null)
{
logger.LogWarning("Root tag with name {RootName} not found.", root);
return null;
}
await LoadChildren(rootElement);
return rootElement;
}
public async Task<List<ItemCategoryTag>> GetFullTagTree()
{
logger.LogDebug("Fetching the full tag tree.");
var allTags = await applicationDbContext.ItemCategoryTags
.AsNoTracking()
.ToListAsync();
var tagDictionary = allTags.ToDictionary(tag => tag.Id);
var rootTags = new List<ItemCategoryTag>();
foreach (var tag in allTags)
{
if (tag.ParentTagId == null)
{
rootTags.Add(tag);
}
else if (tagDictionary.TryGetValue(tag.ParentTagId.Value, out var parentTag))
{
if (parentTag.ListOfChildrenTag == null)
{
parentTag.ListOfChildrenTag = new List<ItemCategoryTag>();
}
parentTag.ListOfChildrenTag.Add(tag);
}
}
logger.LogInformation("Successfully fetched the full tag tree with {Count} root nodes.", rootTags.Count);
return rootTags;
}
private async Task LoadChildren(ItemCategoryTag parentTag)
{
logger.LogDebug("Loading children for tag {TagName} with ID {TagId}.", parentTag.Name, parentTag.Id);
parentTag.ListOfChildrenTag = await applicationDbContext.ItemCategoryTags
.Where(child => child.ParentTagId == parentTag.Id)
.AsNoTracking()
.ToListAsync();
foreach (var child in parentTag.ListOfChildrenTag)
{
await LoadChildren(child);
}
}
}