-- Planlama kararı: talep kaleminin planlanacak kalanından @PlanQuantity kadarını satınalmaya ya da iç transfere ayırır; kalanın geri kalanı -- listede kalır. Planla diyaloğunun onayı (Prc_P_MaterialRequestPlanConfirm) her taslak plan satırı için çağırır. -- Purchase: tedarikçinin talebin şubesi ve deposu için taslak teklif talebi varsa kalem ona eklenir (kalem zaten oradaysa miktarı artar), yoksa -- talebin deposunun alım operasyon türüyle yeni taslak teklif talebi açılır (para birimi ve koşullar kontak kartından; alıcı — satınalma sorumlusu — -- planlayan). Fiyat tedarikçinin fiyat listesinden gelir; teklif → sipariş → alım akışı oradan sürer. -- Transfer: kaynak konumun (lot/seri takipli üründe @PlanLotNo lotunun) serbest stoğu (Prc_V_MaterialRequestPlanSource) yetmelidir; aynı -- kaynak → talebin konumu için taslak iç transfer varsa satır ona, yoksa kaynak deponun iç transfer operasyon türüyle yeni -- taslak açılır. Depoda aynı türden birkaç operasyon türü olabilir (Bakım Sarf Tüketimi, Departman Sarf Çıkışı …); türün kendi -- numaratörünü taşıyanı (SequenceName '….InternalTransfer' / '….Receipt' ile biter) seçilir, taslak da yalnız o türde aranır. Lot planlandıysa transfer satırının lot dağılımına (Stk_T_TransferLineLot, satırın biriminde) eklenir; depo Detaylar ya da -- Otomatik Ata ile değiştirebilir. Kalanın tamamı transferle -- planlanan, satınalma payı olmayan kalem transfer belgesinin yeniden hesabında kapanır (Prc_P_MaterialRequestItemSync). -- Stock: stok talebin teslim konumundadır; Transfer gibi iç transfer açılır, kaynak ve hedef teslim konumudur (Doğrula stoğa dokunmaz, -- teslimi kaydeder: kalemin teslim edilen miktarı artar). Belge numarası ve durumu Plan Takibi'ne transferden yansır. CREATE OR ALTER PROCEDURE [dbo].[Prc_P_MaterialRequestPlan] @Id uniqueidentifier, @PlanMethod nvarchar(16), @PlanQuantity decimal(18, 4), @PlanSupplierId uniqueidentifier, @PlanSourceLocationId uniqueidentifier, @PlanLotNo nvarchar(64), @TenantId uniqueidentifier, @LastModifierId uniqueidentifier AS BEGIN SET NOCOUNT ON; SET XACT_ABORT ON; DECLARE @ProductId uniqueidentifier, @UomId nvarchar(64), @DueDate datetime, @Reason nvarchar(256), @Branch uniqueidentifier, @Warehouse uniqueidentifier, @Location uniqueidentifier, @RequestNo nvarchar(32), @Remaining decimal(18, 4), @Doc uniqueidentifier, @Line uniqueidentifier, @OpType uniqueidentifier, @SrcWarehouse uniqueidentifier, @Free decimal(18, 4), @No nvarchar(128), @Msg nvarchar(400); BEGIN TRANSACTION; -- Kalem kilitlenir: aynı kalemin eşzamanlı iki planı kalanı iki kez dağıtamaz. SELECT @ProductId = i.ProductId, @UomId = i.UomId, @DueDate = i.DueDate, @Reason = i.RequestReason, @Branch = r.BranchId, @Warehouse = r.WarehouseId, @Location = r.LocationId, @RequestNo = r.RequestNo FROM Prc_T_MaterialRequestItem i WITH (UPDLOCK, HOLDLOCK) INNER JOIN Prc_T_MaterialRequest r ON r.Id = i.MaterialRequestId WHERE i.Id = @Id AND i.IsDeleted = 0 AND i.LineStatus = 'Waiting' AND r.IsDeleted = 0 AND (i.TenantId = @TenantId OR (i.TenantId IS NULL AND @TenantId IS NULL)) AND r.ApprovalStatus IN (N'Onaylandı', N'Teklif Talebi', N'Teklif Talebi Gönderildi', N'Satınalma Siparişi'); IF @ProductId IS NULL THROW 50191, N'Kalem planlanamaz: talep onaylı değil ya da kalem kapalı.', 1; SELECT @Remaining = RemainingQuantity FROM Prc_V_MaterialRequestItemPlan WHERE Id = @Id; IF ISNULL(@PlanQuantity, 0) <= 0 THROW 50192, N'Plan miktarı sıfırdan büyük olmalıdır.', 1; IF @PlanQuantity > @Remaining BEGIN SET @Msg = CONCAT(N'Plan miktarı planlanacak kalanı aşamaz (kalan: ', FORMAT(@Remaining, '0.####'), N' ', @UomId, N').'); THROW 50193, @Msg, 1; END IF @PlanMethod = 'Purchase' BEGIN IF @PlanSupplierId IS NULL THROW 50194, N'Satınalma kararında tedarikçi seçilmelidir.', 1; SELECT TOP 1 @Doc = Id FROM Prc_T_PurchaseRfq WHERE IsDeleted = 0 AND Status = 'Draft' AND SupplierId = @PlanSupplierId AND BranchId = @Branch AND WarehouseId = @Warehouse AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL)) ORDER BY CreationTime DESC; IF @Doc IS NULL BEGIN SELECT TOP 1 @OpType = Id FROM Stk_T_OperationType WHERE IsDeleted = 0 AND IsActive = 1 AND OperationKind = 'Receipt' AND WarehouseId = @Warehouse AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL)) ORDER BY CASE WHEN SequenceName LIKE CONCAT('%.', OperationKind) THEN 0 ELSE 1 END, Name; IF @OpType IS NULL THROW 50195, N'Talebin deposu için aktif bir alım operasyon türü tanımlı değil.', 1; SET @Doc = NEWID(); EXEC Adm_P_SequenceNext N'Prc.PurchaseRfq', @TenantId, @No OUTPUT; INSERT INTO Prc_T_PurchaseRfq (Id, TenantId, RfqNo, TenderGroupId, SupplierId, BranchId, OperationTypeId, WarehouseId, CurrencyId, BuyerUserId, IncotermId, IncotermLocation, PaymentTermId, CreationTime, CreatorId, IsDeleted) SELECT @Doc, @TenantId, LEFT(@No, 32), @Doc, c.Id, @Branch, @OpType, @Warehouse, COALESCE(c.SupplierCurrency, 'TRY'), @LastModifierId, c.PurchaseIncotermId, c.PurchaseIncotermLocation, c.PurchasePaymentTermId, GETUTCDATE(), @LastModifierId, 0 FROM Adm_T_Contact c WHERE c.Id = @PlanSupplierId AND c.IsDeleted = 0; IF @@ROWCOUNT = 0 THROW 50194, N'Satınalma kararında tedarikçi seçilmelidir.', 1; END SELECT @Line = Id FROM Prc_T_PurchaseRfqLine WHERE PurchaseRfqId = @Doc AND MaterialRequestItemId = @Id AND IsDeleted = 0; IF @Line IS NOT NULL UPDATE Prc_T_PurchaseRfqLine SET Quantity = Quantity + dbo.Stk_F_UomConvert(@PlanQuantity, @UomId, UomId), LastModificationTime = GETUTCDATE(), LastModifierId = @LastModifierId WHERE Id = @Line; ELSE INSERT INTO Prc_T_PurchaseRfqLine (Id, TenantId, PurchaseRfqId, ProductId, Description, Quantity, UomId, UnitPrice, TaxRate, Amount, DeliveryDate, MaterialRequestItemId, CreationTime, CreatorId, IsDeleted) SELECT NEWID(), @TenantId, @Doc, @ProductId, @Reason, @PlanQuantity, @UomId, ISNULL((SELECT TOP 1 ps.Price FROM Stk_T_ProductSupplier ps WHERE ps.ProductId = @ProductId AND ps.ContactId = @PlanSupplierId AND ps.IsDeleted = 0 ORDER BY ps.MinQuantity), 0), ISNULL(p.PurchaseTaxRate, 0), 0, @DueDate, @Id, GETUTCDATE(), @LastModifierId, 0 FROM Stk_T_Product p WHERE p.Id = @ProductId; EXEC Prc_P_PurchaseRfqRecalc @Doc; END ELSE IF @PlanMethod IN ('Transfer', 'Stock') BEGIN IF @PlanMethod = 'Stock' SET @PlanSourceLocationId = @Location; IF @PlanSourceLocationId IS NULL THROW 50196, N'İç transfer kararında kaynak konum seçilmelidir.', 1; -- Konum ve serbest stok kuralı diyaloğun İç Transfer ızgarasıyla aynıdır. SELECT @SrcWarehouse = WarehouseId, @Free = FreeQuantity FROM Prc_V_MaterialRequestPlanSource WHERE BaseId = @Id AND LocationId = @PlanSourceLocationId AND ISNULL(LotNo, '') = ISNULL(@PlanLotNo, ''); IF @SrcWarehouse IS NULL OR (@PlanMethod = 'Transfer' AND @PlanSourceLocationId = @Location) THROW 50197, N'Kaynak konum, talebin teslim konumundan farklı ve ürünün (lot/seri takipli üründe lotun) stoğu olan bir iç konum olmalıdır.', 1; IF @PlanQuantity > @Free BEGIN SET @Msg = CONCAT(N'Kaynak konumda yeterli serbest stok yok (serbest: ', FORMAT(CASE WHEN @Free > 0 THEN @Free ELSE 0 END, '0.####'), N' ', @UomId, N').'); THROW 50198, @Msg, 1; END SELECT TOP 1 @OpType = Id FROM Stk_T_OperationType WHERE IsDeleted = 0 AND IsActive = 1 AND OperationKind = 'InternalTransfer' AND WarehouseId = @SrcWarehouse AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL)) ORDER BY CASE WHEN SequenceName LIKE CONCAT('%.', OperationKind) THEN 0 ELSE 1 END, Name; IF @OpType IS NULL THROW 50199, N'Kaynak depo için aktif bir iç transfer operasyon türü tanımlı değil.', 1; SELECT TOP 1 @Doc = Id FROM Stk_T_Transfer WHERE IsDeleted = 0 AND OperationTypeId = @OpType AND Status = 'Draft' AND ReturnOfId IS NULL AND BackorderOfId IS NULL AND SourceLocationId = @PlanSourceLocationId AND DestinationLocationId = @Location AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL)) ORDER BY CreationTime DESC; IF @Doc IS NULL BEGIN SET @Doc = NEWID(); INSERT INTO Stk_T_Transfer (Id, TenantId, BranchId, WarehouseId, OperationTypeId, OperationKind, SourceLocationId, DestinationLocationId, SourceDocument, ResponsibleUserId, Status, CreationTime, CreatorId, IsDeleted) SELECT @Doc, @TenantId, ot.BranchId, ot.WarehouseId, ot.Id, 'InternalTransfer', @PlanSourceLocationId, @Location, @RequestNo, @LastModifierId, 'Draft', GETUTCDATE(), @LastModifierId, 0 FROM Stk_T_OperationType ot WHERE ot.Id = @OpType; END ELSE UPDATE Stk_T_Transfer SET SourceDocument = LEFT(CONCAT(SourceDocument, CASE WHEN ISNULL(SourceDocument, '') = '' THEN '' ELSE N', ' END, @RequestNo), 128) WHERE Id = @Doc AND CHARINDEX(@RequestNo, ISNULL(SourceDocument, '')) = 0; -- Planlanan miktar yapılacak miktardır: lotsuz satırda doğrudan yazılır, lotlu satırda lot dağılımından (Stk_P_TransferRecalc) gelir. SELECT @Line = Id FROM Stk_T_TransferLine WHERE TransferId = @Doc AND MaterialRequestItemId = @Id AND IsDeleted = 0; IF @Line IS NOT NULL UPDATE Stk_T_TransferLine SET DemandQuantity = DemandQuantity + dbo.Stk_F_UomConvert(@PlanQuantity, @UomId, UomId), Quantity = Quantity + CASE WHEN ISNULL(@PlanLotNo, '') = '' THEN dbo.Stk_F_UomConvert(@PlanQuantity, @UomId, UomId) ELSE 0 END, LastModificationTime = GETUTCDATE(), LastModifierId = @LastModifierId WHERE Id = @Line; ELSE BEGIN SET @Line = NEWID(); INSERT INTO Stk_T_TransferLine (Id, TenantId, TransferId, ProductId, Description, DemandQuantity, Quantity, UomId, MaterialRequestItemId, CreationTime, CreatorId, IsDeleted) VALUES (@Line, @TenantId, @Doc, @ProductId, @Reason, @PlanQuantity, CASE WHEN ISNULL(@PlanLotNo, '') = '' THEN @PlanQuantity ELSE 0 END, @UomId, @Id, GETUTCDATE(), @LastModifierId, 0); END IF ISNULL(@PlanLotNo, '') <> '' BEGIN UPDATE ll SET Quantity = ll.Quantity + dbo.Stk_F_UomConvert(@PlanQuantity, @UomId, tl.UomId), LastModificationTime = GETUTCDATE(), LastModifierId = @LastModifierId FROM Stk_T_TransferLineLot ll INNER JOIN Stk_T_TransferLine tl ON tl.Id = ll.TransferLineId WHERE ll.TransferLineId = @Line AND ll.LotNo = @PlanLotNo AND ll.IsDeleted = 0; IF @@ROWCOUNT = 0 INSERT INTO Stk_T_TransferLineLot (Id, TenantId, TransferLineId, LotNo, Quantity, CreationTime, CreatorId, IsDeleted) SELECT NEWID(), @TenantId, tl.Id, @PlanLotNo, dbo.Stk_F_UomConvert(@PlanQuantity, @UomId, tl.UomId), GETUTCDATE(), @LastModifierId, 0 FROM Stk_T_TransferLine tl WHERE tl.Id = @Line; END -- Numara ve yeniden hesap (kalemin kapanması dahil) belge kaydı sonrasıyla aynıdır. EXEC Stk_P_TransferAfterSave @Doc, @LastModifierId; END ELSE THROW 50192, N'Karar Satınalma, İç Transfer ya da Stoktan olmalıdır.', 1; COMMIT TRANSACTION; END