140 lines
8.4 KiB
Transact-SQL
140 lines
8.4 KiB
Transact-SQL
-- Tamamla: yapılan miktarlar stoğa işlenir (Inv_T_Stock, ürün biriminde, lot kırılımlı). İç konumdan çıkışta stok yetmezse
|
||
-- işlem durur; dış konumlar stok tutmaz. Envanter takibi kapalı ürün stoğa girmez. Lot/seri takipli üründe lot toplamı
|
||
-- yapılan miktara eşit olmalıdır. Sipariş kalemlerinin alınan, talep kalemlerinin teslim edilen miktarı güncellenir (iadede düşülür).
|
||
-- Talepten az yapılan satırların kalanı aynı türde yeni belgeye (backorder) geçer.
|
||
CREATE OR ALTER PROCEDURE [dbo].[Inv_P_TransferValidate]
|
||
@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
|
||
FROM Inv_T_Transfer WITH (UPDLOCK, HOLDLOCK)
|
||
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;
|
||
|
||
SELECT @SrcInternal = CASE WHEN LocationType = 'Internal' THEN 1 ELSE 0 END FROM Inv_T_Location WHERE Id = @Src;
|
||
SELECT @DstInternal = CASE WHEN LocationType = 'Internal' THEN 1 ELSE 0 END, @DstBranch = BranchId, @DstWarehouse = WarehouseId
|
||
FROM Inv_T_Location WHERE Id = @Dst;
|
||
|
||
IF NOT EXISTS (SELECT 1 FROM Inv_T_TransferLine WHERE TransferId = @Id AND IsDeleted = 0 AND Quantity > 0)
|
||
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.####'))
|
||
FROM Inv_T_TransferLine l
|
||
INNER JOIN Inv_T_Product p ON p.Id = l.ProductId
|
||
CROSS APPLY (SELECT ISNULL(SUM(lt.Quantity), 0) AS Quantity FROM Inv_T_TransferLineLot lt WHERE lt.TransferLineId = l.Id AND lt.IsDeleted = 0) z
|
||
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)
|
||
FROM Inv_T_TransferLineLot z
|
||
INNER JOIN Inv_T_TransferLine l ON l.Id = z.TransferLineId
|
||
INNER JOIN Inv_T_Product p ON p.Id = l.ProductId
|
||
WHERE l.TransferId = @Id AND l.IsDeleted = 0 AND z.IsDeleted = 0 AND p.TrackingMethod = 'Serial'
|
||
AND (z.Quantity <> 1 OR EXISTS (SELECT 1 FROM Inv_T_TransferLineLot z2
|
||
INNER JOIN Inv_T_TransferLine l2 ON l2.Id = z2.TransferLineId
|
||
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,
|
||
dbo.Inv_F_UomConvert(CASE WHEN p.TrackingMethod IN ('Lot', 'Serial') THEN z.Quantity ELSE l.Quantity END, l.UomId, p.UomId) AS Quantity
|
||
FROM Inv_T_TransferLine l
|
||
INNER JOIN Inv_T_Product p ON p.Id = l.ProductId
|
||
LEFT JOIN Inv_T_TransferLineLot z ON z.TransferLineId = l.Id AND z.IsDeleted = 0 AND p.TrackingMethod IN ('Lot', 'Serial')
|
||
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
|
||
INNER JOIN Inv_T_Product p ON p.Id = m.ProductId
|
||
LEFT JOIN Inv_T_Stock s WITH (UPDLOCK, HOLDLOCK)
|
||
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
|
||
|
||
UPDATE s SET Quantity = s.Quantity - m.Quantity, LastMoveDate = @Now, LastModificationTime = @Now, LastModifierId = @UserId
|
||
FROM Inv_T_Stock s
|
||
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));
|
||
END
|
||
|
||
IF @DstInternal = 1
|
||
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
|
||
FROM Inv_T_Stock s WITH (UPDLOCK, HOLDLOCK)
|
||
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));
|
||
|
||
INSERT INTO Inv_T_Stock (Id, TenantId, BranchId, WarehouseId, LocationId, ProductId, LotNo, Quantity, UomId, InDate, LastMoveDate, CreationTime, CreatorId, IsDeleted)
|
||
SELECT NEWID(), @Tenant, @DstBranch, @DstWarehouse, @Dst, m.ProductId, m.LotNo, m.Quantity, m.UomId, @Now, @Now, @Now, @UserId, 0
|
||
FROM @Move m
|
||
WHERE NOT EXISTS (SELECT 1 FROM Inv_T_Stock s
|
||
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
|
||
|
||
UPDATE Inv_T_Transfer
|
||
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
|
||
INNER JOIN (SELECT l.PurchaseOrderLineId, SUM(dbo.Inv_F_UomConvert(l.Quantity, l.UomId, pl.UomId)) AS Quantity
|
||
FROM Inv_T_TransferLine l
|
||
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;
|
||
|
||
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
|
||
INNER JOIN (SELECT l.MaterialRequestItemId, SUM(dbo.Inv_F_UomConvert(l.Quantity, l.UomId, mi.UomId)) AS Quantity
|
||
FROM Inv_T_TransferLine l
|
||
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;
|
||
|
||
IF @ReturnOf IS NULL AND EXISTS (SELECT 1 FROM Inv_T_TransferLine WHERE TransferId = @Id AND IsDeleted = 0 AND Quantity < DemandQuantity)
|
||
EXEC Inv_P_TransferCopy @Id, 'Backorder', @UserId, @New OUTPUT;
|
||
|
||
EXEC Inv_P_TransferRecalc @Id;
|
||
COMMIT TRANSACTION;
|
||
END
|