first commit
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user