using GB5Shared.DTO.Framework.Login; using GB5Shared.QueryExecutor; using MMDAL.DTO.Scheduling; using MMDAL.Query.Scheduling; namespace MMDAL.CustomCode.Scheduling { public class SchedulingDemandDAL : ISchedulingDemandDAL { private readonly IQueryExecutor _QueryExecutor; public SchedulingDemandDAL(IQueryExecutor queryExecutor) { _QueryExecutor = queryExecutor; } public async IAsyncEnumerable StreamOpenIndentsAsync( SchedulingRunTriggerDTO trigger, LoginDTO loginDTO, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken ct) { var param = new { TenantId = trigger.TenantId, WorkOUId = trigger.WorkOUId, HorizonFrom = trigger.HorizonFrom.Date, HorizonTo = trigger.HorizonTo.Date }; int euId = 1; await foreach (var raw in _QueryExecutor.StreamAsync( loginDTO, SchedulingDemandQB.STREAM_OPEN_INDENTS, param).ConfigureAwait(false)) { yield return MapToExecutionUnit(raw, DemandType.ProductionIndent, euId++); } } public async IAsyncEnumerable StreamOpenNestingPlansAsync( SchedulingRunTriggerDTO trigger, LoginDTO loginDTO, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken ct) { var param = new { TenantId = trigger.TenantId }; await foreach (var row in _QueryExecutor.StreamAsync( loginDTO, SchedulingDemandQB.STREAM_OPEN_NESTING_PLANS, param).ConfigureAwait(false)) { yield return row; } } private static ExecutionUnit MapToExecutionUnit(IndentDemandRawDTO raw, DemandType demandType, int euId) { var eu = new ExecutionUnit { EuId = euId, DemandType = demandType, SourceDocumentId = raw.SourceDocumentId, SourceDetailId = raw.SourceDetailId, ItemId = raw.ItemId, SkuId = raw.SkuId, RoutingVersionDetailId = raw.RoutingVersionDetailId, WorkCenterId = raw.WorkCenterId, ProcessId = raw.ProcessId, FixedMachineId = raw.FixedMachineId, Quantity = raw.Quantity, DurationMinutes = raw.DurationMinutes, IsInterruptible = raw.IsInterruptible, MinimumRunMinutes = raw.MinimumRunMinutes, MaxWaitMinutes = raw.MaxWaitMinutes, ExecutionMode = raw.ExecutionMode, BatchContinuity = raw.BatchContinuity, IsMonitorOnly = raw.IsMonitorOnly, PlanNature = raw.PlanNature, MonitorGroup = raw.MonitorGroup, IsGroupOutputStep = raw.IsGroupOutputStep, EarliestStart = raw.EarliestStart, ComputedEarliestStart = raw.EarliestStart, Deadline = raw.Deadline, Priority = raw.Priority, DurationSource = raw.DurationSource, QuantityDecimalPlaces = raw.QuantityDecimalPlaces, IsPatternRequired = raw.IsPatternRequired, Splits = raw.Splits }; // Parse predecessor string "1,2,3" → List if (!string.IsNullOrWhiteSpace(raw.PredecessorStr)) { eu.PredecessorEuIds = raw.PredecessorStr .Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(s => int.TryParse(s.Trim(), out int id) ? id : 0) .Where(id => id > 0) .ToList(); } return eu; } // Flat DB row — only used inside this DAL for mapping; not exposed outside. // IS* fields are TINYINT with 0=Yes convention — kept as byte to match DB type exactly. private class IndentDemandRawDTO { public int SourceDetailId { get; set; } public int SourceDocumentId { get; set; } public int ItemId { get; set; } public int SkuId { get; set; } public int RoutingVersionDetailId { get; set; } public int WorkCenterId { get; set; } public int ProcessId { get; set; } public decimal Quantity { get; set; } public int DurationMinutes { get; set; } public byte IsInterruptible { get; set; } // 0=Yes 1=No public int MinimumRunMinutes { get; set; } public int MaxWaitMinutes { get; set; } public byte ExecutionMode { get; set; } public byte BatchContinuity { get; set; } public byte IsMonitorOnly { get; set; } // 0=Yes 1=No public byte PlanNature { get; set; } public string? MonitorGroup { get; set; } public byte IsGroupOutputStep { get; set; } // 0=Yes 1=No public int? FixedMachineId { get; set; } public DateTime EarliestStart { get; set; } public DateTime Deadline { get; set; } public string? PredecessorStr { get; set; } public int Priority { get; set; } public byte DurationSource { get; set; } // 0=Routing/BOR 1=Manual 2=Subcontract public int QuantityDecimalPlaces { get; set; } // from MUOM.DECIMALPLACES; default 2 public byte IsPatternRequired { get; set; } // 0=Yes 1=No — from MPROCESS.ISPATTERNREQUIRED public byte Splits { get; set; } = 1; // from MROUTINGVERSIONDETAIL.SPLITS } } }