sozsoft-platform/configs/seeds/sql/object/Inv_P_TransferValidate.sql

144 lines
8.6 KiB
MySQL
Raw Normal View History

2026-10-12 21:43:05 +00:00
-- 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ı
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);
-- siparişli alım ürün–tedarikçi fiyatını yazar (Inv_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.
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;
2026-10-14 09:07:11 +00:00
EXEC Inv_P_TransferSupplierPrice @Id, @UserId;
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
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