using System.Linq; using FastEndpoints; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Logging; using GB5Shared.DTO.Framework.Login; using GB5Shared.DTO.Framework.ResponseStandard; using GB5Shared.DTO.Report; using GB5Shared.FastEndPoint; using MMBLL.BOM; using static GB5Shared.GB5Constant.Constant; namespace MMSL.EndPoints.BOM { // Route matches the legacy GB4 BOM.svc/Tree endpoint exactly — MWEBSERVICE -1399999813 is // repointed at this route (see the MM migration script). Live query every call — no caching, // no materialized/cached tree — per the plan's explicit direction (structural BOM/master changes // must be immediately visible, and cache-invalidation-on-structural-change is itself risky). public class GetBOMTree : BaseEndpoint> { private readonly IBOMBLL _BOMBLL; public GetBOMTree(IBOMBLL IBOMBLL) { _BOMBLL = IBOMBLL; } public override void Configure() { Post("/BOM/Tree"); AllowAnonymous(); } public record GetBOMTreeParameters( [property: FromHeader] string Login, [property: FromBody] ReportCallingDTO ReportCallingDTO, [property: QueryParam] int FirstNumber, [property: QueryParam] int MaxResult ); protected override string? GetCacheKey(GetBOMTreeParameters req, LoginDTO login) => null; protected override async Task> ExecuteAsync(GetBOMTreeParameters req, LoginDTO LoginDTO, CancellationToken ct) { try { var (bomId, quantityForBom) = ParseCriteria(req.ReportCallingDTO.CriteriaDTO); var tree = await _BOMBLL.GetBOMTree(bomId, quantityForBom, LoginDTO!, ct); return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse(tree, CacheKeyLevel.NOT_REQUIRED, LoginDTO); } catch (Exception ex) { return await GB5Shared.ResponseStandard.Response .CreateExceptionError(ex, CacheKeyLevel.NOT_REQUIRED, LoginDTO, ex.Message, 500); } } private static (int BomId, decimal QuantityForBom) ParseCriteria(CriteriaDTO? criteriaDTO) { int bomId = -1; decimal quantityForBom = 1; if (criteriaDTO?.SectionCriteriaList == null) return (bomId, quantityForBom); foreach (var sec in criteriaDTO.SectionCriteriaList) { foreach (var attr in sec.AttributesCriteriaList ?? []) { if (attr.FieldValue is null) continue; switch (attr.FieldName?.ToLowerInvariant()) { case "bomid": if (int.TryParse(attr.FieldValue.ToString(), out var b)) bomId = b; break; case "quantityforbom": if (decimal.TryParse(attr.FieldValue.ToString(), out var q) && q > 0) quantityForBom = q; break; } } } return (bomId, quantityForBom); } } }