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
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);
-- 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 REPLACE PROCEDURE public . " Inv_P_TransferValidate " ( p_id uuid , p_user_id uuid DEFAULT NULL )
LANGUAGE plpgsql AS $ $
DECLARE v_tenant uuid ; v_status varchar ( 16 ) ; v_kind varchar ( 32 ) ; v_return_of uuid ; v_src uuid ; v_dst uuid ;
v_src_internal boolean : = false ; v_dst_internal boolean : = false ; v_dst_branch uuid ; v_dst_warehouse uuid ;
v_sign int ; v_new uuid ; v_now timestamp : = NOW ( ) AT TIME ZONE ' UTC ' ; v_msg varchar ( 512 ) ;
BEGIN
SELECT " TenantId " , " Status " , " OperationKind " , " ReturnOfId " , " SourceLocationId " , " DestinationLocationId "
INTO v_tenant , v_status , v_kind , v_return_of , v_src , v_dst
FROM " Inv_T_Transfer " WHERE " Id " = p_id
FOR UPDATE ;
IF v_status < > ' Ready ' THEN
RAISE EXCEPTION ' Yalnı z hazı r belge tamamlanabilir. ' USING ERRCODE = ' P0001 ' , DETAIL = ' 50306 ' ;
END IF ;
v_sign : = CASE WHEN v_return_of IS NULL THEN 1 ELSE - 1 END ;
SELECT " LocationType " = ' Internal ' INTO v_src_internal FROM " Inv_T_Location " WHERE " Id " = v_src ;
SELECT " LocationType " = ' Internal ' , " BranchId " , " WarehouseId " INTO v_dst_internal , v_dst_branch , v_dst_warehouse
FROM " Inv_T_Location " WHERE " Id " = v_dst ;
v_src_internal : = COALESCE ( v_src_internal , false ) ;
v_dst_internal : = COALESCE ( v_dst_internal , false ) ;
IF NOT EXISTS ( SELECT 1 FROM " Inv_T_TransferLine " WHERE " TransferId " = p_id AND " IsDeleted " = false AND " Quantity " > 0 ) THEN
RAISE EXCEPTION ' Yapı lan miktarı girilmiş satı r yok. ' USING ERRCODE = ' P0001 ' , DETAIL = ' 50309 ' ;
END IF ;
SELECT p . " Name " | | ' : lot/seri toplamı ' | | rtrim ( rtrim ( z . q : : text , ' 0 ' ) , ' . ' ) | | ' , yapı lan miktar ' | | rtrim ( rtrim ( l . " Quantity " : : text , ' 0 ' ) , ' . ' ) INTO v_msg
FROM " Inv_T_TransferLine " l
INNER JOIN " Inv_T_Product " p ON p . " Id " = l . " ProductId "
CROSS JOIN LATERAL ( SELECT COALESCE ( SUM ( lt . " Quantity " ) , 0 ) AS q FROM " Inv_T_TransferLineLot " lt WHERE lt . " TransferLineId " = l . " Id " AND lt . " IsDeleted " = false ) z
WHERE l . " TransferId " = p_id AND l . " IsDeleted " = false AND l . " Quantity " > 0 AND p . " TrackInventory " = true AND p . " TrackingMethod " IN ( ' Lot ' , ' Serial ' )
AND z . q < > l . " Quantity "
LIMIT 1 ;
IF v_msg IS NOT NULL THEN
RAISE EXCEPTION ' Lot/seri miktarı yapı lan miktara eşit değil — % ' , v_msg USING ERRCODE = ' P0001 ' , DETAIL = ' 50310 ' ;
END IF ;
SELECT p . " Name " | | ' / ' | | z . " LotNo " INTO v_msg
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 " = p_id AND l . " IsDeleted " = false AND z . " IsDeleted " = false 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 " = p_id AND l2 . " IsDeleted " = false AND z2 . " IsDeleted " = false
AND l2 . " ProductId " = l . " ProductId " AND z2 . " LotNo " = z . " LotNo " AND z2 . " Id " < > z . " Id " ) )
LIMIT 1 ;
IF v_msg IS NOT NULL THEN
RAISE EXCEPTION ' Seri numaralı üründe her seri 1 adet ve tekil olmalı dı r: % ' , v_msg USING ERRCODE = ' P0001 ' , DETAIL = ' 50311 ' ;
END IF ;
-- Stoğa işlenecek hareket: ürün × lot, ürün biriminde.
DROP TABLE IF EXISTS tmp_inv_move ;
CREATE TEMP TABLE tmp_inv_move AS
SELECT m . " ProductId " , m . " LotNo " , SUM ( m . " Quantity " ) AS " Quantity " , m . " UomId "
FROM ( SELECT l . " ProductId " , p . " UomId " ,
CASE WHEN p . " TrackingMethod " IN ( ' Lot ' , ' Serial ' ) THEN z . " LotNo " ELSE ' ' END AS " LotNo " ,
public . " 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 " = false AND p . " TrackingMethod " IN ( ' Lot ' , ' Serial ' )
WHERE l . " TransferId " = p_id AND l . " IsDeleted " = false AND l . " Quantity " > 0 AND p . " TrackInventory " = true ) m
GROUP BY m . " ProductId " , m . " LotNo " , m . " UomId " ;
IF v_src_internal THEN
PERFORM 1 FROM " Inv_T_Stock " s
WHERE s . " LocationId " = v_src AND s . " TenantId " IS NOT DISTINCT FROM v_tenant
AND ( s . " ProductId " , s . " LotNo " ) IN ( SELECT " ProductId " , " LotNo " FROM tmp_inv_move )
FOR UPDATE ;
SELECT p . " Name " | | CASE WHEN m . " LotNo " = ' ' THEN ' ' ELSE ' / ' | | m . " LotNo " END INTO v_msg
FROM tmp_inv_move m
INNER JOIN " Inv_T_Product " p ON p . " Id " = m . " ProductId "
LEFT JOIN " Inv_T_Stock " s ON s . " LocationId " = v_src AND s . " ProductId " = m . " ProductId " AND s . " LotNo " = m . " LotNo "
AND s . " TenantId " IS NOT DISTINCT FROM v_tenant
WHERE COALESCE ( s . " Quantity " , 0 ) < m . " Quantity "
LIMIT 1 ;
IF v_msg IS NOT NULL THEN
RAISE EXCEPTION ' Kaynak konumda yeterli stok yok: % ' , v_msg USING ERRCODE = ' P0001 ' , DETAIL = ' 50312 ' ;
END IF ;
2026-10-14 19:26:03 +00:00
-- Kaynak ve hedef aynı ysa stok yerinde kalı r: belge teslimi kaydeder (yeterlilik yine denetlenir).
IF v_src < > v_dst THEN
UPDATE " Inv_T_Stock " s SET " Quantity " = s . " Quantity " - m . " Quantity " , " LastMoveDate " = v_now , " LastModificationTime " = v_now , " LastModifierId " = p_user_id
FROM tmp_inv_move m
WHERE m . " ProductId " = s . " ProductId " AND m . " LotNo " = s . " LotNo " AND s . " LocationId " = v_src AND s . " TenantId " IS NOT DISTINCT FROM v_tenant ;
END IF ;
2026-10-12 21:43:05 +00:00
END IF ;
2026-10-14 19:26:03 +00:00
IF v_dst_internal AND v_src < > v_dst THEN
2026-10-12 21:43:05 +00:00
UPDATE " Inv_T_Stock " s SET " Quantity " = s . " Quantity " + m . " Quantity " , " LastMoveDate " = v_now , " LastModificationTime " = v_now , " LastModifierId " = p_user_id ,
" InDate " = CASE WHEN s . " Quantity " < = 0 THEN v_now ELSE s . " InDate " END
FROM tmp_inv_move m
WHERE m . " ProductId " = s . " ProductId " AND m . " LotNo " = s . " LotNo " AND s . " LocationId " = v_dst AND s . " TenantId " IS NOT DISTINCT FROM v_tenant ;
INSERT INTO " Inv_T_Stock " ( " Id " , " TenantId " , " BranchId " , " WarehouseId " , " LocationId " , " ProductId " , " LotNo " , " Quantity " , " UomId " , " InDate " , " LastMoveDate " , " CreationTime " , " CreatorId " , " IsDeleted " )
SELECT gen_random_uuid ( ) , v_tenant , v_dst_branch , v_dst_warehouse , v_dst , m . " ProductId " , m . " LotNo " , m . " Quantity " , m . " UomId " , v_now , v_now , v_now , p_user_id , false
FROM tmp_inv_move m
WHERE NOT EXISTS ( SELECT 1 FROM " Inv_T_Stock " s
WHERE s . " LocationId " = v_dst AND s . " ProductId " = m . " ProductId " AND s . " LotNo " = m . " LotNo "
AND s . " TenantId " IS NOT DISTINCT FROM v_tenant ) ;
END IF ;
DROP TABLE tmp_inv_move ;
UPDATE " Inv_T_Transfer "
SET " Status " = ' Done ' , " EffectiveDate " = v_now ,
" ReceivedByUserId " = CASE WHEN v_kind = ' InternalTransfer ' THEN p_user_id ELSE " ReceivedByUserId " END ,
" ReceivedDate " = CASE WHEN v_kind = ' InternalTransfer ' THEN v_now ELSE " ReceivedDate " END
WHERE " Id " = p_id ;
UPDATE " Prc_T_PurchaseOrderLine " ol SET " ReceivedQuantity " = ol . " ReceivedQuantity " + v_sign * x . " Quantity "
FROM ( SELECT l . " PurchaseOrderLineId " , SUM ( public . " 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 " = p_id AND l . " IsDeleted " = false AND l . " Quantity " > 0
GROUP BY l . " PurchaseOrderLineId " ) x
WHERE x . " PurchaseOrderLineId " = ol . " Id " ;
2026-10-14 09:07:11 +00:00
CALL public . " Inv_P_TransferSupplierPrice " ( p_id , p_user_id ) ;
2026-10-12 21:43:05 +00:00
UPDATE " Prc_T_MaterialRequestItem " i SET " DeliveredQuantity " = i . " DeliveredQuantity " + v_sign * x . " Quantity " ,
" LineStatus " = CASE WHEN i . " DeliveredQuantity " + v_sign * x . " Quantity " > = i . " Quantity " THEN ' Done '
WHEN i . " LineStatus " = ' Done ' THEN ' Waiting ' ELSE i . " LineStatus " END
FROM ( SELECT l . " MaterialRequestItemId " , SUM ( public . " 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 " = p_id AND l . " IsDeleted " = false AND l . " Quantity " > 0
GROUP BY l . " MaterialRequestItemId " ) x
WHERE x . " MaterialRequestItemId " = i . " Id " ;
IF v_return_of IS NULL AND EXISTS ( SELECT 1 FROM " Inv_T_TransferLine " WHERE " TransferId " = p_id AND " IsDeleted " = false AND " Quantity " < " DemandQuantity " ) THEN
CALL public . " Inv_P_TransferCopy " ( p_id , ' Backorder ' , p_user_id , v_new ) ;
END IF ;
CALL public . " Inv_P_TransferRecalc " ( p_id ) ;
END ;
$ $ ;