2026-10-19 14:35:08 +00:00
-- Tamamla: yapı lan miktarlar stoğa işlenir (Stk_T_Stock, ürün biriminde, lot kı rı lı mlı ). İç konumdan çı kı şta stok yetmezse
2026-10-14 19:26:03 +00:00
-- işlem durur; dı ş konumlar stok tutmaz. Kaynak ve hedefi aynı konum olan belge stoğa dokunmaz (teslim kaydı dı r). Envanter takibi kapalı ürün stoğa girmez. Lot/seri takipli üründe lot toplamı
2026-10-14 09:07:11 +00:00
-- yapı lan miktara eşit olmalı dı r. Sipariş kalemlerinin alı nan, talep kalemlerinin teslim edilen miktarı güncellenir (iadede düşülür);
2026-10-19 14:35:08 +00:00
-- siparişli alı m ürün– tedarikçi fiyatı nı yazar (Stk_P_TransferSupplierPrice).
2026-10-12 21:43:05 +00:00
-- Talepten az yapı lan satı rları n kalanı aynı türde yeni belgeye (backorder) geçer.
2026-10-19 14:35:08 +00:00
CREATE OR ALTER PROCEDURE [ dbo ] . [ Stk_P_TransferValidate ]
2026-10-12 21:43:05 +00:00
@ Id uniqueidentifier ,
@ UserId uniqueidentifier = NULL
AS
BEGIN
SET NOCOUNT ON ;
SET XACT_ABORT ON ;
DECLARE @ Tenant uniqueidentifier , @ Status nvarchar ( 16 ) , @ Kind nvarchar ( 32 ) , @ ReturnOf uniqueidentifier ,
@ Src uniqueidentifier , @ Dst uniqueidentifier , @ SrcInternal bit = 0 , @ DstInternal bit = 0 ,
@ DstBranch uniqueidentifier , @ DstWarehouse uniqueidentifier , @ Sign int , @ New uniqueidentifier ,
@ Now datetime = GETUTCDATE ( ) , @ Msg nvarchar ( 512 ) ;
BEGIN TRANSACTION ;
SELECT @ Tenant = TenantId , @ Status = Status , @ Kind = OperationKind , @ ReturnOf = ReturnOfId ,
@ Src = SourceLocationId , @ Dst = DestinationLocationId
2026-10-19 14:35:08 +00:00
FROM Stk_T_Transfer WITH ( UPDLOCK , HOLDLOCK )
2026-10-12 21:43:05 +00:00
WHERE Id = @ Id ;
IF @ Status < > ' Ready ' THROW 50306 , N ' Yalnı z hazı r belge tamamlanabilir. ' , 1 ;
SET @ Sign = CASE WHEN @ ReturnOf IS NULL THEN 1 ELSE - 1 END ;
2026-10-19 14:35:08 +00:00
SELECT @ SrcInternal = CASE WHEN LocationType = ' Internal ' THEN 1 ELSE 0 END FROM Stk_T_Location WHERE Id = @ Src ;
2026-10-12 21:43:05 +00:00
SELECT @ DstInternal = CASE WHEN LocationType = ' Internal ' THEN 1 ELSE 0 END , @ DstBranch = BranchId , @ DstWarehouse = WarehouseId
2026-10-19 14:35:08 +00:00
FROM Stk_T_Location WHERE Id = @ Dst ;
2026-10-12 21:43:05 +00:00
2026-10-19 14:35:08 +00:00
IF NOT EXISTS ( SELECT 1 FROM Stk_T_TransferLine WHERE TransferId = @ Id AND IsDeleted = 0 AND Quantity > 0 )
2026-10-12 21:43:05 +00:00
THROW 50309 , N ' Yapı lan miktarı girilmiş satı r yok. ' , 1 ;
SELECT TOP 1 @ Msg = CONCAT ( p . Name , N ' : lot/seri toplamı ' , FORMAT ( z . Quantity , ' 0.#### ' ) , N ' , yapı lan miktar ' , FORMAT ( l . Quantity , ' 0.#### ' ) )
2026-10-19 14:35:08 +00:00
FROM Stk_T_TransferLine l
INNER JOIN Stk_T_Product p ON p . Id = l . ProductId
CROSS APPLY ( SELECT ISNULL ( SUM ( lt . Quantity ) , 0 ) AS Quantity FROM Stk_T_TransferLineLot lt WHERE lt . TransferLineId = l . Id AND lt . IsDeleted = 0 ) z
2026-10-12 21:43:05 +00:00
WHERE l . TransferId = @ Id AND l . IsDeleted = 0 AND l . Quantity > 0 AND p . TrackInventory = 1 AND p . TrackingMethod IN ( ' Lot ' , ' Serial ' )
AND z . Quantity < > l . Quantity ;
IF @ Msg IS NOT NULL
BEGIN
SET @ Msg = CONCAT ( N ' Lot/seri miktarı yapı lan miktara eşit değil — ' , @ Msg ) ;
THROW 50310 , @ Msg , 1 ;
END
SELECT TOP 1 @ Msg = CONCAT ( p . Name , ' / ' , z . LotNo )
2026-10-19 14:35:08 +00:00
FROM Stk_T_TransferLineLot z
INNER JOIN Stk_T_TransferLine l ON l . Id = z . TransferLineId
INNER JOIN Stk_T_Product p ON p . Id = l . ProductId
2026-10-12 21:43:05 +00:00
WHERE l . TransferId = @ Id AND l . IsDeleted = 0 AND z . IsDeleted = 0 AND p . TrackingMethod = ' Serial '
2026-10-19 14:35:08 +00:00
AND ( z . Quantity < > 1 OR EXISTS ( SELECT 1 FROM Stk_T_TransferLineLot z2
INNER JOIN Stk_T_TransferLine l2 ON l2 . Id = z2 . TransferLineId
2026-10-12 21:43:05 +00:00
WHERE l2 . TransferId = @ Id AND l2 . IsDeleted = 0 AND z2 . IsDeleted = 0
AND l2 . ProductId = l . ProductId AND z2 . LotNo = z . LotNo AND z2 . Id < > z . Id ) ) ;
IF @ Msg IS NOT NULL
BEGIN
SET @ Msg = CONCAT ( N ' Seri numaralı üründe her seri 1 adet ve tekil olmalı dı r: ' , @ Msg ) ;
THROW 50311 , @ Msg , 1 ;
END
-- Stoğa işlenecek hareket: ürün × lot, ürün biriminde.
DECLARE @ Move TABLE ( ProductId uniqueidentifier NOT NULL , LotNo nvarchar ( 64 ) NOT NULL , Quantity decimal ( 18 , 4 ) NOT NULL , UomId nvarchar ( 64 ) NOT NULL ,
PRIMARY KEY ( ProductId , LotNo ) ) ;
INSERT INTO @ Move ( ProductId , LotNo , Quantity , UomId )
SELECT m . ProductId , m . LotNo , SUM ( m . Quantity ) , m . UomId
FROM ( SELECT l . ProductId , p . UomId ,
CASE WHEN p . TrackingMethod IN ( ' Lot ' , ' Serial ' ) THEN z . LotNo ELSE ' ' END AS LotNo ,
2026-10-19 14:35:08 +00:00
dbo . Stk_F_UomConvert ( CASE WHEN p . TrackingMethod IN ( ' Lot ' , ' Serial ' ) THEN z . Quantity ELSE l . Quantity END , l . UomId , p . UomId ) AS Quantity
FROM Stk_T_TransferLine l
INNER JOIN Stk_T_Product p ON p . Id = l . ProductId
LEFT JOIN Stk_T_TransferLineLot z ON z . TransferLineId = l . Id AND z . IsDeleted = 0 AND p . TrackingMethod IN ( ' Lot ' , ' Serial ' )
2026-10-12 21:43:05 +00:00
WHERE l . TransferId = @ Id AND l . IsDeleted = 0 AND l . Quantity > 0 AND p . TrackInventory = 1 ) m
GROUP BY m . ProductId , m . LotNo , m . UomId ;
IF @ SrcInternal = 1
BEGIN
SELECT TOP 1 @ Msg = CONCAT ( p . Name , CASE WHEN m . LotNo = ' ' THEN ' ' ELSE CONCAT ( ' / ' , m . LotNo ) END )
FROM @ Move m
2026-10-19 14:35:08 +00:00
INNER JOIN Stk_T_Product p ON p . Id = m . ProductId
LEFT JOIN Stk_T_Stock s WITH ( UPDLOCK , HOLDLOCK )
2026-10-12 21:43:05 +00:00
ON s . LocationId = @ Src AND s . ProductId = m . ProductId AND s . LotNo = m . LotNo
AND ( s . TenantId = @ Tenant OR ( s . TenantId IS NULL AND @ Tenant IS NULL ) )
WHERE ISNULL ( s . Quantity , 0 ) < m . Quantity ;
IF @ Msg IS NOT NULL
BEGIN
SET @ Msg = CONCAT ( N ' Kaynak konumda yeterli stok yok: ' , @ Msg ) ;
THROW 50312 , @ Msg , 1 ;
END
2026-10-14 19:26:03 +00:00
-- Kaynak ve hedef aynı ysa stok yerinde kalı r: belge teslimi kaydeder (yeterlilik yine denetlenir).
IF @ Src < > @ Dst
UPDATE s SET Quantity = s . Quantity - m . Quantity , LastMoveDate = @ Now , LastModificationTime = @ Now , LastModifierId = @ UserId
2026-10-19 14:35:08 +00:00
FROM Stk_T_Stock s
2026-10-14 19:26:03 +00:00
INNER JOIN @ Move m ON m . ProductId = s . ProductId AND m . LotNo = s . LotNo
WHERE s . LocationId = @ Src AND ( s . TenantId = @ Tenant OR ( s . TenantId IS NULL AND @ Tenant IS NULL ) ) ;
2026-10-12 21:43:05 +00:00
END
2026-10-14 19:26:03 +00:00
IF @ DstInternal = 1 AND @ Src < > @ Dst
2026-10-12 21:43:05 +00:00
BEGIN
UPDATE s SET Quantity = s . Quantity + m . Quantity , LastMoveDate = @ Now , LastModificationTime = @ Now , LastModifierId = @ UserId ,
InDate = CASE WHEN s . Quantity < = 0 THEN @ Now ELSE s . InDate END
2026-10-19 14:35:08 +00:00
FROM Stk_T_Stock s WITH ( UPDLOCK , HOLDLOCK )
2026-10-12 21:43:05 +00:00
INNER JOIN @ Move m ON m . ProductId = s . ProductId AND m . LotNo = s . LotNo
WHERE s . LocationId = @ Dst AND ( s . TenantId = @ Tenant OR ( s . TenantId IS NULL AND @ Tenant IS NULL ) ) ;
2026-10-19 14:35:08 +00:00
INSERT INTO Stk_T_Stock ( Id , TenantId , BranchId , WarehouseId , LocationId , ProductId , LotNo , Quantity , UomId , InDate , LastMoveDate , CreationTime , CreatorId , IsDeleted )
2026-10-12 21:43:05 +00:00
SELECT NEWID ( ) , @ Tenant , @ DstBranch , @ DstWarehouse , @ Dst , m . ProductId , m . LotNo , m . Quantity , m . UomId , @ Now , @ Now , @ Now , @ UserId , 0
FROM @ Move m
2026-10-19 14:35:08 +00:00
WHERE NOT EXISTS ( SELECT 1 FROM Stk_T_Stock s
2026-10-12 21:43:05 +00:00
WHERE s . LocationId = @ Dst AND s . ProductId = m . ProductId AND s . LotNo = m . LotNo
AND ( s . TenantId = @ Tenant OR ( s . TenantId IS NULL AND @ Tenant IS NULL ) ) ) ;
END
2026-10-19 14:35:08 +00:00
UPDATE Stk_T_Transfer
2026-10-12 21:43:05 +00:00
SET Status = ' Done ' , EffectiveDate = @ Now ,
ReceivedByUserId = CASE WHEN @ Kind = ' InternalTransfer ' THEN @ UserId ELSE ReceivedByUserId END ,
ReceivedDate = CASE WHEN @ Kind = ' InternalTransfer ' THEN @ Now ELSE ReceivedDate END
WHERE Id = @ Id ;
UPDATE ol SET ReceivedQuantity = ol . ReceivedQuantity + @ Sign * x . Quantity
FROM Prc_T_PurchaseOrderLine ol
2026-10-19 14:35:08 +00:00
INNER JOIN ( SELECT l . PurchaseOrderLineId , SUM ( dbo . Stk_F_UomConvert ( l . Quantity , l . UomId , pl . UomId ) ) AS Quantity
FROM Stk_T_TransferLine l
2026-10-12 21:43:05 +00:00
INNER JOIN Prc_T_PurchaseOrderLine pl ON pl . Id = l . PurchaseOrderLineId
WHERE l . TransferId = @ Id AND l . IsDeleted = 0 AND l . Quantity > 0
GROUP BY l . PurchaseOrderLineId ) x ON x . PurchaseOrderLineId = ol . Id ;
2026-10-19 14:35:08 +00:00
EXEC Stk_P_TransferSupplierPrice @ Id , @ UserId ;
2026-10-14 09:07:11 +00:00
2026-10-12 21:43:05 +00:00
UPDATE i SET DeliveredQuantity = i . DeliveredQuantity + @ Sign * x . Quantity ,
LineStatus = CASE WHEN i . DeliveredQuantity + @ Sign * x . Quantity > = i . Quantity THEN ' Done '
WHEN i . LineStatus = ' Done ' THEN ' Waiting ' ELSE i . LineStatus END
FROM Prc_T_MaterialRequestItem i
2026-10-19 14:35:08 +00:00
INNER JOIN ( SELECT l . MaterialRequestItemId , SUM ( dbo . Stk_F_UomConvert ( l . Quantity , l . UomId , mi . UomId ) ) AS Quantity
FROM Stk_T_TransferLine l
2026-10-12 21:43:05 +00:00
INNER JOIN Prc_T_MaterialRequestItem mi ON mi . Id = l . MaterialRequestItemId
WHERE l . TransferId = @ Id AND l . IsDeleted = 0 AND l . Quantity > 0
GROUP BY l . MaterialRequestItemId ) x ON x . MaterialRequestItemId = i . Id ;
2026-10-19 14:35:08 +00:00
IF @ ReturnOf IS NULL AND EXISTS ( SELECT 1 FROM Stk_T_TransferLine WHERE TransferId = @ Id AND IsDeleted = 0 AND Quantity < DemandQuantity )
EXEC Stk_P_TransferCopy @ Id , ' Backorder ' , @ UserId , @ New OUTPUT ;
2026-10-12 21:43:05 +00:00
2026-10-19 14:35:08 +00:00
EXEC Stk_P_TransferRecalc @ Id ;
2026-10-12 21:43:05 +00:00
COMMIT TRANSACTION ;
END