using GB5Shared.DTO.Framework.AutoNumber; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using GB5Shared.ResponseStandard; using GB5Shared.Validation; using MMDAL.CustomCode.ItemGroup; using MMDAL.DTO.ItemGroup; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MMBLL.ItemGroup { public class ItemGroupBLL : IItemGroupBLL { private readonly IItemGroupDAL _ItemGroupDAL; private readonly AutoNumber _AutoNumber; private readonly IValidation _Validation; public ItemGroupBLL(IItemGroupDAL IItemGroupDAL, AutoNumber AutoNumber, IValidation validation) { _ItemGroupDAL = IItemGroupDAL; _AutoNumber = AutoNumber; _Validation = validation; } public async Task GetItemGroup(int ItemGroupId, LoginDTO LoginDTO) { try { return await _ItemGroupDAL.GetItemGroup(ItemGroupId, LoginDTO); } catch (Exception) { throw; } } public async Task SaveItemGroup(ItemGroupDTO ItemGroupDTO, LoginDTO LoginDTO) { if (ItemGroupDTO == null) throw new ArgumentNullException(nameof(ItemGroupDTO)); AutoNumberDTO? autoNumberDTO = null; try { await _Validation.NotEmpty(ItemGroupDTO.ItemGroupName, nameof(ItemGroupDTO.ItemGroupName)); await _Validation.NotEmpty(ItemGroupDTO.ItemGroupCode, nameof(ItemGroupDTO.ItemGroupCode)); // Common fields ItemGroupDTO.ItemGroupModifiedById = LoginDTO.UserId; ItemGroupDTO.ItemGroupModifiedOn = DateTime.UtcNow; ItemGroupDTO.BranchTenantId = LoginDTO.ClientId; // <-- Set TenantId from Login int count = 1; if (ItemGroupDTO.ItemGroupId == 0) { autoNumberDTO = await _AutoNumber.GetNumberAsync(count, "ITEMGROUP", LoginDTO); ItemGroupDTO.ItemGroupId = autoNumberDTO.StartNumber; ItemGroupDTO.ItemGroupCreatedById = LoginDTO.UserId; ItemGroupDTO.ItemGroupCreatedOn = DateTime.UtcNow; await _ItemGroupDAL.SaveItemGroup(ItemGroupDTO, LoginDTO); return $"{SuccessResponse.SaveSuccessMessage} {ItemGroupDTO.ItemGroupId}"; } else { await _ItemGroupDAL.UpdateItemGroup(ItemGroupDTO, LoginDTO); return $"{SuccessResponse.UpdateSuccessMessage} {ItemGroupDTO.ItemGroupId}"; } } catch (ValidationException vex) { throw new Exception($"Validation Failed: {vex.Message}"); } catch (Exception ex) { if (autoNumberDTO != null && ItemGroupDTO.ItemGroupId > 0) { await _AutoNumber.RollbackAutoNumber("ITEMGROUP", ItemGroupDTO.ItemGroupId, LoginDTO); } throw new Exception($"An error occurred: {ex.Message}", ex); } } public async Task DeleteItemGroup(int ItemGroupId, LoginDTO LoginDTO) { try { var result = await _ItemGroupDAL.DeleteItemGroup(ItemGroupId, LoginDTO); if (result <= 0) return $"{ErrorResponse.DeleteNotFoundMessage}"; return $"{SuccessResponse.DeleteSuccessMessage}"; } catch (Exception ex) { throw new Exception($"Error deleting ItemGroup ID {ItemGroupId}", ex); } } public async Task GetSelectListItemGroup(CriteriaDTO criteriaDTO, LoginDTO loginDTO) { try { return await _ItemGroupDAL.GetSelectListItemGroup(criteriaDTO, loginDTO); } catch (Exception) { throw; } } public async Task GetItemGroupTree(LoginDTO LoginDTO, CriteriaDTO CriteriaDTO) { try { string flatListJson = await _ItemGroupDAL.GetItemGroupTree(LoginDTO, CriteriaDTO); var flatList = JsonConvert.DeserializeObject>(flatListJson) ?? new List(); var itemGroupTreeDTOs = new List(); foreach (var item in flatList) { var node = new ItemGroupTreeDTO { Id = item.Id, Code = item.Code, data = item.Name, attr = new ItemGroupTreeAttributeDTO { Id = item.Id, Code = item.Code } }; if (item.ParentId.HasValue) node.Parent = new ItemGroupTreeDTO { Id = item.ParentId.Value }; itemGroupTreeDTOs.Add(node); } var tree = BuildItemGroupTree(itemGroupTreeDTOs); return JsonConvert.SerializeObject(tree); } catch (Exception) { throw; } } private static List BuildItemGroupTree(List nodes) { var lookup = nodes.GroupBy(node => node.Id).ToDictionary(g => g.Key, g => g.First()); var roots = new List(); foreach (var node in nodes) { var parentId = node.Parent?.Id; node.Parent = null; // Legacy GB4 rows sometimes mark a root by self-referencing ParentId == Id instead of NULL. if (!parentId.HasValue || parentId.Value == node.Id || !lookup.TryGetValue(parentId.Value, out var parent)) { roots.Add(node); continue; } parent.children.Add(node); } return roots; } } }