CREATE OR ALTER PROCEDURE [dbo].[Mnt_S_MaintenanceInstructionSchedule] AS BEGIN SET NOCOUNT ON; -- Zamanlanmış iş (Maintenance Instruction Schedule, her gece 01:00). -- 0. Sonraki bakım tarihi boş olan aktif talimatın tarihi önce hesaplanır; böylece başlangıcı geçmiş ya da yeni -- onaylanan talimatın bugünkü vadesi aynı çalıştırmada iş emri alır. -- 1. Sonraki bakım tarihi bugün ya da geçmiş olan aktif ve onaylanmış her talimattan o vade için Taslak, Otomatik bakım -- iş emri açar: numara Mnt.WorkOrder numaratöründen, ekip talimatın ilk ekibi, malzemeler talimattan; kullanım konumu -- ekipmanın departmanının ilk iç konumudur. Aynı talimat ve vade için otomatik emir varsa tekrar açılmaz; önceki -- emir kapanmamış olsa da her vade yeni emir alır. -- 2. Aktif talimatların sonraki bakım tarihini Başlangıç Tarihi + k × periyot dizisinde bugüne eşit ya da bugünden -- sonraki ilk tarihe taşır; Bitiş Tarihi geçmişse ya da talimat pasifse tarih boşalır. -- İş host ve her kiracı için çağrılır, yordam parametre almaz; bütün kiracıların satırlarını işler ve aynı gün tekrar -- çalışması sonucu değiştirmez. DECLARE @Today date = CAST(GETDATE() AS date); DECLARE @Ins uniqueidentifier, @Tenant uniqueidentifier, @Due date, @Wo uniqueidentifier, @No nvarchar(128), @Pass int = 1; WHILE @Pass <= 2 BEGIN IF @Pass = 2 BEGIN DECLARE due_cursor CURSOR LOCAL FAST_FORWARD FOR SELECT i.Id, i.TenantId, i.NextDueDate FROM Mnt_T_MaintenanceInstruction i WHERE i.IsDeleted = 0 AND i.IsActive = 1 AND i.ApprovalStatus = N'Onaylandı' AND i.NextDueDate IS NOT NULL AND i.NextDueDate <= @Today AND NOT EXISTS (SELECT 1 FROM Mnt_T_WorkOrder w WHERE w.MaintenanceInstructionId = i.Id AND w.Source = 'Automatic' AND w.IsDeleted = 0 AND CAST(w.PlannedStart AS date) = i.NextDueDate); OPEN due_cursor; FETCH NEXT FROM due_cursor INTO @Ins, @Tenant, @Due; WHILE @@FETCH_STATUS = 0 BEGIN SET @Wo = NEWID(); SET @No = NULL; EXEC dbo.Adm_P_SequenceNext N'Mnt.WorkOrder', @Tenant, @No OUTPUT; INSERT INTO Mnt_T_WorkOrder (Id, TenantId, BranchId, WorkOrderNo, Name, EquipmentId, RequestDate, MaintenanceKind, ResourceType, MaintenanceTypeId, TeamId, Source, MaintenanceInstructionId, PlannedStart, Priority, Status, IsActive, CreationTime, IsDeleted) SELECT @Wo, i.TenantId, i.BranchId, LEFT(@No, 32), LEFT(CONCAT(i.Name, N' - ', p.Name), 256), i.EquipmentId, @Today, 'Preventive', 'Internal', i.MaintenanceTypeId, TRY_CAST(LEFT(i.TeamIds, CHARINDEX('|', CONCAT(i.TeamIds, '|')) - 1) AS uniqueidentifier), 'Automatic', i.Id, DATEADD(hour, 8, CAST(@Due AS datetime)), 0, 'Draft', 1, GETUTCDATE(), 0 FROM Mnt_T_MaintenanceInstruction i INNER JOIN Stk_T_Product p ON p.Id = i.EquipmentId WHERE i.Id = @Ins; INSERT INTO Mnt_T_WorkOrderMaterial (Id, TenantId, WorkOrderId, ProductId, Quantity, UomId, LocationId, Description, CreationTime, IsDeleted) SELECT NEWID(), m.TenantId, @Wo, m.ProductId, m.Quantity, m.UomId, (SELECT TOP 1 l.Id FROM Mnt_T_MaintenanceInstruction i INNER JOIN Stk_T_Product p ON p.Id = i.EquipmentId INNER JOIN Stk_T_Location l ON l.DepartmentId = p.EquipmentDepartmentId WHERE i.Id = @Ins AND l.IsDeleted = 0 AND l.IsActive = 1 AND l.LocationType = 'Internal' ORDER BY l.Code, l.Name), m.Description, GETUTCDATE(), 0 FROM Mnt_T_MaintenanceInstructionMaterial m WHERE m.MaintenanceInstructionId = @Ins AND m.IsDeleted = 0 AND m.IsActive = 1; EXEC dbo.Mnt_P_WorkOrderAfterSave @Wo, NULL; FETCH NEXT FROM due_cursor INTO @Ins, @Tenant, @Due; END CLOSE due_cursor; DEALLOCATE due_cursor; END UPDATE i SET NextDueDate = CASE WHEN n.NextDate > i.EndDate THEN NULL ELSE n.NextDate END FROM Mnt_T_MaintenanceInstruction i CROSS APPLY ( SELECT CASE WHEN i.PeriodUnit IN ('Month', 'Year') THEN 1 ELSE 0 END AS IsMonth, CASE i.PeriodUnit WHEN 'Week' THEN 7 * i.PeriodValue WHEN 'Year' THEN 12 * i.PeriodValue ELSE i.PeriodValue END AS Step ) s CROSS APPLY ( SELECT CASE WHEN s.IsMonth = 1 THEN DATEDIFF(month, i.StartDate, @Today) ELSE DATEDIFF(day, i.StartDate, @Today) END / s.Step AS K ) k CROSS APPLY ( SELECT CASE WHEN s.IsMonth = 1 THEN DATEADD(month, k.K * s.Step, i.StartDate) ELSE DATEADD(day, k.K * s.Step, i.StartDate) END AS Candidate ) c CROSS APPLY ( SELECT CASE WHEN i.StartDate >= @Today THEN i.StartDate WHEN c.Candidate >= @Today THEN c.Candidate WHEN s.IsMonth = 1 THEN DATEADD(month, (k.K + 1) * s.Step, i.StartDate) ELSE DATEADD(day, (k.K + 1) * s.Step, i.StartDate) END AS NextDate ) n WHERE i.IsDeleted = 0 AND i.IsActive = 1 AND i.PeriodValue > 0 AND (@Pass = 2 OR i.NextDueDate IS NULL); SET @Pass += 1; END UPDATE Mnt_T_MaintenanceInstruction SET NextDueDate = NULL WHERE NextDueDate IS NOT NULL AND (IsDeleted = 1 OR IsActive = 0 OR PeriodValue <= 0); END GO