sozsoft-platform/configs/seeds/sql/object/Prc_P_MaterialRequestPlan.sql
2026-10-14 12:07:11 +03:00

182 lines
11 KiB
Transact-SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 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 serbest stoğu (Prc_V_MaterialRequestPlanSource) yetmelidir; aynı kaynak → talebin konumu için onaya
-- girmemiş taslak iç transfer varsa satır ona, yoksa kaynak deponun iç transfer operasyon türüyle yeni taslak açılır. 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; belge açılmaz, serbest stok yetmelidir. Miktar kalemin stoktan karşılanan ve teslim edilen
-- miktarına eklenir; satınalma payı olmayan ve kalanı biten kalem kapanır.
CREATE OR ALTER PROCEDURE [dbo].[Prc_P_MaterialRequestPlan]
@Id uniqueidentifier,
@PlanMethod nvarchar(16),
@PlanQuantity decimal(18, 4),
@PlanSupplierId uniqueidentifier,
@PlanSourceLocationId uniqueidentifier,
@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 Inv_T_OperationType
WHERE IsDeleted = 0 AND IsActive = 1 AND OperationKind = 'Receipt' AND WarehouseId = @Warehouse
ORDER BY 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.Inv_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 Inv_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 Inv_T_Product p
WHERE p.Id = @ProductId;
EXEC Prc_P_PurchaseRfqRecalc @Doc;
END
ELSE IF @PlanMethod = 'Transfer'
BEGIN
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;
IF @SrcWarehouse IS NULL OR @PlanSourceLocationId = @Location
THROW 50197, N'Kaynak konum, talebin teslim konumundan farklı ve ürünün 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 @Doc = Id
FROM Inv_T_Transfer
WHERE IsDeleted = 0 AND OperationKind = 'InternalTransfer' AND Status = 'Draft' AND ReturnOfId IS NULL AND BackorderOfId IS NULL
AND SourceLocationId = @PlanSourceLocationId AND DestinationLocationId = @Location
AND ISNULL(ApprovalStatus, N'Onay Gerekmez') = N'Onay Gerekmez'
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 Inv_T_OperationType
WHERE IsDeleted = 0 AND IsActive = 1 AND OperationKind = 'InternalTransfer' AND WarehouseId = @SrcWarehouse
ORDER BY Name;
IF @OpType IS NULL
THROW 50199, N'Kaynak depo için aktif bir iç transfer operasyon türü tanımlı değil.', 1;
SET @Doc = NEWID();
INSERT INTO Inv_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 Inv_T_OperationType ot
WHERE ot.Id = @OpType;
END
ELSE
UPDATE Inv_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;
SELECT @Line = Id FROM Inv_T_TransferLine WHERE TransferId = @Doc AND MaterialRequestItemId = @Id AND IsDeleted = 0;
IF @Line IS NOT NULL
UPDATE Inv_T_TransferLine
SET DemandQuantity = DemandQuantity + dbo.Inv_F_UomConvert(@PlanQuantity, @UomId, UomId), LastModificationTime = GETUTCDATE(), LastModifierId = @LastModifierId
WHERE Id = @Line;
ELSE
INSERT INTO Inv_T_TransferLine (Id, TenantId, TransferId, ProductId, Description, DemandQuantity, Quantity, UomId, MaterialRequestItemId,
CreationTime, CreatorId, IsDeleted)
VALUES (NEWID(), @TenantId, @Doc, @ProductId, @Reason, @PlanQuantity, 0, @UomId, @Id, GETUTCDATE(), @LastModifierId, 0);
-- Numara, kaynak depo onaycısı ve yeniden hesap (kalemin kapanması dahil) belge kaydı sonrasıyla aynıdır.
EXEC Inv_P_TransferAfterSave @Doc, @LastModifierId;
END
ELSE IF @PlanMethod = 'Stock'
BEGIN
SELECT @Free = FreeQuantity FROM Prc_V_MaterialRequestPlanSource WHERE BaseId = @Id AND LocationId = @Location;
IF @PlanQuantity > ISNULL(@Free, 0)
BEGIN
SET @Msg = CONCAT(N'Teslim konumunda yeterli serbest stok yok (serbest: ', FORMAT(CASE WHEN @Free > 0 THEN @Free ELSE 0 END, '0.####'), N' ', @UomId, N').');
THROW 50198, @Msg, 1;
END
UPDATE Prc_T_MaterialRequestItem
SET FromStockQuantity = FromStockQuantity + @PlanQuantity, DeliveredQuantity = DeliveredQuantity + @PlanQuantity,
LastModificationTime = GETUTCDATE(), LastModifierId = @LastModifierId
WHERE Id = @Id;
UPDATE i SET LineStatus = 'Done'
FROM Prc_T_MaterialRequestItem i
INNER JOIN Prc_V_MaterialRequestItemPlan p ON p.Id = i.Id
WHERE i.Id = @Id AND p.PurchaseQuantity = 0 AND p.RemainingQuantity <= 0;
END
ELSE
THROW 50192, N'Karar Satınalma, İç Transfer ya da Stoktan olmalıdır.', 1;
COMMIT TRANSACTION;
END