CREATE OR REPLACE
  FUNCTION prodqtyreserved
  (
      p_product_id   NUMBER,
      p_warehouse_id NUMBER 
  )
    RETURN NUMBER
  AS
    v_Warehouse_ID NUMBER;
    v_Quantity     NUMBER := 99999; -- unlimited
    v_IsBOM        CHAR(1);
    v_IsStocked    CHAR(1);
    v_ProductType  CHAR(1);
    v_ProductQty   NUMBER;
    v_StdPrecision INT;
  BEGIN
    -- Check Parameters
    v_Warehouse_ID     := p_Warehouse_ID;
    IF (v_Warehouse_ID IS NULL) THEN
      RETURN 0;
    END IF;
    -- DBMS_OUTPUT.PUT_LINE('Warehouse=' || v_Warehouse_ID);
    -- Check, if product exists and if it is stocked
    BEGIN
      SELECT IsBOM,
        ProductType,
        IsStocked
      INTO v_IsBOM,
        v_ProductType,
        v_IsStocked
      FROM M_PRODUCT
      WHERE M_Product_ID=p_Product_ID;
      --
    EXCEPTION -- not found
    WHEN OTHERS THEN
      RETURN 0;
    END;
    -- No reservation for non-stocked
    IF (v_IsStocked='Y') THEN
      -- Get ProductQty
      SELECT -1*COALESCE(SUM(MovementQty), 0)
      INTO v_ProductQty
      FROM M_ProductionLine p
      WHERE M_Product_ID=p_Product_ID
      AND MovementQty   < 0
      AND p.Processed   = 'N'
      AND EXISTS
        (SELECT *
        FROM M_LOCATOR l
        WHERE p.M_Locator_ID=l.M_Locator_ID
        AND l.M_Warehouse_ID=v_Warehouse_ID
        );
      --
      RETURN v_ProductQty;
    END IF;
    -- Unlimited (e.g. only services)
    IF (v_Quantity = 99999) THEN
      RETURN 0;
    END IF;
    IF (v_Quantity > 0) THEN
      -- Get Rounding Precision for Product
      SELECT COALESCE(MAX(u.StdPrecision), 0)
      INTO v_StdPrecision
      FROM C_UOM u,
        M_PRODUCT p
      WHERE u.C_UOM_ID  =p.C_UOM_ID
      AND p.M_Product_ID=p_Product_ID;
      --
      RETURN ROUND (v_Quantity, v_StdPrecision);
    END IF;
    RETURN 0;
  END;
/