\q
--
-- PostgreSQL database dump
--

-- Dumped from database version 15.13
-- Dumped by pg_dump version 15.13

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;

--
-- Name: vgate; Type: SCHEMA; Schema: -; Owner: postgres
--

CREATE SCHEMA vgate;


ALTER SCHEMA vgate OWNER TO postgres;

--
-- Name: application/octet-stream; Type: DOMAIN; Schema: vgate; Owner: postgres
--

CREATE DOMAIN vgate."application/octet-stream" AS bytea;


ALTER DOMAIN vgate."application/octet-stream" OWNER TO postgres;

--
-- Name: cardlink_currency; Type: TYPE; Schema: vgate; Owner: postgres
--

CREATE TYPE vgate.cardlink_currency AS ENUM (
    'USD',
    'RUB',
    'EUR'
);


ALTER TYPE vgate.cardlink_currency OWNER TO postgres;

--
-- Name: cardlink_status; Type: TYPE; Schema: vgate; Owner: postgres
--

CREATE TYPE vgate.cardlink_status AS ENUM (
    'SUCCESS',
    'UNDERPAID',
    'OVERPAID',
    'FAIL'
);


ALTER TYPE vgate.cardlink_status OWNER TO postgres;

--
-- Name: email_address; Type: DOMAIN; Schema: vgate; Owner: postgres
--

CREATE DOMAIN vgate.email_address AS text
	CONSTRAINT email_address_check CHECK ((VALUE ~ '^[^@\s]+@[^@\s]+\.[^@\s]+$'::text));


ALTER DOMAIN vgate.email_address OWNER TO postgres;

--
-- Name: i18n.translation_type; Type: TYPE; Schema: vgate; Owner: postgres
--

CREATE TYPE vgate."i18n.translation_type" AS ENUM (
    'source',
    'auto',
    'manual'
);


ALTER TYPE vgate."i18n.translation_type" OWNER TO postgres;

--
-- Name: TYPE "i18n.translation_type"; Type: COMMENT; Schema: vgate; Owner: postgres
--

COMMENT ON TYPE vgate."i18n.translation_type" IS 'Specifies the origin of a translation:
- source: original text provided directly by the project
- auto: translation generated automatically (e.g., by AI or a translation service)
- manual: translation added or edited by a human (e.g., developer or project contributor)';


--
-- Name: language; Type: TYPE; Schema: vgate; Owner: postgres
--

CREATE TYPE vgate.language AS ENUM (
    'rus',
    'eng'
);


ALTER TYPE vgate.language OWNER TO postgres;

--
-- Name: pally_currency; Type: TYPE; Schema: vgate; Owner: postgres
--

CREATE TYPE vgate.pally_currency AS ENUM (
    'USD',
    'RUB',
    'EUR'
);


ALTER TYPE vgate.pally_currency OWNER TO postgres;

--
-- Name: pally_status; Type: TYPE; Schema: vgate; Owner: postgres
--

CREATE TYPE vgate.pally_status AS ENUM (
    'SUCCESS',
    'UNDERPAID',
    'OVERPAID',
    'FAIL'
);


ALTER TYPE vgate.pally_status OWNER TO postgres;

--
-- Name: promotype; Type: TYPE; Schema: vgate; Owner: postgres
--

CREATE TYPE vgate.promotype AS ENUM (
    'traffic',
    'discount'
);


ALTER TYPE vgate.promotype OWNER TO postgres;

--
-- Name: text/plain; Type: DOMAIN; Schema: vgate; Owner: postgres
--

CREATE DOMAIN vgate."text/plain" AS text;


ALTER DOMAIN vgate."text/plain" OWNER TO postgres;

--
-- Name: aaio_callback(text, uuid, uuid, text, numeric, aaio.currency, double precision, double precision, double precision, text, text, text, text, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.aaio_callback(status text, merchant_id uuid, invoice_id uuid, order_id text, amount numeric, currency aaio.currency, profit double precision, commission double precision, commission_client double precision, commission_type text, sign text, method text, "desc" text, email text) RETURNS text
    LANGUAGE plpgsql SECURITY DEFINER
    AS $_$
DECLARE
    merchant_id UUID = current_setting('app.aaio_merchant')::UUID;
    subuser_id INT;
    result_hash BYTEA;
    signature_verified BOOLEAN;
    response JSON;
BEGIN
    RAISE LOG $log$
      aaio_callback: {
        status: %,
        merchant_id: %,
        invoice_id: %,
        order_id: %,
        amount: %,
        currency: %,
        profit: %,
        commission: %,
        commission_client: %,
        commission_type: %,
        sign: %,
        method: %,
        desc: %,
        email: %
      }
      $log$,
      status,
      merchant_id,
      invoice_id,
      order_id,
      amount,
      currency,
      profit,
      commission,
      commission_client,
      commission_type,
      sign,
      method,
      "desc",
      email;

    result_hash = encode(
        digest(
            format(
                '%s:%s:%s:%s:%s',
                merchant_id,
                amount,
                currency,
                current_setting('app.aaio_secret_2'),
                order_id
            ),
            'sha256'
        ),
        'hex'
    );

    signature_verified = common.secure_hash_equals(sign::BYTEA, result_hash);

    IF NOT signature_verified THEN
        RAISE sqlstate 'PT401' USING
            message = 'Unauthorized';
    END IF;

    IF EXISTS ( 
        SELECT 1 
        FROM legacy.payment p
        WHERE service = 'aaio' AND p.order_id = aaio_callback.order_id 
    ) THEN
        RAISE sqlstate 'PT409' USING
            message = 'Payment already exists';
    END IF;

    subuser_id := (
        SELECT u.sub_id
        FROM legacy.user u
        INNER JOIN legacy.invoice i ON i.user_id = u.user_id
        WHERE i.id = order_id::TEXT AND i.pool::TEXT = u.pool::TEXT
        LIMIT 1
    );

    INSERT INTO legacy.payment
    (
        user_id,
        subuser_id,
        paid,
        order_id,
        amount_gb,
        balance_before,
        discount,
        service,
        date
    ) VALUES (
        (
            SELECT user_id
            FROM legacy.invoice
            WHERE id = order_id
        ),
        subuser_id,
        amount,
        order_id,
        (
            SELECT i.amount
            FROM legacy.invoice i
            WHERE i.id = aaio_callback.order_id
        ),
        CASE WHEN subuser_id IS NULL THEN
            '0 GB'
        ELSE
            (
                SELECT dataimpulse.get_subuser(subuser_id)->>'balance_format'
            )
        END,
        NULL,
        'aaio',
        current_date
    );

    PERFORM process_successful_payment(order_id);

    RETURN 'true';
END
$_$;


ALTER FUNCTION vgate.aaio_callback(status text, merchant_id uuid, invoice_id uuid, order_id text, amount numeric, currency aaio.currency, profit double precision, commission double precision, commission_client double precision, commission_type text, sign text, method text, "desc" text, email text) OWNER TO postgres;

--
-- Name: activate_traffic_promocode(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.activate_traffic_promocode(code text) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
  _current_user TEXT := common.current_user_id();
  used_promo_list TEXT[];
  promo_info RECORD;
  sub_id TEXT;
  is_used BOOLEAN;
  balance_before TEXT;
  source TEXT  := 'web';
BEGIN
  SET role TO postgres;

  SELECT traffic_amount, pool, remaining_activation
  FROM legacy.promocode
  WHERE promo_name = code
  INTO promo_info;

  IF promo_info IS NULL OR promo_info.remaining_activation < 0 THEN
    -- TODO: expires promo?
    RAISE sqlstate 'PT422' USING message = format('promocode %s not exists or expired', code);
  END IF;

  sub_id := legacy.ensure_subuser_exists(promo_info.pool::DATAIMPULSEPOOL, _current_user);

  UPDATE legacy.user
  SET used_promo_list = ''
  WHERE "user".used_promo_list IS NULL;

  SELECT string_to_array(COALESCE("user".used_promo_list, ''), ',')
  FROM legacy.user
  WHERE user_id = _current_user
  INTO used_promo_list;

  SELECT EXISTS (
   SELECT promocode
   FROM unnest(used_promo_list) as promocode
   WHERE promocode = code
  ) INTO is_used;

  IF is_used THEN
    RAISE sqlstate 'PT409' USING message = 'promocode already used by user';
  END IF;

  UPDATE legacy.promocode SET remaining_activation = remaining_activation - 1 WHERE promo_name=code;

  UPDATE legacy."user"
  SET
    used_promo_list = "user".used_promo_list || ',' || code,
    buy_num = buy_num + 1
  WHERE user_id=_current_user;

  SELECT dataimpulse.subuser_balance_get(
      (
        SELECT u.sub_id
        FROM legacy.user AS u
        WHERE u.pool::TEXT = promo_info.pool AND u.user_id = _current_user
      )::INT
  )->'balance_format'
  INTO balance_before;

  RAISE NOTICE 'sub_bal_add: %, %', sub_id, promo_info.traffic_amount;
  PERFORM dataimpulse.subuser_balance_add(sub_id::INT, promo_info.traffic_amount::INT);

  BEGIN
    PERFORM common.send_promo_notification(
      _current_user,
      code,
      promo_info.traffic_amount::INT,
      balance_before,
      source
    );
  EXCEPTION WHEN OTHERS THEN
    RAISE WARNING 'Failed to send notification: %', SQLERRM;
  END;
END $$;


ALTER FUNCTION vgate.activate_traffic_promocode(code text) OWNER TO postgres;

--
-- Name: add_ip_to_whitelist(inet, common.dataimpulsepool); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.add_ip_to_whitelist(ip inet, pool common.dataimpulsepool) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    _current_user TEXT := common.current_user_id();
    sub_id INT;
BEGIN
    IF common.ip_is_local_or_private(ip) THEN
        RAISE sqlstate 'PT406' USING
            message = 'Local and private IP addresses are not allowed';
    END IF;

    SELECT "user".sub_id::INT
    FROM legacy.user
    WHERE user_id = _current_user AND "user".pool = add_ip_to_whitelist.pool
    INTO sub_id;

    IF sub_id IS NULL THEN
        RAISE sqlstate 'PT404' USING
            message = 'No subuser found for this pool type';
    END IF;

    RAISE DEBUG 'sub_id: %, ip: %', sub_id, ip;

    PERFORM dataimpulse.add_allowed_ip(sub_id, ip);
    
    RETURN jsonb_build_object('message', format('IP %s added to whitelist', ip));
EXCEPTION
WHEN sqlstate 'PT406' THEN
    RAISE;
WHEN sqlstate 'PT404' THEN
    RAISE;
WHEN OTHERS THEN
    IF SQLSTATE = 'PT400' AND SQLERRM LIKE '%Bind is already exists for other subuser%' THEN
        RAISE sqlstate 'PT400' USING
            message = 'Bind is already exists for other subuser.';
    ELSE
        RAISE LOG 'Error in add_ip_to_whitelist: % - %', SQLSTATE, SQLERRM;
        RAISE sqlstate 'PT500' USING
            message = 'Internal server error';
    END IF;
END $$;


ALTER FUNCTION vgate.add_ip_to_whitelist(ip inet, pool common.dataimpulsepool) OWNER TO postgres;

--
-- Name: apays_callback(json); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.apays_callback(json) RETURNS json
    LANGUAGE plpgsql SECURITY DEFINER
    AS $_$
DECLARE
    o_id TEXT = $1->>'order_id';
    o_status TEXT = $1->>'status';
    sign TEXT = $1->>'sign';
    signature_verified BOOLEAN;
    subuser_id INT;
    secret_key TEXT = current_setting('app.apays_secret');
BEGIN
    subuser_id := (
        SELECT u.sub_id
        FROM legacy.user u
        INNER JOIN legacy.invoice i ON i.user_id = u.user_id
        WHERE i.id = o_id AND i.pool = u.pool
        LIMIT 1
    );

    RAISE NOTICE 'o_id: %, o_status: %, sign: %', o_id, o_status, sign;

    signature_verified := (
        sign = md5(format('%s:%s:%s', o_id, o_status, secret_key))
    );

    RAISE NOTICE 'signature_verified: %', signature_verified; 
    RAISE NOTICE 'status: %', o_status; 

    IF NOT EXISTS (
        SELECT 1
        FROM legacy.payment p
        WHERE p.order_id = o_id
    ) 
    AND o_status = 'approved'
    AND signature_verified THEN
        INSERT INTO legacy.payment
        (
            user_id,
            subuser_id,
            paid,
            order_id,
            amount_gb,
            balance_before,
            discount,
            service,
            date
        ) VALUES (
            (
                SELECT user_id
                FROM legacy.invoice i
                WHERE i.id = o_id
            ),
            subuser_id,
            (
                SELECT i.price
                FROM legacy.invoice i
                WHERE i.id = o_id
            ),
            (
                SELECT i.id
                FROM legacy.invoice i
                WHERE i.id = o_id
            ),
            (
                SELECT i.amount
                FROM legacy.invoice i
                WHERE i.id = o_id
            ),
            CASE WHEN subuser_id IS NULL THEN
                '0 GB'
            ELSE
                (
                    SELECT dataimpulse.get_subuser(subuser_id)->>'balance_format'
                )
            END,
            NULL,
            'apays',
            current_date
        );
    ELSE
        RAISE sqlstate 'PT401' USING 
            message = 'Unauthorized';
    END IF;

    PERFORM process_successful_payment(o_id);

    RETURN json_build_object('success', true);
END
$_$;


ALTER FUNCTION vgate.apays_callback(json) OWNER TO postgres;

--
-- Name: calculate(integer[]); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.calculate(amounts integer[]) RETURNS double precision[]
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    result FLOAT[];
BEGIN
    SELECT array_agg(
        COALESCE((SELECT MAX(discount) FROM legacy.discount_tier WHERE min_amount <= a), 0.0)
    )
    FROM unnest(amounts) AS a INTO result;

    RETURN result;
END;
$$;


ALTER FUNCTION vgate.calculate(amounts integer[]) OWNER TO postgres;

--
-- Name: calculate(integer); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.calculate(amount integer) RETURNS double precision
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    resutl FLOAT;
BEGIN
    SELECT COALESCE(MAX(discount), 0.0) INTO resutl
    FROM legacy.discount_tier
    WHERE min_amount <= amount;

    RETURN resutl;
END;
$$;


ALTER FUNCTION vgate.calculate(amount integer) OWNER TO postgres;

--
-- Name: calculate_detailed_price(integer, common.dataimpulsepool, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.calculate_detailed_price(amount integer, pool common.dataimpulsepool, promocode text DEFAULT NULL::text) RETURNS common.price_calculation
    LANGUAGE plpgsql
    AS $$
DECLARE
    result common.price_calculation;
BEGIN
    SELECT base_price, pool_price, volume_discount, volume_discount_amount,
           promo_discount, promo_discount_amount, final_price
    INTO result
    FROM common.calculate_detailed_price(amount, pool, promocode);
    RETURN result;
END;
$$;


ALTER FUNCTION vgate.calculate_detailed_price(amount integer, pool common.dataimpulsepool, promocode text) OWNER TO postgres;

--
-- Name: can_edit_article(bigint); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.can_edit_article(article_id bigint) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'vgate', 'public', 'pg_temp'
    AS $$
DECLARE
    current_user_id text;
    article_user_id text;
    current_user_role text;
BEGIN
    -- Get current user ID and role
    current_user_id := common.current_user_id();
    current_user_role := common.current_role();
    
    -- Get article user_id
    SELECT user_id FROM legacy.blog_article WHERE "order" = article_id INTO article_user_id;
    
    -- Check if article exists
    IF NOT FOUND THEN
        RAISE sqlstate 'PT404' USING
            message = 'Article not found';
    END IF;
    
    -- Check if user can edit: either owner or admin
    IF current_user_id = article_user_id THEN
        RETURN jsonb_build_object('can_edit', true);
    ELSE
        RETURN jsonb_build_object('can_edit', false);
    END IF;
    
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE sqlstate 'PT500' USING
            message = 'Unexpected server error';
END;
$$;


ALTER FUNCTION vgate.can_edit_article(article_id bigint) OWNER TO postgres;

--
-- Name: cardlink_callback(text, text, text, text, vgate.cardlink_status, vgate.cardlink_currency, text, text, text, text, text, text, text, text, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.cardlink_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.cardlink_status, "CurrencyIn" vgate.cardlink_currency, "SignatureValue" text, custom text DEFAULT NULL::text, "AccountType" text DEFAULT NULL::text, "AccountNumber" text DEFAULT NULL::text, "AccountBank" text DEFAULT NULL::text, "BalanceAmount" text DEFAULT NULL::text, "BalanceCurrency" text DEFAULT NULL::text, "ErrorCode" text DEFAULT NULL::text, "ErrorMessage" text DEFAULT NULL::text) RETURNS json
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    sign TEXT;
    signature_verified BOOLEAN;
    subuser_id INT;
    api_token TEXT := current_setting('app.cardlink_api_token');
    hash TEXT;
BEGIN
    subuser_id := (
        SELECT u.sub_id
        FROM legacy.user u
        INNER JOIN legacy.invoice i ON i.user_id = u.user_id AND i.pool = u.pool
        WHERE i.id = "InvId"
        LIMIT 1
    );

    hash = md5(
        format('%s:%s:%s', "OutSum", "InvId", api_token)
    );

    signature_verified := (
        "SignatureValue" = upper(hash)
    );

    RAISE NOTICE 'OutSum: %, InvId: %, api_token: %', "OutSum", "InvId", api_token; 
    RAISE NOTICE 'hash: %', hash; 
    RAISE NOTICE 'signature_verified: %', signature_verified; 

    IF NOT EXISTS (
        SELECT 1
        FROM legacy.payment p
        WHERE p.order_id = "InvId"
    ) 
    AND "Status"::TEXT IN ('SUCCESS', 'OVERPAID')
    AND signature_verified THEN
        INSERT INTO legacy.payment
        (
            user_id,
            subuser_id,
            paid,
            order_id,
            amount_gb,
            balance_before,
            discount,
            service,
            date
        ) VALUES (
            (
                SELECT user_id
                FROM legacy.invoice i
                WHERE i.id = "InvId"
            ),
            subuser_id,
            (
                SELECT i.price
                FROM legacy.invoice i
                WHERE i.id = "InvId"
            ),
            (
                SELECT i.id
                FROM legacy.invoice i
                WHERE i.id = "InvId"
            ),
            (
                SELECT i.amount
                FROM legacy.invoice i
                WHERE i.id = "InvId"
            ),
            CASE WHEN subuser_id IS NULL THEN
                '0 GB'
            ELSE
                (
                    SELECT dataimpulse.get_subuser(subuser_id)->>'balance_format'
                )
            END,
            NULL,
            'cardlink',
            current_date
        );
    ELSE
        RAISE sqlstate 'PT401' USING 
            message = 'Unauthorized';
    END IF;

    PERFORM process_successful_payment("InvId");

    RETURN json_build_object('success', true);
END
$$;


ALTER FUNCTION vgate.cardlink_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.cardlink_status, "CurrencyIn" vgate.cardlink_currency, "SignatureValue" text, custom text, "AccountType" text, "AccountNumber" text, "AccountBank" text, "BalanceAmount" text, "BalanceCurrency" text, "ErrorCode" text, "ErrorMessage" text) OWNER TO postgres;

--
-- Name: change_account_password(text, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.change_account_password(old_password text, new_password text) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
  sub_user_info JSONB;
  _scram_hash TEXT;
  _role TEXT;
  has_password BOOLEAN;
  _current_user TEXT;
  _user_id TEXT;
BEGIN
  _current_user := common.current_user_id();

  SET role TO postgres;

  SELECT EXISTS (
    SELECT 1
    FROM legacy.all_user
    WHERE user_id = _current_user
    AND password IS NOT NULL
  )
  INTO has_password;

  IF has_password THEN
    SELECT basic_auth.check_user_pass(_current_user, old_password) INTO _user_id;
    IF _user_id IS NULL THEN
      RAISE invalid_password USING message = 'invalid user or password';
    END IF;
  END IF;

  _scram_hash := common.generate_scram_hash(new_password);

  -- new realization
  UPDATE legacy.all_user SET password = _scram_hash WHERE all_user.user_id = _current_user;
END
$$;


ALTER FUNCTION vgate.change_account_password(old_password text, new_password text) OWNER TO postgres;

--
-- Name: change_language(vgate.language); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.change_language(code vgate.language) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
  _current_user TEXT := common.current_user_id();
BEGIN
  SET role TO postgres;
  UPDATE legacy.all_user SET lang = code::TEXT
  WHERE user_id = _current_user;
END $$;


ALTER FUNCTION vgate.change_language(code vgate.language) OWNER TO postgres;

--
-- Name: check_headers(); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.check_headers() RETURNS json
    LANGUAGE plpgsql
    AS $$
BEGIN
    RETURN current_setting('request.headers', true)::json;
END
$$;


ALTER FUNCTION vgate.check_headers() OWNER TO postgres;

--
-- Name: check_headers(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.check_headers(title text) RETURNS vgate."text/plain"
    LANGUAGE plpgsql
    AS $$
BEGIN
    RETURN common.get_header("title")::text;
END
$$;


ALTER FUNCTION vgate.check_headers(title text) OWNER TO postgres;

--
-- Name: check_tg_user_exists(bigint); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.check_tg_user_exists(tg_id bigint) RETURNS boolean
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
    RETURN EXISTS (
        SELECT 1 
        FROM legacy.all_user 
        WHERE user_id = tg_id::TEXT
    );
END;
$$;


ALTER FUNCTION vgate.check_tg_user_exists(tg_id bigint) OWNER TO postgres;

--
-- Name: check_user_exists(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.check_user_exists(user_id text) RETURNS boolean
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
    RETURN EXISTS (
        SELECT 1 
        FROM legacy.all_user 
        WHERE legacy.all_user.user_id = check_user_exists.user_id
    );
END;
$$;


ALTER FUNCTION vgate.check_user_exists(user_id text) OWNER TO postgres;

--
-- Name: check_user_role(uuid, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.check_user_role(user_id uuid, role text) RETURNS boolean
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
    RETURN EXISTS (
        SELECT 1
        FROM "user" u
        WHERE u.id = user_id
          AND u.rolname = role
    );
END;
$$;


ALTER FUNCTION vgate.check_user_role(user_id uuid, role text) OWNER TO postgres;

--
-- Name: confirm_email(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.confirm_email(confirmation_token text) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    confirmation RECORD;
BEGIN
    SELECT token, user_id, exp, used
      INTO confirmation
      FROM public.confirmation_inner
     WHERE token = confirmation_token
       AND used = false;
       
    IF NOT FOUND THEN
      RAISE EXCEPTION 'Invalid or already used confirmation token';
    END IF;
    
    IF confirmation.exp < now() THEN
      RAISE EXCEPTION 'Confirmation token expired';
    END IF;
    
    UPDATE legacy.all_user
       SET confirmed = 1
     WHERE user_id = confirmation.user_id;
    IF NOT FOUND THEN
      RAISE EXCEPTION 'User not found';
    END IF;
    
    UPDATE public.confirmation_inner
       SET used = true
     WHERE token = confirmation_token;
END;
$$;


ALTER FUNCTION vgate.confirm_email(confirmation_token text) OWNER TO postgres;

--
-- Name: create_apays_invoice(integer); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.create_apays_invoice(amount integer) RETURNS json
    LANGUAGE plpgsql
    AS $$
DECLARE
    order_id UUID = uuid_generate_v4();
    form_data TEXT = '';
    sign TEXT;
    response_status INT;
    response JSON;
BEGIN
    sign := md5(order_id::TEXT || ':' || amount::TEXT || ':' || '6c375258-ae9f-4ad5-bd8f-0324f550cb33');
    form_data := form_data || 'client_id=481';
    form_data := form_data || '&order_id=' || order_id::TEXT;
    form_data := form_data || '&amount=' || amount::TEXT;
    form_data := form_data || '&sign=' || sign;

    SELECT status, content::JSON
    FROM http(
        (
            'GET',
            'https://apays.io/backend/create_order?' || form_data,
            NULL,
            NULL,
            NULL
        )::http_request
    ) INTO response_status, response;

    IF (response_status != 200) OR (response->>'status' != 'true') THEN
        RAISE sqlstate 'PT500' USING message = 'failed to create order: ' || response;
    ELSE
        RETURN json_build_object(
            'amount', amount,
            'order_id', order_id,
            'url', response->>'url'
        );
    END IF;
END
$$;


ALTER FUNCTION vgate.create_apays_invoice(amount integer) OWNER TO postgres;

--
-- Name: create_blog_article(text, text, vgate.language, boolean); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.create_blog_article(title text, content text, language vgate.language, hidden boolean DEFAULT false) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    current_user_id text;
    article_id bigint;
    result jsonb;
BEGIN
    current_user_id := common.current_user_id();
    
    IF title IS NULL OR trim(title) = '' THEN
        RAISE sqlstate 'PT400' USING
            message = 'Title is required';
    END IF;
    
    IF content IS NULL OR trim(content) = '' THEN
        RAISE sqlstate 'PT400' USING
            message = 'Content is required';
    END IF;
    
    INSERT INTO legacy.blog_article (title, content, user_id, language)
    VALUES (trim(title), trim(content), current_user_id, language)
    RETURNING "id" INTO article_id;
    
    RETURN jsonb_build_object('id', article_id);
EXCEPTION
    WHEN sqlstate 'PT400' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE warning 'Error creating blog article: %', SQLERRM;
        RAISE sqlstate 'PT500' USING
            message = 'Unexpected server error';
END;
$$;


ALTER FUNCTION vgate.create_blog_article(title text, content text, language vgate.language, hidden boolean) OWNER TO postgres;

--
-- Name: create_invoice(text, integer, text, common.dataimpulsepool); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.create_invoice(payment text, amount integer, promocode text, pool common.dataimpulsepool) RETURNS text
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
  gb_cost_usd NUMERIC;
  price NUMERIC;
  is_exists BOOLEAN;
  invoice_model JSONB;
BEGIN
  SELECT EXISTS (
    SELECT name 
    FROM available_pay 
    WHERE name = payment
      AND is_available = 'true'
  ) INTO is_exists; 

  IF NOT is_exists THEN
    RAISE sqlstate 'PT409' USING message = 'payment method not available';
  END IF;

  SELECT gb_cost_usd 
  FROM legacy.price 
  WHERE price.pool = create_invoice.pool 
  INTO gb_cost_usd;

  price := gb_cost_usd * amount;

  price := common.apply_discounts(price, amount, promocode);

  CASE payment
    WHEN 'aaio' THEN
      SELECT create_aaio_invoice_legacy_tg(amount, pool, lang) INTO invoice_model;
    WHEN 'crystalpay' THEN
      -- code for crystalpay
    WHEN 'criptomus' THEN
      -- code for criptomus
  END CASE;

  RETURN invoice_model;
END $$;


ALTER FUNCTION vgate.create_invoice(payment text, amount integer, promocode text, pool common.dataimpulsepool) OWNER TO postgres;

--
-- Name: create_invoice_web(text, integer, common.dataimpulsepool, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.create_invoice_web(payment_method text, amount integer, pool common.dataimpulsepool, promocode text DEFAULT NULL::text) RETURNS vgate."text/plain"
    LANGUAGE plpgsql
    AS $$
DECLARE
    price_calc common.price_calculation;
    _current_user TEXT := common.current_user_id_with_ok(false);
    order_id TEXT;
    invoice_url TEXT;
    source TEXT := 'web';
BEGIN

    IF common.is_provider() THEN
      source := 'bot';
    END IF;

    SET ROLE TO postgres;

    IF NOT EXISTS (
        SELECT name
        FROM legacy.available_pay
        WHERE name = payment_method
            AND is_available = 'true'
            OR name = 'telegram_stars' -- TODO: REMOVE IT V PISDU, THIS IS ONLY FOR TESTING
    ) THEN
        RAISE sqlstate 'PT409' USING message = 'payment method not available';
    END IF;

    price_calc := common.calculate_detailed_price(amount, pool, promocode);

    CASE payment_method
        WHEN 'aaio' THEN
            order_id := uuid_generate_v4()::TEXT;
            SELECT aaio.create_invoice(
                price_calc.final_price,
                'USD'::aaio.currency,
                order_id::UUID
            )->>'url'
            INTO invoice_url;

        WHEN 'crystal' THEN
            SELECT result.url, id
            FROM json_to_record(
                crystalpay.create_invoice(
                    price_calc.final_price,
                    lifetime := 15,
                    callback_url := format(
                        '%s/rpc/crystalpay_callback',
                        common.get_setting('app.api_url')
                    ),
                    amount_currency := 'USD'
                )
            ) AS result(url TEXT, id TEXT)
            INTO invoice_url, order_id;

        WHEN 'apays' THEN
            SELECT result.order_id, result.url
            FROM json_to_record(
                create_apays_invoice(usd_to_kop(price_calc.final_price))
            ) AS result(amount NUMERIC, order_id TEXT, url TEXT)
            INTO order_id, invoice_url;

        WHEN 'cryptomus' THEN
            order_id := uuid_generate_v4()::TEXT;

            SELECT result.url, result.order_id
            FROM json_to_record(
                cryptomus.create_invoice(
                    price_calc.final_price,
                    'USD',
                    order_id::UUID,
                    url_callback := format(
                        '%s/rpc/cryptomus_callback',
                        common.get_setting('app.api_url')
                    )
                )->'result'
            ) AS result(url TEXT, order_id TEXT)
            INTO invoice_url, order_id;

        WHEN 'heleket' THEN
            order_id := uuid_generate_v4()::TEXT;

            SELECT result.url
            FROM json_to_record(
                heleket.create_invoice(
                    price_calc.final_price,
                    'USD',
                    order_id::UUID,
                    url_callback := format(
                        '%s/rpc/heleket_callback',
                        common.get_setting('app.api_url')
                    )
                )->'result'
            ) AS result(url TEXT)
            INTO invoice_url;

        WHEN 'cardlink' THEN
            order_id := uuid_generate_v4()::TEXT;

            SELECT result.link_page_url
            FROM json_to_record(
                cardlink.create_invoice(
                    price_calc.final_price * current_setting('app.ruble_to_dollar_exchange_rate')::NUMERIC,
                    order_id,
                    'RUB'
                )
            ) AS result(link_page_url TEXT)
            INTO invoice_url;
        WHEN 'pally' THEN
            order_id := uuid_generate_v4()::TEXT;

            SELECT result.link_page_url
            FROM json_to_record(
                pally.create_invoice(
                    price_calc.final_price * current_setting('app.ruble_to_dollar_exchange_rate')::NUMERIC,
                    order_id,
                    'RUB'
                )
            ) AS result(link_page_url TEXT)
            INTO invoice_url;
        WHEN 'freekassa' THEN
            order_id := uuid_generate_v4()::TEXT;

            SELECT "result"."invoice_url"
            FROM json_to_record(
                freekassa.create_invoice(
                    price_calc.final_price,
                    'USD',
                    "order_id"
                )
            ) AS "result" ("invoice_url" TEXT)
            INTO invoice_url;
        WHEN 'telegram_stars' THEN
            order_id := uuid_generate_v4()::TEXT;

            -- For Telegram Stars, we return a special JSON response instead of URL
            -- The bot will handle the actual invoice creation via Telegram Bot API
            SELECT jsonb_build_object(
                'amount_gb', amount,
                'pool_type', pool,
                'type', 'telegram_stars',
                'order_id', order_id,
                'amount_usd', price_calc.final_price,
                'stars_amount', telegram_stars.convert_usd_to_stars(price_calc.final_price),
                'exchange_rate', telegram_stars.get_exchange_rate(),
                'description', format('Proxy traffic: %s GB %s', amount, pool::TEXT),
                'currency', 'XTR'
            )::TEXT
            INTO invoice_url;
        ELSE
            RAISE sqlstate 'PT408' USING
                message := 'No such payment_system';
    END CASE;

    IF promocode IS NOT NULL THEN
      PERFORM record_promo_activation(_current_user, promocode, 'discount'::PROMOTYPE);
    END IF;

    INSERT INTO legacy.invoice (
        id,
        payment_system,
        amount,
        price,
        user_id,
        pool,
        source
    )
    VALUES (
        order_id,
        payment_method,
        amount,
        price_calc.final_price,
        _current_user,
        pool,
        source
    );

    BEGIN
    PERFORM set_config(
      'response.headers',
      jsonb_build_array(
        jsonb_build_object(
          'x-invoice-id', format('%s', "order_id")
        )
      )::TEXT,
      true
    );
    EXCEPTION WHEN OTHERS THEN
      RAISE WARNING 'Ye shit broke mate (x-invoice-id)';
    END;

    RETURN invoice_url;
END $$;


ALTER FUNCTION vgate.create_invoice_web(payment_method text, amount integer, pool common.dataimpulsepool, promocode text) OWNER TO postgres;

--
-- Name: create_referral_withdraw_request(numeric, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.create_referral_withdraw_request(amount numeric, comment text DEFAULT ''::text) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $_$
DECLARE
    _current_user TEXT;
    _current_balance NUMERIC;
    _min_withdraw_amount NUMERIC := common.get_setting('min_withdraw_amount')::NUMERIC; -- Minimum withdraw amount in USD
    _request_id BIGINT;
    _status withdraw_request_status;
BEGIN
    _current_user := common.current_user_id();

    -- Validate withdrawal amount
    IF amount <= 0 THEN
        RAISE sqlstate 'PT400' USING message = 'Withdrawal amount must be greater than 0';
    END IF;

    IF amount < _min_withdraw_amount THEN
        RAISE sqlstate 'PT400' USING message = format('Minimum withdrawal amount is $%s', to_char(_min_withdraw_amount, 'FM999999.00'));
    END IF;

    -- Get current referral balance
    SELECT COALESCE(ref_balance_usd, 0)
    FROM legacy.all_user
    WHERE user_id = _current_user
    INTO _current_balance;

    -- Check if user has sufficient balance
    IF _current_balance < amount THEN
        RAISE sqlstate 'PT409' USING message = format('Insufficient referral balance. Available: $%s, Requested: $%s', to_char(_current_balance, 'FM999999.00'), to_char(amount, 'FM999999.00'));
    END IF;

    -- Convert amount to kopecks for storage (amount * 100)
    -- Since legacy.request.amount is bigint, we store cents/kopecks
    INSERT INTO legacy.request (
        user_id,
        amount,
        comment
    )
    VALUES (
        _current_user,
        (amount * 100)::bigint, -- Convert to cents
        COALESCE(comment, format('Referral withdrawal request for $%s', to_char(amount, 'FM999999.00')))
    )
    RETURNING id, status INTO _request_id, _status;

    RAISE LOG 'Referral withdraw request created: user_id=%, amount=$%, request_id=%, status=%', _current_user, to_char(amount, 'FM999999.00'), to_char(_request_id, 'FM999999.00'), _status;

    BEGIN
        PERFORM common.send_telegram_message(
            common.admins(),
            (common.indoc($html$
                    <b>Новый запрос на вывод средств</b>
                    <b>ID запроса: %s</b>
                $html$::TEXT),
                ARRAY[
                    _request_id::TEXT
                ]::TEXT[]
            )::common.format_promise
        );
    EXCEPTION WHEN OTHERS THEN
        RAISE WARNING 'Failed to send referral withdraw request notification: %', SQLERRM;
    END;

    RETURN jsonb_build_object(
        'success', true,
        'message', 'Withdrawal request created successfully',
        'request_id', _request_id,
        'amount', amount,
        'status', _status
    );

EXCEPTION
    WHEN OTHERS THEN
        RAISE LOG 'Error in create_referral_withdraw_request: % - %', SQLSTATE, SQLERRM;
        RAISE;
END $_$;


ALTER FUNCTION vgate.create_referral_withdraw_request(amount numeric, comment text) OWNER TO postgres;

--
-- Name: create_subuser(text, common.dataimpulsepool, jsonb, integer, inet[], jsonb); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.create_subuser(token text, pool_type common.dataimpulsepool DEFAULT 'residential'::common.dataimpulsepool, sticky_range jsonb DEFAULT NULL::jsonb, threads integer DEFAULT NULL::integer, allowed_ips inet[] DEFAULT NULL::inet[], default_pool_parameters jsonb DEFAULT NULL::jsonb) RETURNS integer
    LANGUAGE plpgsql
    AS $$
DECLARE
    reseller_id INT;
    subuser_id INT;
BEGIN
    reseller_id := (SELECT id FROM resellers WHERE api_key = token);

    IF reseller_id IS NULL THEN
        RAISE sqlstate 'PT401' USING
            message = 'Unauthorized';
    END IF;

    SELECT (dataimpulse.create_subuser(
        'r_' || reseller_id,
        sticky_range,
        threads,
        allowed_ips,
        pool_type,
        default_pool_parameters
    ))->>'id'
    INTO subuser_id;

    IF subuser_id IS NULL THEN
        RAISE sqlstate 'PT503' USING
            message = 'Failed to create subuser';
    ELSE
        INSERT INTO reseller_subusers (id, reseller_id)
        VALUES (subuser_id, reseller_id);
        RETURN subuser_id;
    END IF;
END
$$;


ALTER FUNCTION vgate.create_subuser(token text, pool_type common.dataimpulsepool, sticky_range jsonb, threads integer, allowed_ips inet[], default_pool_parameters jsonb) OWNER TO postgres;

--
-- Name: create_tgcode(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.create_tgcode(user_id text DEFAULT common.current_user_id()) RETURNS integer
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    _user_id TEXT := common.get_header('X-Tg-Id');
    new_tgcode INTEGER;
    expires_at BIGINT;
BEGIN
    IF common.is_provider() THEN

       -- Generate random 6-digit code
       new_tgcode := floor(random() * 900000 + 100000)::INTEGER;
       
       -- Set expiration to 5 minutes from now (300 seconds)
       expires_at := EXTRACT(EPOCH FROM NOW()) + 300;
       
       -- Update user with new tgcode
       UPDATE legacy.all_user 
       SET tgcode = new_tgcode::TEXT, 
           tgcode_expires = expires_at::TEXT 
       WHERE all_user.user_id = _user_id;
       
       -- Return the generated code
       RETURN new_tgcode;
    ELSE
        RAISE EXCEPTION 'You are not a provider';
    END IF;
END;
$$;


ALTER FUNCTION vgate.create_tgcode(user_id text) OWNER TO postgres;

--
-- Name: cryptomus_callback(json); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.cryptomus_callback(json) RETURNS text
    LANGUAGE plpgsql SECURITY DEFINER
    AS $_$
DECLARE
    data JSON := $1;
    merchant_id TEXT := current_setting('app.cryptomus_merchant');
    api_key TEXT := current_setting('app.cryptomus_api_key');
    sign TEXT;
    sign_base64 TEXT;
    hash TEXT;
    o_id TEXT;
    signature_verified BOOLEAN;
    subuser_id INT;
BEGIN
    sign = data->>'sign';

    SELECT json_object_agg(key, value)
    FROM json_each(data)
    WHERE key != 'sign'
    INTO data;

    data = REPLACE(data::TEXT, ' ', '')::JSON;

    RAISE NOTICE 'data: %', data;

    sign_base64 = encode(
        data::TEXT::BYTEA,
        'base64'
    );

    hash = md5(
        REPLACE(
            sign_base64,
            E'\n',
            ''
        ) || api_key
    );

    signature_verified = common.secure_hash_equals(sign::BYTEA, hash::BYTEA);

    IF NOT signature_verified THEN
        RAISE sqlstate 'PT401' USING
            message = 'Unauthorized';
    END IF;

    o_id := data->>'order_id';

    IF EXISTS ( 
        SELECT 1 
        FROM legacy.payment p
        WHERE p.order_id = o_id
    ) THEN
        RAISE sqlstate 'PT409' USING
            message = 'Payment already exists';
    END IF;

    IF NOT EXISTS (
        SELECT 1
        FROM legacy.invoice i
        WHERE i.id = o_id
    ) THEN
        RAISE sqlstate 'PT404' USING
            message = 'Invoice not found';
    END IF;

    subuser_id := (
        SELECT u.sub_id
        FROM legacy.user u
        INNER JOIN legacy.invoice i ON i.user_id = u.user_id
        WHERE i.id = o_id AND i.pool::TEXT = u.pool::TEXT
        LIMIT 1
    );

    INSERT INTO legacy.payment
    (
        user_id,
        subuser_id,
        paid,
        order_id,
        amount_gb,
        balance_before,
        discount,
        service,
        date
    ) VALUES (
        (
            SELECT user_id
            FROM legacy.invoice i
            WHERE i.id = o_id
        ),
        subuser_id,
        (
            SELECT i.price
            FROM legacy.invoice i
            WHERE i.id = o_id
        ),
        (
            SELECT i.id
            FROM legacy.invoice i
            WHERE i.id = o_id
        ),
        (
            SELECT i.amount
            FROM legacy.invoice i
            WHERE i.id = o_id
        ),
        CASE WHEN subuser_id IS NULL THEN
            '0 GB'
        ELSE
            (
                SELECT dataimpulse.get_subuser(subuser_id)->>'balance_format'
            )
        END,
        NULL,
        'cryptomus',
        current_date
    );

    PERFORM process_successful_payment(o_id);

    RETURN 'true';
END
$_$;


ALTER FUNCTION vgate.cryptomus_callback(json) OWNER TO postgres;

--
-- Name: crystalpay_callback(text, text, text, text, text, text, text, text, text, text, text, text, text, text, text, text, text, date, date, date); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.crystalpay_callback(id text, signature text, url text, state text, type text, method text, required_method text, amount_currency text, rub_amount text, initial_amount text, remaining_amount text, balance_amount text, commission_amount text, description text, redirect_url text, callback_url text, extra text, created_at date, expired_at date, final_at date) RETURNS text
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    payment_signature BYTEA;
    result_hash BYTEA;
    signature_verified BOOLEAN;
    subuser_id INT;
    crystalpay_salt TEXT := (SELECT current_setting('app.crystalpay_salt'));
BEGIN
    --TODO: make request to tg_bot to notify user about payment

    result_hash := digest(id || ':' || crystalpay_salt, 'sha1');

    payment_signature := ('\x' || signature)::BYTEA;

    RAISE NOTICE 'callback_signature: %', signature;
    RAISE NOTICE 'callback_signature 2: %', payment_signature;

    signature_verified := common.secure_hash_equals(result_hash, payment_signature);

    RAISE NOTICE 'result_hash: %', result_hash;
    RAISE NOTICE 'equality: %', signature_verified;

    subuser_id := (
        SELECT u.sub_id
        FROM legacy.user u
        INNER JOIN legacy.invoice i ON i.user_id = u.user_id
        WHERE i.id = crystalpay_callback.id AND i.pool::TEXT = u.pool::TEXT
        LIMIT 1
    );

    IF NOT EXISTS (
        SELECT 1
        FROM legacy.payment p
        WHERE p.order_id = crystalpay_callback.id
    ) 
    AND state = 'payed'
    AND signature_verified THEN
        INSERT INTO legacy.payment
        (
            user_id,
            subuser_id,
            paid,
            order_id,
            amount_gb,
            balance_before,
            discount,
            service,
            date
        ) VALUES (
            (
                SELECT user_id
                FROM legacy.invoice i
                WHERE i.id = crystalpay_callback.id
            ),
            subuser_id,
            (
                SELECT i.price
                FROM legacy.invoice i
                WHERE i.id = crystalpay_callback.id
            ),
            (
                SELECT i.id
                FROM legacy.invoice i
                WHERE i.id = crystalpay_callback.id
            ),
            (
                SELECT i.amount
                FROM legacy.invoice i
                WHERE i.id = crystalpay_callback.id
            ),
            CASE WHEN subuser_id IS NULL THEN
                '0 GB'
            ELSE
                (
                    SELECT dataimpulse.get_subuser(subuser_id)->>'balance_format'
                )
            END,
            NULL,
            'crystal',
            current_date
        );
    ELSE
        RAISE EXCEPTION 'Invalid signature';
    END IF;

    PERFORM process_successful_payment(id);

    RETURN 'true';
END
$$;


ALTER FUNCTION vgate.crystalpay_callback(id text, signature text, url text, state text, type text, method text, required_method text, amount_currency text, rub_amount text, initial_amount text, remaining_amount text, balance_amount text, commission_amount text, description text, redirect_url text, callback_url text, extra text, created_at date, expired_at date, final_at date) OWNER TO postgres;

--
-- Name: daily_statistics(timestamp with time zone, timestamp with time zone); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.daily_statistics(from_date timestamp with time zone DEFAULT NULL::timestamp with time zone, to_date timestamp with time zone DEFAULT NULL::timestamp with time zone) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    new_users_day INT;
    new_users_week INT;
    new_users_month INT;
    web_users_total INT;
    promo_gb INT;
    result JSONB = '{}';
    report_start TIMESTAMP with time zone;
    report_end TIMESTAMP with time zone;
    promo_gb_count INT;
    discount_promo_usage INT;
BEGIN
    IF from_date IS NULL AND to_date IS NULL THEN
        report_end := now();
        report_start := date_trunc('day', report_end);
    ELSE
        report_start := COALESCE(from_date, now() - interval '24 hours');
        report_end := COALESCE(to_date, now());
    END IF;

    RAISE NOTICE 'from_date: %, to_date: %', from_date, to_date;
    RAISE NOTICE 'report_start: %, report_end: %', report_start, report_end;

    SELECT COALESCE(jsonb_object_agg(
        format('%s_%s', pool, source),
        jsonb_build_object(
            'gb',    COALESCE(gb,    0),
            'sum',   COALESCE(sum,   0),
            'count', COALESCE(count, 0)
        )
    ), '{}'::jsonb)
    FROM (
        SELECT
	  i.pool            as pool,
	  SUM(p.amount_gb)  as gb,
	  i.source          as source,
	  SUM(p.paid)       as sum,
	  COUNT(p)          as count
        FROM legacy.payment p
	INNER JOIN legacy.invoice i ON i.id = p.order_id
        WHERE
	  p.created_at >= report_start
	  AND p.created_at <= report_end
        GROUP BY
	  i.pool,
	  i.source
    ) AS pool_counts
    INTO result;

    SELECT COUNT(au)
    FROM legacy.all_user au
    WHERE au.created_at >= report_start AND au.created_at <= report_end
    INTO new_users_day;

    SELECT COUNT(au)
    FROM legacy.all_user au
    WHERE now() - au.created_at <= interval '1 week'
    INTO new_users_week;

    SELECT COUNT(au)
    FROM legacy.all_user au
    WHERE now() - au.created_at <= interval '1 month'
    INTO new_users_month;

    SELECT COUNT(au)
    FROM legacy.all_user au
    WHERE NOT common.is_numeric(au.user_id::text)
    INTO web_users_total;

    SELECT SUM(gb_amount), COUNT(cross_promo_activations)
    FROM legacy.cross_promo_activations
    WHERE created_at >= report_start AND created_at <= report_end
    INTO promo_gb, promo_gb_count;

    SELECT COUNT(p)
    FROM legacy.payment p
    WHERE p.created_at >= report_start AND p.created_at <= report_end
    AND p.discount != '0'
    INTO discount_promo_usage;

    result = result || jsonb_build_object(
        'web_users_total', COALESCE(web_users_total, 0),
        'new_users_day', COALESCE(new_users_day, 0),
        'new_users_week', COALESCE(new_users_week, 0),
        'new_users_month', COALESCE(new_users_month, 0),
        'promo', jsonb_build_object(
            'traffic', jsonb_build_object(
                'gb', COALESCE(promo_gb, 0),
                'count', COALESCE(promo_gb_count, 0)
            ),
            'discount', jsonb_build_object(
                'count', COALESCE(discount_promo_usage, 0)
            )
        )
    );

    RETURN result;
END
$$;


ALTER FUNCTION vgate.daily_statistics(from_date timestamp with time zone, to_date timestamp with time zone) OWNER TO postgres;

--
-- Name: delete_blog_article(bigint); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.delete_blog_article(article_id bigint) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    current_user_id text;
    deleted_rows integer;
BEGIN
    -- Get current user ID
    current_user_id := common.current_user_id();
    
    -- Delete article
    DELETE FROM legacy.blog_article
    WHERE id = article_id AND user_id = current_user_id;
    
    GET DIAGNOSTICS deleted_rows = ROW_COUNT;
    
    -- Check if article was deleted
    IF deleted_rows = 0 THEN
        RAISE sqlstate 'PT404' USING
            message = 'Article not found';
    END IF;
    
    -- Return success
    RETURN;
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN sqlstate 'PT401' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE sqlstate 'PT500' USING
            message = 'Unexpected server error';
END;
$$;


ALTER FUNCTION vgate.delete_blog_article(article_id bigint) OWNER TO postgres;

--
-- Name: delete_subuser(text, integer); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.delete_subuser(token text, subuser_id integer) RETURNS json
    LANGUAGE plpgsql
    AS $$
DECLARE
    r_id INT;
BEGIN
    r_id := (SELECT id FROM resellers WHERE api_key = token);

    IF r_id IS NULL THEN
        RAISE sqlstate 'PT401' USING
            message = 'Unauthorized';
    END IF;

    IF NOT EXISTS (
            SELECT 1 
            FROM reseller_subusers
            WHERE id = subuser_id AND reseller_id = r_id
        ) THEN
        RAISE sqlstate 'PT404' USING
            message = 'Subuser not found',
            detail = 'No subuser associated with the provided id';
    END IF;

    RETURN dataimpulse.delete_subuser(
        subuser_id
    );
END
$$;


ALTER FUNCTION vgate.delete_subuser(token text, subuser_id integer) OWNER TO postgres;

--
-- Name: discount_promocode_info(text, integer); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.discount_promocode_info(code text, amount integer) RETURNS jsonb
    LANGUAGE plpgsql
    AS $$
DECLARE
  _current_user TEXT := common.current_user_id();
  promo_info RECORD;
BEGIN
  SET role TO postgres;

  SELECT discount FROM legacy.disc_promocode WHERE name = code INTO promo_info;

  IF promo_info IS NULL 
    OR NOT common.is_available_discount_promocode(code, amount, _current_user)  THEN
    RAISE sqlstate 'PT422' USING message = 'promocode does not exist or expired';
  END IF;

  RETURN row_to_json(promo_info);
END $$;


ALTER FUNCTION vgate.discount_promocode_info(code text, amount integer) OWNER TO postgres;

--
-- Name: enforce_role_sync(); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.enforce_role_sync() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = NEW.rolname) THEN
    RAISE EXCEPTION 'Role does not exist: %', NEW.rolname;
  END IF;

  RETURN NEW;
END;
$$;


ALTER FUNCTION vgate.enforce_role_sync() OWNER TO postgres;

--
-- Name: enum(regtype); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.enum(t regtype) RETURNS text[]
    LANGUAGE sql STABLE
    AS $$
  SELECT array_agg(e.enumlabel ORDER BY e.enumsortorder)
  FROM pg_enum e
  WHERE e.enumtypid = t::oid
$$;


ALTER FUNCTION vgate.enum(t regtype) OWNER TO postgres;

--
-- Name: freekassa_callback(integer, numeric, integer, text, text, text, integer, text, numeric, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.freekassa_callback("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text DEFAULT NULL::text) RETURNS text
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    "result_hash" TEXT;
    "signature_verified" BOOLEAN;
    "secret_2" TEXT := current_setting('app.freekassa_secret_2');
    "subuser_id" INT;
BEGIN
    RAISE NOTICE 'freekassa callback: %', json_build_object(
        'MERCHANT_ID', "MERCHANT_ID",
        'AMOUNT', "AMOUNT",
        'intid', "intid",
        'MERCHANT_ORDER_ID', "MERCHANT_ORDER_ID",
        'P_EMAIL', "P_EMAIL",
        'P_PHONE', "P_PHONE",
        'CUR_ID', "CUR_ID",
        'SIGN', "SIGN",
        'payer_account', "payer_account",
        'commission', "commission"
    );

    "result_hash" := md5(
        format(
            '%s:%s:%s:%s',
            "MERCHANT_ID",
            "AMOUNT",
            "secret_2",
            "MERCHANT_ORDER_ID"
        )
    );

    "signature_verified" := "common"."secure_hash_equals"(
        "SIGN"::BYTEA,
        "result_hash"::BYTEA
    );

    IF NOT "signature_verified" THEN
        RAISE sqlstate 'PT401' USING
            message = 'Unauthorized';
    END IF;

    PERFORM http_post(
        'https://vproxy.cc/api/rpc/freekassa_callback_inner',
        jsonb_build_object(
            'MERCHANT_ID', "MERCHANT_ID",
            'AMOUNT', "AMOUNT",
            'intid', "intid",
            'MERCHANT_ORDER_ID', "MERCHANT_ORDER_ID",
            'P_EMAIL', "P_EMAIL",
            'P_PHONE', "P_PHONE",
            'CUR_ID', "CUR_ID",
            'SIGN', "SIGN",
            'payer_account', "payer_account",
            'commission', "commission"
        )
    );

    RETURN 'YES';
END
$$;


ALTER FUNCTION vgate.freekassa_callback("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text) OWNER TO postgres;

--
-- Name: freekassa_callback_inner(integer, numeric, integer, text, text, text, integer, text, numeric, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.freekassa_callback_inner("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text DEFAULT NULL::text) RETURNS text
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    "result_hash" TEXT;
    "signature_verified" BOOLEAN;
    "secret_2" TEXT := current_setting('app.freekassa_secret_2');
    "subuser_id" INT;
BEGIN
    RAISE NOTICE 'freekassa callback: %', json_build_object(
        'MERCHANT_ID', "MERCHANT_ID",
        'AMOUNT', "AMOUNT",
        'intid', "intid",
        'MERCHANT_ORDER_ID', "MERCHANT_ORDER_ID",
        'P_EMAIL', "P_EMAIL",
        'P_PHONE', "P_PHONE",
        'CUR_ID', "CUR_ID",
        'SIGN', "SIGN",
        'payer_account', "payer_account",
        'commission', "commission"
    );

    "result_hash" := md5(
        format(
            '%s:%s:%s:%s',
            "MERCHANT_ID",
            "AMOUNT",
            "secret_2",
            "MERCHANT_ORDER_ID"
        )
    );

    "signature_verified" := "common"."secure_hash_equals"(
        "SIGN"::BYTEA,
        "result_hash"::BYTEA
    );

    IF NOT "signature_verified" THEN
        RAISE sqlstate 'PT401' USING
            message = 'Unauthorized';
    END IF;

    IF EXISTS (
        SELECT 1
        FROM legacy.payment p
        WHERE "service" = 'freekassa'
            AND "p"."order_id" = "freekassa_callback_inner"."MERCHANT_ORDER_ID"
    ) THEN
        RAISE sqlstate 'PT409' USING
            message = 'Payment already exists';
    END IF;

    subuser_id := (
        SELECT u.sub_id
        FROM legacy.user u
        INNER JOIN legacy.invoice i ON i.user_id = u.user_id
        WHERE i.id = "MERCHANT_ORDER_ID"::TEXT AND i.pool::TEXT = u.pool::TEXT
        LIMIT 1
    );

    INSERT INTO legacy.payment
    (
        user_id,
        subuser_id,
        paid,
        order_id,
        amount_gb,
        balance_before,
        discount,
        service,
        date
    ) VALUES (
        (
            SELECT "user_id"
            FROM "legacy"."invoice"
            WHERE "id" = "MERCHANT_ORDER_ID"
        ),
        subuser_id,
        "AMOUNT",
        "MERCHANT_ORDER_ID",
        (
            SELECT "amount"
            FROM "legacy"."invoice"
            WHERE id = "MERCHANT_ORDER_ID"
        ),
        CASE WHEN "subuser_id" IS NULL THEN
            '0 GB'
        ELSE
            (
                SELECT "dataimpulse"."get_subuser"("subuser_id")->>'balance_format'
            )
        END,
        NULL,
        'freekassa',
        current_date
    );

    PERFORM "process_successful_payment"("MERCHANT_ORDER_ID");
    RETURN 'YES';
END
$$;


ALTER FUNCTION vgate.freekassa_callback_inner("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text) OWNER TO postgres;

--
-- Name: get_apays_invoice_status(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_apays_invoice_status(order_id text) RETURNS json
    LANGUAGE plpgsql
    AS $$
DECLARE
    form_data TEXT = '';
    sign TEXT;
    response_status INT;
    response JSON;
BEGIN
    sign := md5(order_id || ':' || '6c375258-ae9f-4ad5-bd8f-0324f550cb33');
    form_data := form_data || 'client_id=481';
    form_data := form_data || '&order_id=' || order_id;
    form_data := form_data || '&sign=' || sign;

    SELECT status, content::JSON
    FROM http(
        (
            'GET',
            'https://apays.io/backend/get_order?' || form_data,
            NULL,
            NULL,
            NULL
        )::http_request
    ) INTO response_status, response;

    IF (response_status != 200) OR (response->>'status' != 'true') THEN
        RAISE sqlstate 'PT500' USING message = 'failed to get order status';
    ELSE
        RETURN json_build_object(
            'order_id', order_id,
            'status', response->>'order_status'
        );
    END IF;
END
$$;


ALTER FUNCTION vgate.get_apays_invoice_status(order_id text) OWNER TO postgres;

--
-- Name: get_balance(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_balance(token text) RETURNS integer
    LANGUAGE plpgsql
    AS $$
DECLARE
    balance INT;
BEGIN
    IF NOT EXISTS (SELECT 1 FROM resellers WHERE api_key = token) THEN
        RAISE sqlstate 'PT401' USING
            message = 'Unauthorized';
    END IF;

    SELECT traffic_amount
    FROM resellers
    WHERE api_key = token
    INTO balance;

    IF balance IS NULL THEN
        RAISE sqlstate 'PT500' USING
            message = 'Failed to get balance';
    ELSE
        RETURN balance;
    END IF;
END
$$;


ALTER FUNCTION vgate.get_balance(token text) OWNER TO postgres;

--
-- Name: get_banner(integer); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_banner(id integer) RETURNS vgate."application/octet-stream"
    LANGUAGE sql SECURITY DEFINER
    AS $$
  SELECT blob FROM legacy.banner WHERE banner.id = get_banner.id;
$$;


ALTER FUNCTION vgate.get_banner(id integer) OWNER TO postgres;

--
-- Name: get_banner_blob(integer); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_banner_blob(id integer) RETURNS vgate."application/octet-stream"
    LANGUAGE sql SECURITY DEFINER
    AS $$
  SELECT blob FROM legacy.banner WHERE banner.id = get_banner_blob.id;
$$;


ALTER FUNCTION vgate.get_banner_blob(id integer) OWNER TO postgres;

--
-- Name: get_banners(); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_banners() RETURNS jsonb
    LANGUAGE sql SECURITY DEFINER
    AS $$
  SELECT jsonb_agg(jsonb_build_object('id', id, 'name', name, 'link', link)) 
  FROM legacy.banner;
$$;


ALTER FUNCTION vgate.get_banners() OWNER TO postgres;

--
-- Name: get_blog_article(bigint); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_blog_article(article_id bigint) RETURNS record
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'vgate', 'public', 'pg_temp'
    AS $$
DECLARE
    current_user_id text;
    article record;
BEGIN
    SELECT id, title, content, language, hidden, created_at, updated_at, "order",
           CASE WHEN image_blob IS NOT NULL THEN true ELSE false END as has_image
    FROM legacy.blog_article WHERE "order" = article_id INTO article;
    
    -- Check if article exists
    IF NOT FOUND THEN
        RAISE sqlstate 'PT404' USING
            message = 'Article not found';
    END IF;
    
    -- Return result
    RETURN article;
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE sqlstate 'PT500' USING
            message = 'Unexpected server error';
END;
$$;


ALTER FUNCTION vgate.get_blog_article(article_id bigint) OWNER TO postgres;

--
-- Name: get_blog_article_image_blob(bigint); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_blog_article_image_blob(article_id bigint) RETURNS vgate."application/octet-stream"
    LANGUAGE sql SECURITY DEFINER
    AS $$
  SELECT image_blob FROM legacy.blog_article WHERE "order" = get_blog_article_image_blob.article_id;
$$;


ALTER FUNCTION vgate.get_blog_article_image_blob(article_id bigint) OWNER TO postgres;

--
-- Name: get_blog_articles(integer, integer, text, vgate.language); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_blog_articles(limit_count integer DEFAULT 50, offset_count integer DEFAULT 0, search_query text DEFAULT NULL::text, user_language vgate.language DEFAULT NULL::vgate.language) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'vgate', 'public', 'pg_temp'
    AS $_$
    DECLARE
        current_user_role text;
        articles_json json;
        where_clause text;
        total_count integer;
    BEGIN
        -- Try to get user role, but don't fail if not authenticated
        BEGIN
            current_user_role := common.current_role();
        EXCEPTION
            WHEN OTHERS THEN
                current_user_role := NULL;
        END;

        -- Build where clause
        where_clause := 'WHERE hidden = false';
        
        -- Add language filter if specified
        IF user_language IS NOT NULL THEN
            where_clause := where_clause || format(' AND language = %L', user_language);
        END IF;
        
        -- Add search filter if specified
        IF search_query IS NOT NULL AND trim(search_query) != '' THEN
            where_clause := where_clause || format(' AND (title ILIKE %L OR content ILIKE %L)', 
                '%' || search_query || '%', '%' || search_query || '%');
        END IF;

        -- Admins can see hidden articles too
        IF current_user_role = 'admin' THEN
            where_clause := 'WHERE true'; -- Show all articles (hidden and public)
            
            -- Re-add language and search filters for admins
            IF user_language IS NOT NULL THEN
                where_clause := where_clause || format(' AND language = %L', user_language);
            END IF;
            
            IF search_query IS NOT NULL AND trim(search_query) != '' THEN
                where_clause := where_clause || format(' AND (title ILIKE %L OR content ILIKE %L)', 
                    '%' || search_query || '%', '%' || search_query || '%');
            END IF;
        END IF;

        EXECUTE format($f$
           SELECT count(*) FROM legacy.blog_article
           %s
        $f$, where_clause)
        INTO total_count;

        RAISE LOG 'where_clause: %', where_clause;

        EXECUTE format($f$
            SELECT COALESCE(jsonb_agg(row_to_json(t)), '[]')
            FROM (
                SELECT id, title, content, language, hidden, created_at, updated_at, "order",
                CASE WHEN image_blob IS NOT NULL THEN true ELSE false END as has_image
                FROM legacy.blog_article
                %s
                ORDER BY created_at DESC
                LIMIT %s OFFSET %s
            ) t
        $f$, where_clause, limit_count, offset_count)
        INTO articles_json;

        RETURN jsonb_build_object(
            'articles', articles_json,
            'count', COALESCE(json_array_length(articles_json), 0),
            'total', COALESCE(total_count, 0)
        );
    EXCEPTION
        WHEN OTHERS THEN
            RAISE warning 'Error getting blog articles: %', SQLERRM;
            RAISE sqlstate 'PT500' USING
                message = 'Unexpected server error';
    END;
    $_$;


ALTER FUNCTION vgate.get_blog_articles(limit_count integer, offset_count integer, search_query text, user_language vgate.language) OWNER TO postgres;

--
-- Name: get_current_setting(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_current_setting(setting text, OUT response text) RETURNS text
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
    SELECT current_setting(setting) INTO response;
END; $$;


ALTER FUNCTION vgate.get_current_setting(setting text, OUT response text) OWNER TO postgres;

--
-- Name: get_dataimpulse_pool_stats(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_dataimpulse_pool_stats(pool text) RETURNS json
    LANGUAGE plpgsql
    AS $$
BEGIN
    RETURN (dataimpulse.pool_stats(pool));
END
$$;


ALTER FUNCTION vgate.get_dataimpulse_pool_stats(pool text) OWNER TO postgres;

--
-- Name: get_dataimpulse_proxy_asns(common.dataimpulsepool, text[], text[], text[], text[], text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_dataimpulse_proxy_asns(pool common.dataimpulsepool, countries text[], states text[] DEFAULT '{}'::text[], cities text[] DEFAULT '{}'::text[], zipcodes text[] DEFAULT '{}'::text[], order_by text DEFAULT 'name,asc'::text) RETURNS json
    LANGUAGE plpgsql
    AS $$
BEGIN
    RETURN dataimpulse.get_proxy_asns(
        pool,
        countries,
        states,
        cities,
        zipcodes,
        order_by
    );
END
$$;


ALTER FUNCTION vgate.get_dataimpulse_proxy_asns(pool common.dataimpulsepool, countries text[], states text[], cities text[], zipcodes text[], order_by text) OWNER TO postgres;

--
-- Name: get_dataimpulse_proxy_cities(common.dataimpulsepool, text[], text[], text[], text[], text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_dataimpulse_proxy_cities(pool common.dataimpulsepool, countries text[], states text[] DEFAULT '{}'::text[], zipcodes text[] DEFAULT '{}'::text[], asns text[] DEFAULT '{}'::text[], order_by text DEFAULT 'name,asc'::text) RETURNS json
    LANGUAGE plpgsql
    AS $$
DECLARE
    _token TEXT := get_current_token();
    response_status INT;
    response JSON;
BEGIN
    RETURN dataimpulse.get_proxy_cities(
        pool,
        countries,
        states,
        zipcodes,
        asns,
        order_by
    );
END
$$;


ALTER FUNCTION vgate.get_dataimpulse_proxy_cities(pool common.dataimpulsepool, countries text[], states text[], zipcodes text[], asns text[], order_by text) OWNER TO postgres;

--
-- Name: get_dataimpulse_proxy_countries(common.dataimpulsepool, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_dataimpulse_proxy_countries(pool common.dataimpulsepool, order_by text DEFAULT 'name,asc'::text) RETURNS json
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    _token TEXT := get_current_token();
    response_status INT;
    response JSON;
BEGIN
    RETURN dataimpulse.get_proxy_countries(
        pool,
        order_by
    );
END
$$;


ALTER FUNCTION vgate.get_dataimpulse_proxy_countries(pool common.dataimpulsepool, order_by text) OWNER TO postgres;

--
-- Name: get_dataimpulse_proxy_states(common.dataimpulsepool, text[], text[], text[], text[], text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_dataimpulse_proxy_states(pool common.dataimpulsepool, countries text[], cities text[] DEFAULT '{}'::text[], zipcodes text[] DEFAULT '{}'::text[], asns text[] DEFAULT '{}'::text[], order_by text DEFAULT 'name,asc'::text) RETURNS json
    LANGUAGE plpgsql
    AS $$
DECLARE
    _token TEXT := get_current_token();
    response_status INT;
    response JSON;
BEGIN
    RETURN dataimpulse.get_proxy_states(
        pool,
        countries,
        cities,
        zipcodes,
        asns,
        order_by
    );
END
$$;


ALTER FUNCTION vgate.get_dataimpulse_proxy_states(pool common.dataimpulsepool, countries text[], cities text[], zipcodes text[], asns text[], order_by text) OWNER TO postgres;

--
-- Name: get_dataimpulse_proxy_zipcodes(common.dataimpulsepool, text[], text[], text[], text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_dataimpulse_proxy_zipcodes(pool common.dataimpulsepool, countries text[], states text[] DEFAULT '{}'::text[], asns text[] DEFAULT '{}'::text[], order_by text DEFAULT 'name,asc'::text) RETURNS json
    LANGUAGE plpgsql
    AS $$
DECLARE
    _token TEXT := get_current_token();
    response_status INT;
    response JSON;
BEGIN
    RETURN dataimpulse.get_proxy_zipcodes(
        pool,
        countries,
        states,
        asns,
        order_by
    );
END
$$;


ALTER FUNCTION vgate.get_dataimpulse_proxy_zipcodes(pool common.dataimpulsepool, countries text[], states text[], asns text[], order_by text) OWNER TO postgres;

--
-- Name: get_default_pool_parameters(common.dataimpulsepool); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_default_pool_parameters(pool common.dataimpulsepool DEFAULT 'residential'::common.dataimpulsepool) RETURNS jsonb
    LANGUAGE plpgsql
    AS $$
DECLARE
    _current_user TEXT := common.current_user_id();
    sub_id INT;
    user_info JSONB;
    default_params JSONB;
BEGIN
    SET ROLE TO postgres;

    -- Get user's pool if not specified
    IF pool IS NULL THEN
        SELECT "user".pool INTO pool
        FROM legacy.user
        WHERE user_id = _current_user
        LIMIT 1;
        
        IF pool IS NULL THEN
            pool := 'residential'::common.dataimpulsepool;
        END IF;
    END IF;

    SELECT "user".sub_id::INT
    FROM legacy.user
    WHERE user_id = _current_user AND "user".pool = get_default_pool_parameters.pool
    INTO sub_id;

    IF sub_id IS NULL THEN
        RAISE sqlstate 'PT422' USING
            message = 'No subuser found for this pool type';
    END IF;

    user_info := dataimpulse.get_subuser(sub_id);
    
    -- Extract default_pool_parameters or return default structure
    IF user_info ? 'default_pool_parameters' THEN
        default_params := user_info->'default_pool_parameters';
    ELSE
        default_params := jsonb_build_object(
            'countries', '[]'::jsonb,
            'cities', '[]'::jsonb,
            'states', '[]'::jsonb,
            'zipcodes', '[]'::jsonb,
            'asns', '[]'::jsonb,
            'exclude_countries', '[]'::jsonb,
            'exclude_asn', '[]'::jsonb,
            'anonymous_filter', false,
            'rotation_interval', null
        );
    END IF;
    
    RETURN default_params;
EXCEPTION
    WHEN OTHERS THEN
        RAISE;
END $$;


ALTER FUNCTION vgate.get_default_pool_parameters(pool common.dataimpulsepool) OWNER TO postgres;

--
-- Name: get_my_articles(integer, integer); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_my_articles(limit_count integer DEFAULT 50, offset_count integer DEFAULT 0) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $_$
DECLARE
    current_user_id text;
    articles jsonb;
    total_count integer;
BEGIN
    current_user_id := common.current_user_id();

    EXECUTE $f$
        SELECT count(*) FROM legacy.blog_article WHERE user_id = $1
    $f$
    INTO total_count
    USING current_user_id;
    
    EXECUTE $f$
        SELECT COALESCE(jsonb_agg(row_to_json(t)), '[]')
        FROM (SELECT id, title, content, language, hidden, created_at, updated_at, "order", user_id,
                     CASE WHEN image_blob IS NOT NULL THEN true ELSE false END as has_image
              FROM legacy.blog_article
        WHERE user_id = $1
        ORDER BY created_at DESC
        LIMIT $2 OFFSET $3) t
    $f$
    INTO articles
    USING current_user_id, limit_count, offset_count;
    
    RETURN jsonb_build_object(
        'articles', COALESCE(articles, '[]'::jsonb),
        'count', COALESCE(jsonb_array_length(articles), 0),
        'total', COALESCE(total_count, 0)
    );
EXCEPTION
    WHEN OTHERS THEN
        RAISE warning 'Error getting my articles: %', SQLERRM;
        RAISE sqlstate 'PT500' USING
            message = 'Unexpected server error';
END;
$_$;


ALTER FUNCTION vgate.get_my_articles(limit_count integer, offset_count integer) OWNER TO postgres;

--
-- Name: get_proxy(text, text, text, text, integer, integer, common.dataimpulsepool, text[], text[], text[], text[], text[], text[], common.proxyregion); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_proxy(anonymous text, type text, protocol text, format text, quantity integer, sessionttl integer, pool common.dataimpulsepool, countries text[] DEFAULT NULL::text[], cities text[] DEFAULT NULL::text[], states text[] DEFAULT NULL::text[], excluded_asns text[] DEFAULT NULL::text[], included_asns text[] DEFAULT NULL::text[], zipcodes text[] DEFAULT NULL::text[], region common.proxyregion DEFAULT 'eur'::common.proxyregion) RETURNS vgate."text/plain"
    LANGUAGE plpgsql
    AS $$
DECLARE
    "current_user" TEXT := common.current_user_id();
    "sub_id" TEXT;
BEGIN
    SET ROLE TO postgres;

    IF common.is_provider() THEN
        "current_user" := common.get_header('X-Tg-Id');
        IF "current_user" IS NULL THEN
            RAISE EXCEPTION 'X-Tg-Id header is required';
        END IF;
    END IF;

    SELECT "user"."sub_id" 
    FROM "legacy"."user" 
    WHERE "user_id" = "current_user" AND "user"."pool"::DATAIMPULSEPOOL = "get_proxy"."pool" 
    INTO "sub_id";

    RETURN "dataimpulse"."get_proxy"(
        "anonymous"     := "anonymous",
        "type"          := "type",
        "protocol"      := "protocol",
        "format"        := "format",
        "quantity"      := "quantity",
        "sessionttl"    := "sessionttl",
        "pool"          := "pool",
        "subuser_id"    := "sub_id",
        "countries"     := "countries",
        "cities"        := "cities",
        "states"        := "states",
        "excluded_asns" := "excluded_asns",
        "included_asns" := "included_asns",
        "zipcodes"      := "zipcodes",
        "host"          := COALESCE((SELECT "ip" FROM "dataimpulse"."host" WHERE "host"."region" = "get_proxy"."region" LIMIT 1), '148.251.5.30')
    );
END $$;


ALTER FUNCTION vgate.get_proxy(anonymous text, type text, protocol text, format text, quantity integer, sessionttl integer, pool common.dataimpulsepool, countries text[], cities text[], states text[], excluded_asns text[], included_asns text[], zipcodes text[], region common.proxyregion) OWNER TO postgres;

--
-- Name: get_whitelist_ips(common.dataimpulsepool); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.get_whitelist_ips(pool common.dataimpulsepool) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    _current_user TEXT := common.current_user_id();
    sub_id INT;
    user_info JSONB;
BEGIN
    
    SELECT "user".sub_id::INT
    FROM legacy.user
    WHERE user_id = _current_user AND "user".pool = get_whitelist_ips.pool
    INTO sub_id;

    IF sub_id IS NULL THEN
        RAISE sqlstate 'PT422' USING
            message = 'No subuser found for this pool type';
    END IF;

    user_info := dataimpulse.get_subuser(sub_id);
    
    RETURN COALESCE(user_info->'allowed_ips', '[]'::JSONB);
EXCEPTION
    WHEN OTHERS THEN
        RAISE LOG 'Error in get_whitelist_ips: % - %', SQLSTATE, SQLERRM;
        RAISE sqlstate 'PT500' USING 
            message = 'Internal server error';
END $$;


ALTER FUNCTION vgate.get_whitelist_ips(pool common.dataimpulsepool) OWNER TO postgres;

--
-- Name: heleket_callback(json); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.heleket_callback(json) RETURNS json
    LANGUAGE plpgsql SECURITY DEFINER
    AS $_$
DECLARE
    data JSON := $1;
    merchant_id TEXT := current_setting('app.heleket_merchant');
    api_key TEXT := current_setting('app.heleket_api_key');
    sign TEXT;
    sign_base64 TEXT;
    hash TEXT;
    o_id TEXT;
    signature_verified BOOLEAN;
    subuser_id INT;
    status TEXT := data->>'status';
    v_log_source TEXT := common.build_log_source(ARRAY['vgate', 'heleket_callback']);
BEGIN
    RAISE LOG '% Heleket callback received: %', v_log_source, data;
    
    sign = data->>'sign';

    SELECT json_object_agg(key, value)
    FROM json_each(data)
    WHERE key != 'sign'
    INTO data;

    data = REPLACE(data::TEXT, ' ', '')::JSON;

    RAISE NOTICE 'data: %', data;

    sign_base64 = encode(
        convert_to(data::TEXT, 'UTF8'),
        'base64'
    );

    hash := md5(
        REPLACE(
            sign_base64,
            E'\n',
            ''
        ) || api_key
    );

    signature_verified = common.secure_hash_equals(
        convert_to(sign, 'UTF8'),
        convert_to(hash, 'UTF8')
    );
    RAISE LOG '% Heleket signature verification result: %', v_log_source, signature_verified;

    IF NOT signature_verified THEN
        RAISE LOG '% Heleket signature verification failed', v_log_source;
        RAISE sqlstate 'PT401' USING
            message = 'Unauthorized';
    END IF;

    o_id := data->>'order_id';
    RAISE LOG '% Heleket processing order_id: %, status: %', v_log_source, o_id, status;

    IF EXISTS ( 
        SELECT 1 
        FROM legacy.payment p
        WHERE p.order_id = o_id
    ) THEN
        RAISE LOG '% Heleket payment already exists for order_id: %', v_log_source, o_id;
        RAISE sqlstate 'PT409' USING
            message = 'Payment already exists';
    END IF;

    IF NOT EXISTS (
        SELECT 1
        FROM legacy.invoice i
        WHERE i.id = o_id
    ) THEN
        RAISE LOG '% Heleket invoice not found for order_id: %', v_log_source, o_id;
        RAISE sqlstate 'PT404' USING
            message = 'Invoice not found';
    END IF;

    IF status IN ('paid', 'paid_over') THEN
        RAISE LOG '% Heleket payment status is valid for order_id: %, proceeding with payment processing', v_log_source, o_id;
        
        subuser_id := (
            SELECT u.sub_id
            FROM legacy.user u
            INNER JOIN legacy.invoice i ON i.user_id = u.user_id
            WHERE i.id = o_id AND i.pool::TEXT = u.pool::TEXT
            LIMIT 1
        );
        
        RAISE LOG '% Heleket payment subuser_id: % for order_id: %', v_log_source, subuser_id, o_id;

        INSERT INTO legacy.payment
        (
            user_id,
            subuser_id,
            paid,
            order_id,
            amount_gb,
            balance_before,
            discount,
            service,
            date
        ) VALUES (
            (
                SELECT user_id
                FROM legacy.invoice i
                WHERE i.id = o_id
            ),
            subuser_id,
            (
                SELECT i.price
                FROM legacy.invoice i
                WHERE i.id = o_id
            ),
            (
                SELECT i.id
                FROM legacy.invoice i
                WHERE i.id = o_id
            ),
            (
                SELECT i.amount
                FROM legacy.invoice i
                WHERE i.id = o_id
            ),
            CASE WHEN subuser_id IS NULL THEN
                '0 GB'
            ELSE
                (
                    SELECT dataimpulse.get_subuser(subuser_id)->>'balance_format'
                )
            END,
            NULL,
            'heleket',
            current_date
        );
        
        RAISE LOG '% Heleket payment record inserted for order_id: %', v_log_source, o_id;
        PERFORM process_successful_payment(o_id);
        RAISE LOG '% Heleket payment successfully processed for order_id: %', v_log_source, o_id;
    ELSE
        RAISE LOG '% Heleket payment status is not valid for processing: %, order_id: %', v_log_source, status, o_id;
    END IF;

    RETURN json_build_object(
        'success', true
    );
END
$_$;


ALTER FUNCTION vgate.heleket_callback(json) OWNER TO postgres;

--
-- Name: i18n.dictionary(vgate.language); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate."i18n.dictionary"(lang_code vgate.language) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    lang_id INTEGER;
    _country_id INTEGER;
    result jsonb;
BEGIN
    SELECT language_id, country_id FROM common.get_language_id(lang_code) INTO lang_id, _country_id;

    SELECT jsonb_object_agg(t.text_id, t.content)
    FROM vgate.translation t
    WHERE t.language_id = lang_id
        AND t.country_id = _country_id
    INTO result;

    RETURN COALESCE(result, '{}'::jsonb);
END;
$$;


ALTER FUNCTION vgate."i18n.dictionary"(lang_code vgate.language) OWNER TO postgres;

--
-- Name: i18n.load(jsonb); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate."i18n.load"(jsonb) RETURNS TABLE(hash text, label text, lang vgate.language, status text, error_message text)
    LANGUAGE plpgsql SECURITY DEFINER
    AS $_$
DECLARE
    translations jsonb := $1;
    translation_item jsonb;
    _hash common.sha256;
    _label text;
    _content text;
    _lang vgate.language;
    lang_id INTEGER;
    _country_id INTEGER;
BEGIN
    -- Validate input is array
    IF jsonb_typeof(translations) != 'array' THEN
        RAISE EXCEPTION 'Input must be a JSON array of translation objects';
    END IF;

    -- Process each translation item
    FOR translation_item IN SELECT jsonb_array_elements(translations)
    LOOP
        BEGIN
            -- Extract fields from translation item
            _hash    := (translation_item->>'hash')::common.sha256;
            _label   := translation_item->>'label';
            _content := translation_item->>'content';
            _lang    := (translation_item->>'lang')::vgate.language;

            -- Validate required fields
            IF _hash IS NULL OR _label IS NULL OR _content IS NULL OR _lang IS NULL THEN
                hash          := translation_item->>'hash';
                label         := _label;
                lang          := _lang;
                status        := 'error';
                error_message := 'Missing required fields: hash, label, content, lang';
                RETURN NEXT;
                CONTINUE;
            END IF;

            -- Insert text entry if not exists, or update actualized_at if exists
            INSERT INTO vgate.text (id, label, actualized_at)
            VALUES (_hash, _label, now())
            ON CONFLICT (id) DO UPDATE SET
                actualized_at = now();

            -- Get language IDs
            SELECT language_id, country_id FROM common.get_language_id(_lang)
            INTO lang_id, _country_id;

            -- Insert translation
            INSERT INTO vgate.translation (text_id, language_id, country_id, content)
            VALUES (_hash, lang_id, _country_id, _content)
            ON CONFLICT (text_id, language_id, country_id) DO UPDATE SET
                content = EXCLUDED.content,
                updated_at = now();

            -- Return success row
            hash          := _hash::text;
            label         := _label;
            lang          := _lang;
            status        := 'success';
            error_message := NULL;
            RETURN NEXT;

        EXCEPTION WHEN OTHERS THEN
            hash          := COALESCE(_hash::text, translation_item->>'hash');
            label         := _label;
            lang          := _lang;
            status        := 'error';
            error_message := SQLERRM;
            RETURN NEXT;
        END;
    END LOOP;

    RETURN;
END;
$_$;


ALTER FUNCTION vgate."i18n.load"(jsonb) OWNER TO postgres;

--
-- Name: i18n.translate(common.sha256, text, text, vgate.language, vgate.language); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate."i18n.translate"(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language) RETURNS vgate."text/plain"
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    lang_id INTEGER;
    _country_id INTEGER;
    _content TEXT;
BEGIN
    INSERT INTO vgate.text (id, label, actualized_at)
    VALUES (hash, label, now())
    ON CONFLICT (id) DO NOTHING;

    IF NOT FOUND THEN
        SELECT language_id, country_id FROM common.get_language_id(lable_lang_code) INTO lang_id, _country_id;

        INSERT INTO vgate.translation (text_id, language_id, country_id, content)
        VALUES (hash, lang_id, _country_id, "i18n.translate".content)
        ON CONFLICT (text_id, language_id, country_id) DO UPDATE SET
            content = EXCLUDED.content,
            updated_at = now();
    ELSE 
        UPDATE vgate.text SET actualized_at = now() WHERE id = hash;
    END IF;

    SELECT language_id, country_id FROM common.get_language_id(lang_code) INTO lang_id, _country_id;

    SELECT translation.content 
    FROM vgate.translation 
    WHERE text_id = hash
        AND language_id = lang_id
        AND country_id = _country_id 
    INTO _content;

    IF FOUND THEN
        RETURN _content;
    END IF;

    -- Look for existing translations with same source content and target language
    SELECT t_target.content 
    FROM vgate.translation t_source
    JOIN vgate.translation t_target ON t_source.text_id = t_target.text_id
    WHERE t_source.content = "i18n.translate".content  -- same source content
        AND t_source.language_id = (SELECT language_id FROM common.get_language_id(lable_lang_code))
        AND t_source.country_id = (SELECT country_id FROM common.get_language_id(lable_lang_code))
        AND t_target.language_id = lang_id           -- translated to target language 
        AND t_target.country_id = _country_id        -- in target country
        AND t_source.text_id != hash                 -- different text (not the one we're looking for)
    LIMIT 1
    INTO _content;

    IF FOUND THEN
        -- Found a reusable translation, store it for this text_id
        INSERT INTO vgate.translation (text_id, language_id, country_id, content)
        VALUES (hash, lang_id, _country_id, _content)
        ON CONFLICT (text_id, language_id, country_id) DO UPDATE SET
            content = EXCLUDED.content,
            updated_at = now();
        
        RETURN _content;
    END IF;

    -- If still no translation found, return original content
    RETURN "i18n.translate".content;
END;
$$;


ALTER FUNCTION vgate."i18n.translate"(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language) OWNER TO postgres;

--
-- Name: is_password_exists(); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.is_password_exists() RETURNS boolean
    LANGUAGE plpgsql
    AS $$
DECLARE
  has_password BOOLEAN;
  _current_user TEXT;
BEGIN
  _current_user = common.current_user_id();

  SET role TO postgres;

  SELECT EXISTS (
    SELECT 1
    FROM legacy.all_user
    WHERE user_id = _current_user
    AND password IS NOT NULL
  )
  INTO has_password;

  RETURN has_password;
END
$$;


ALTER FUNCTION vgate.is_password_exists() OWNER TO postgres;

--
-- Name: legacy_get_statistic(common.period, common.dataimpulsepool); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.legacy_get_statistic(period common.period DEFAULT 'week'::common.period, pool common.dataimpulsepool DEFAULT 'residential'::common.dataimpulsepool) RETURNS jsonb
    LANGUAGE plpgsql
    AS $$
DECLARE
  sub_id TEXT; 
  _current_user TEXT;
BEGIN
  _current_user := common.current_user_id();

  IF common.is_provider() THEN
    _current_user := common.get_header('X-Tg-Id');
    IF _current_user IS NULL THEN
      RAISE EXCEPTION 'You are provider, so X-Tg-Id header is required';
    END IF;
  END IF;

  SET ROLE TO postgres;

  SELECT "user".sub_id 
  FROM legacy.user 
  WHERE user_id = _current_user AND "user".pool::DATAIMPULSEPOOL = legacy_get_statistic.pool 
  INTO sub_id;

  RETURN dataimpulse.subuser_get_usage_stat(sub_id::INT, period);
END $$;


ALTER FUNCTION vgate.legacy_get_statistic(period common.period, pool common.dataimpulsepool) OWNER TO postgres;

--
-- Name: merge_users(text, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.merge_users(source_user_id text, target_user_id text) RETURNS TABLE(operation text, table_name text, rows_affected bigint, details text)
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
    RETURN QUERY SELECT * FROM common.merge_users(source_user_id, target_user_id, false);
END;
$$;


ALTER FUNCTION vgate.merge_users(source_user_id text, target_user_id text) OWNER TO postgres;

--
-- Name: pallyinfo_callback(text, text, text, text, vgate.pally_status, vgate.pally_currency, text, text, text, text, text, text, text, text, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.pallyinfo_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.pally_status, "CurrencyIn" vgate.pally_currency, "SignatureValue" text, custom text DEFAULT NULL::text, "AccountType" text DEFAULT NULL::text, "AccountNumber" text DEFAULT NULL::text, "BalanceAmount" text DEFAULT NULL::text, "BalanceCurrency" text DEFAULT NULL::text, "AccountBank" text DEFAULT NULL::text, "ErrorCode" text DEFAULT NULL::text, "ErrorMessage" text DEFAULT NULL::text) RETURNS json
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    sign TEXT;
    signature_verified BOOLEAN;
    subuser_id INT;
    api_token TEXT := current_setting('app.pally_api_token');
    hash TEXT;
BEGIN
    subuser_id := (
        SELECT u.sub_id
        FROM legacy.user u
        INNER JOIN legacy.invoice i ON i.user_id = u.user_id AND i.pool = u.pool
        WHERE i.id = "InvId"
        LIMIT 1
    );

    hash = md5(
        format('%s:%s:%s', "OutSum", "InvId", api_token)
    );

    signature_verified := (
        "SignatureValue" = upper(hash)
    );

    IF NOT EXISTS (
        SELECT 1
        FROM legacy.payment p
        WHERE p.order_id = "InvId"
          AND service = 'pally'
    )
    AND "Status"::TEXT IN ('SUCCESS', 'OVERPAID')
    AND signature_verified THEN
        INSERT INTO legacy.payment
        (
            user_id,
            subuser_id,
            paid,
            order_id,
            amount_gb,
            balance_before,
            discount,
            service,
            date
        ) VALUES (
            (
                SELECT user_id
                FROM legacy.invoice i
                WHERE i.id = "InvId"
            ),
            subuser_id,
            (
                SELECT i.price
                FROM legacy.invoice i
                WHERE i.id = "InvId"
            ),
            (
                SELECT i.id
                FROM legacy.invoice i
                WHERE i.id = "InvId"
            ),
            (
                SELECT i.amount
                FROM legacy.invoice i
                WHERE i.id = "InvId"
            ),
            CASE WHEN subuser_id IS NULL THEN
                '0 GB'
            ELSE
                (
                    SELECT dataimpulse.get_subuser(subuser_id)->>'balance_format'
                )
            END,
            NULL,
            'pally',
            current_date
        );
    ELSE
        RAISE sqlstate 'PT401' USING
            message = 'Unauthorized';
    END IF;

    PERFORM process_successful_payment("InvId");

    RETURN json_build_object('success', true);
END
$$;


ALTER FUNCTION vgate.pallyinfo_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.pally_status, "CurrencyIn" vgate.pally_currency, "SignatureValue" text, custom text, "AccountType" text, "AccountNumber" text, "BalanceAmount" text, "BalanceCurrency" text, "AccountBank" text, "ErrorCode" text, "ErrorMessage" text) OWNER TO postgres;

--
-- Name: password_recovery(text, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.password_recovery(recovery_code text, password text) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    username TEXT;
    _user_id TEXT;
BEGIN
    IF NOT EXISTS (
        SELECT 1
        FROM legacy.recovery_inner
        WHERE code = recovery_code
    ) THEN
        RAISE sqlstate 'PT409' USING
            message = 'Wrong recovery code';
    END IF;

    SELECT user_id
    FROM legacy.recovery_inner
    WHERE code = recovery_code
    INTO _user_id;

    SELECT au.username
    FROM legacy.all_user AS au
    WHERE user_id = _user_id
    INTO username;

    UPDATE legacy.recovery_inner
    SET used = true
    WHERE code = recovery_code;

    UPDATE legacy.all_user
    SET password = common.generate_scram_hash(password_recovery.password)
    WHERE user_id = _user_id;

    RETURN;
END
$$;


ALTER FUNCTION vgate.password_recovery(recovery_code text, password text) OWNER TO postgres;

--
-- Name: password_recovery_email(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.password_recovery_email(email text) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    _email TEXT = email;
    user_id TEXT;
    username TEXT;
    recovery_code TEXT;
BEGIN
    IF EXISTS (
        SELECT 1
        FROM legacy.all_user AS au
        WHERE au.email = _email
    ) THEN
        SELECT au.user_id, au.username
        FROM legacy.all_user AS au
        WHERE au.email = _email
        INTO user_id, username;
        
        recovery_code := substr(md5(RANDOM()::TEXT || CLOCK_TIMESTAMP()::TEXT), 1, 32);

        INSERT INTO legacy.recovery_inner (code, user_id, exp, used)
        VALUES (recovery_code, user_id, NOW() + INTERVAL '1 hour', false);

        PERFORM vinn.send_email(
            email,
            'Vproxy password recovery',
            common.password_recovery_email_html(
                username,
                format(
                    'https://vproxy.cc/en/password-recovery?recovery_code=%s',
                    recovery_code
                )
            )
        );
    END IF;

    RETURN;
END
$$;


ALTER FUNCTION vgate.password_recovery_email(email text) OWNER TO postgres;

--
-- Name: prices(); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.prices() RETURNS jsonb
    LANGUAGE sql SECURITY DEFINER
    AS $$
  SELECT jsonb_build_object(
    'residential', (SELECT gb_cost_usd FROM legacy.price WHERE pool = 'residential'),
    'residential_premium', (SELECT gb_cost_usd FROM legacy.price WHERE pool = 'residential_premium'),
    'datacenter', (SELECT gb_cost_usd FROM legacy.price WHERE pool = 'datacenter'),
    'mobile', (SELECT gb_cost_usd FROM legacy.price WHERE pool = 'mobile')
  )
$$;


ALTER FUNCTION vgate.prices() OWNER TO postgres;

--
-- Name: record_promo_activation(text, text, vgate.promotype); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.record_promo_activation(p_user_id text, p_promo_name text, p_promo_type vgate.promotype) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
    v_usage_count INT;
    v_traffic_amount INT;
BEGIN
    UPDATE legacy.user 
    SET used_promo_list = ''
    WHERE "user".used_promo_list IS NULL;

    IF p_promo_type = 'traffic' THEN
        SELECT traffic_amount INTO v_traffic_amount
        FROM legacy.promocode
        WHERE promo_name = p_promo_name;
        
        INSERT INTO legacy.cross_promo_activations (user_id, promo_name, gb_amount)
        VALUES (p_user_id, p_promo_name, v_traffic_amount);
    ELSE
        UPDATE legacy.disc_promocode 
        SET activations = activations - 1 
        WHERE name = p_promo_name;

        UPDATE legacy."user" 
        SET 
          used_promo_list = "user".used_promo_list || ',' || p_promo_name,
          buy_num = buy_num + 1 
        WHERE user_id=p_user_id;
    END IF;

    SELECT usage_count INTO v_usage_count
    FROM legacy.promo_activations
    WHERE user_id = p_user_id AND promo_name = p_promo_name AND promo_type::PROMOTYPE = p_promo_type;

    IF FOUND THEN
        UPDATE legacy.promo_activations
        SET usage_count = v_usage_count + 1
        WHERE user_id = p_user_id AND promo_name = p_promo_name AND promo_type::PROMOTYPE = p_promo_type;
    ELSE
        INSERT INTO legacy.promo_activations (user_id, promo_name, usage_count, promo_type)
        VALUES (p_user_id, p_promo_name, 1, p_promo_type);
    END IF;
END;
$$;


ALTER FUNCTION vgate.record_promo_activation(p_user_id text, p_promo_name text, p_promo_type vgate.promotype) OWNER TO postgres;

--
-- Name: referral_payment(integer, common.dataimpulsepool, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.referral_payment(amount integer, pool common.dataimpulsepool, promocode text DEFAULT NULL::text) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
    _current_user TEXT;
    gb_cost_usd NUMERIC;
    price NUMERIC;
    order_id TEXT;
    invoice_url TEXT;
    _sub_id INT;
    source TEXT;
    balance_before TEXT;
BEGIN
    _current_user := common.current_user_id();
    IF common.is_provider() THEN
        _current_user := common.get_header('X-Tg-Id');
        IF _current_user IS NULL THEN
            RAISE EXCEPTION 'You are a provider, but telegram id is not provided';
        END IF;
    END IF;

    SET ROLE TO postgres;

    SELECT p.gb_cost_usd
    FROM legacy.price p
    WHERE p.pool::common.dataimpulsepool = referral_payment.pool
    INTO gb_cost_usd;

    price := gb_cost_usd * amount;

    IF promocode IS NOT NULL
      AND NOT common.is_available_discount_promocode(promocode, amount, _current_user) THEN
      RAISE sqlstate 'PT422' USING message = 'promocode not exists or expired';
    END IF;

    price := common.apply_discounts(price, amount, promocode);

    if price > (
        SELECT ref_balance_usd
        FROM legacy.all_user
        WHERE all_user.user_id = _current_user
    ) THEN
        RAISE sqlstate 'PT409' USING message = 'insufficient referral balance';
    END IF;

    SELECT u.sub_id
    FROM legacy.user u
    WHERE user_id = _current_user
        AND u.pool = referral_payment.pool
    INTO _sub_id;

    IF _sub_id IS NULL THEN
        _sub_id = dataimpulse.create_subuser(
            label := 'referral_payment_' || _current_user,
            pool_type := pool::DATAIMPULSEPOOL
        )->>'id';

        INSERT INTO legacy.user (
            user_id,
            sub_id,
            pool,
            buy_num
        )
        VALUES (
            _current_user,
            _sub_id,
            pool::DATAIMPULSEPOOL,
            (
                SELECT (COALESCE(SUM(u.buy_num), 0))
                FROM legacy.user u
                WHERE u.user_id = _current_user
            )
        );
    END IF;

    UPDATE legacy.all_user
    SET ref_balance_usd = COALESCE(ref_balance_usd, 0) - price
    WHERE user_id = _current_user;

    UPDATE legacy.user
    SET buy_num = COALESCE(buy_num, 0) + 1
    WHERE user_id = _current_user;

    SELECT dataimpulse.subuser_balance_get(
        (
            SELECT u.sub_id
            FROM legacy.user AS u
            WHERE u.pool = referral_payment.pool AND u.user_id = _current_user
        )::INT
    )->'balance_format'
    INTO balance_before;

    PERFORM dataimpulse.subuser_balance_add(
        _sub_id,
        amount
    );

    IF common.is_provider() THEN
        source := 'bot';
    ELSE
        source := 'web';
    END IF;

    BEGIN
        PERFORM common.send_purchase_notification(
            NULL,
            _current_user,
            amount,
            price,
            0,
            'Реферальный баланс',
            balance_before,
            source,
            pool
        );
    EXCEPTION WHEN OTHERS THEN
        RAISE WARNING 'Failed to send notification: %', SQLERRM;
    END;

    BEGIN
      INSERT INTO
        legacy.payment(
          service,
          paid,
          user_id,
          subuser_id,
          amount_gb,
          balance_before,
          discount,
          date,
          order_id
        )
      VALUES (
        'referral',
        price::numeric(6,2),
        _current_user,
        _sub_id,
        amount,
        balance_before,
        0,
        now(),
        uuid_generate_v4()
      );
    EXCEPTION WHEN OTHERS THEN
      RAISE WARNING 'Ye shit broke mate (referral payment insert)';
    END;
END
$$;


ALTER FUNCTION vgate.referral_payment(amount integer, pool common.dataimpulsepool, promocode text) OWNER TO postgres;

--
-- Name: remove_ip_from_whitelist(inet, common.dataimpulsepool); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.remove_ip_from_whitelist(ip inet, pool common.dataimpulsepool) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    _current_user TEXT := common.current_user_id();
    sub_id INT;
BEGIN
    IF common.ip_is_local_or_private(ip) THEN
        RAISE sqlstate 'PT406' USING
            message = 'Local and private IP addresses are not allowed';
    END IF;

    IF common.is_provider() THEN
      _current_user := common.get_header('X-Tg-Id');
      IF _current_user IS NULL THEN
        RAISE EXCEPTION 'You are a provider, but telegram id is not provided';
      END IF;
    END IF;

    SELECT "user".sub_id::INT
    FROM legacy.user
    WHERE user_id = _current_user AND "user".pool = remove_ip_from_whitelist.pool
    INTO sub_id;

    IF sub_id IS NULL THEN
        RAISE sqlstate 'PT422' USING
            message = 'No subuser found for this pool type';
    END IF;

    PERFORM dataimpulse.remove_allowed_ip(sub_id, ip);
    
    RETURN jsonb_build_object('message', format('IP %s removed from whitelist', ip));
EXCEPTION
    WHEN OTHERS THEN
        RAISE LOG 'Error in remove_ip_from_whitelist: % - %', SQLSTATE, SQLERRM;
        RAISE sqlstate 'PT500' USING
            message = 'Internal server error';
END $$;


ALTER FUNCTION vgate.remove_ip_from_whitelist(ip inet, pool common.dataimpulsepool) OWNER TO postgres;

--
-- Name: request_email_confirmation(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.request_email_confirmation(user_id text) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    confirmation_token TEXT;
    user_email TEXT;
    username TEXT;
BEGIN
    -- Get user email and username
    SELECT
      "legacy"."all_user"."email", "legacy"."all_user"."username" INTO user_email, username
    FROM legacy.all_user
    WHERE legacy.all_user.user_id = request_email_confirmation.user_id;

    IF NOT FOUND THEN
        RAISE sqlstate 'PT404' USING message = 'User not found';
    END IF;

    -- Generate new confirmation token
    confirmation_token := substr(md5(RANDOM()::TEXT || CLOCK_TIMESTAMP()::TEXT), 1, 32);

    -- Insert new confirmation token
    INSERT INTO public.confirmation_inner(token, user_id, exp, used)
    VALUES (confirmation_token, user_id, NOW() + INTERVAL '1 day', false);

    PERFORM vinn.send_email(
        user_email,
        'Vproxy email confirmation',
        common.confirm_email_html(
          username,
          format(
            'https://vproxy.cc/en/confirm-email?confirmation_token=%s',
            confirmation_token))
    );
END;
$$;


ALTER FUNCTION vgate.request_email_confirmation(user_id text) OWNER TO postgres;

--
-- Name: request_email_confirmation(vgate.email_address); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.request_email_confirmation(email vgate.email_address) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $_$
DECLARE
    confirmation_token TEXT;
    _old_email TEXT;
    username TEXT;
    _user_id TEXT;
BEGIN
    IF common.is_provider() THEN
        _user_id := common.get_header('X-Tg-Id');

        IF _user_id IS NULL THEN
            RAISE EXCEPTION 'You are a provider, but telegram id is not provided';
        END IF;

        IF email IS NULL THEN
            RAISE EXCEPTION 'Email is not provided';
        END IF;

        IF email !~ '^[^@]+@[^@]+\.[^@]+$' THEN
          RAISE EXCEPTION 'Invalid email format';
        END IF;

        SELECT
          "legacy"."all_user"."email", "legacy"."all_user"."username" INTO _old_email, username
        FROM legacy.all_user
        WHERE legacy.all_user.user_id = _user_id;

        IF NOT FOUND THEN
            RAISE sqlstate 'PT404' USING message = 'User not found';
        END IF;

        IF _old_email IS NOT NULL THEN
            RAISE sqlstate 'PT422' USING message = 'Email already exists';
        END IF;

        BEGIN
          UPDATE legacy.all_user
          SET email = request_email_confirmation.email
          WHERE user_id = _user_id;
        EXCEPTION
          WHEN unique_violation THEN
            RAISE sqlstate 'PT409' USING message = 'Email already exists';
        END;

        confirmation_token := substr(md5(RANDOM()::TEXT || CLOCK_TIMESTAMP()::TEXT), 1, 32);

        -- Insert new confirmation token
        INSERT INTO public.confirmation_inner(token, user_id, exp, used)
        VALUES (confirmation_token, _user_id, NOW() + INTERVAL '1 day', false);

        PERFORM vinn.send_email(
            email,
            'Vproxy email confirmation',
            common.confirm_email_html(
              username,
              format(
                'https://vproxy.cc/en/confirm-email?confirmation_token=%s',
                confirmation_token))
        );
    ELSE
        RAISE EXCEPTION 'You are not a provider';
    END IF;
END;
$_$;


ALTER FUNCTION vgate.request_email_confirmation(email vgate.email_address) OWNER TO postgres;

--
-- Name: reseller_token(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.reseller_token(user_id text DEFAULT common.current_user_id()) RETURNS vgate."text/plain"
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    _user_id TEXT;
BEGIN
    RAISE LOG 'is provider: %', common.is_provider();
    IF common.is_provider() THEN

        _user_id := common.get_header('X-Tg-Id');

        IF _user_id IS NULL THEN
            RAISE EXCEPTION 'You are a provider, but telegram id is not provided';
        END IF;
    ELSE
        _user_id := reseller_token.user_id;
    END IF;

    RAISE LOG 'reseller_token called with user_id: %', _user_id;

    INSERT INTO reseller_inner.resellers (user_id) VALUES (_user_id) ON CONFLICT DO NOTHING;

    RAISE LOG 'reseller_token: successfully inserted/retrieved reseller for user_id: %', _user_id;
    
    RETURN (
        SELECT api_key
        FROM reseller_inner.resellers r
        WHERE r.user_id::TEXT = _user_id
    );
EXCEPTION
    WHEN OTHERS THEN
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception: ' || SQLERRM;
END $$;


ALTER FUNCTION vgate.reseller_token(user_id text) OWNER TO postgres;

--
-- Name: reset_password(common.dataimpulsepool); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.reset_password(pool common.dataimpulsepool) RETURNS vgate."text/plain"
    LANGUAGE plpgsql
    AS $$
DECLARE
  sub_id TEXT; 
  _current_user TEXT := common.current_user_id();
BEGIN

  SET ROLE TO postgres;

  SELECT "user".sub_id 
  FROM legacy.user 
  WHERE user_id = _current_user AND "user".pool::DATAIMPULSEPOOL = reset_password.pool 
  INTO sub_id;

  RETURN dataimpulse.reset_subuser_password(sub_id::INT)->>'password';
END $$;


ALTER FUNCTION vgate.reset_password(pool common.dataimpulsepool) OWNER TO postgres;

--
-- Name: schema_is(common.schematype); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.schema_is(_type common.schematype) RETURNS boolean
    LANGUAGE plpgsql
    AS $$
BEGIN
    IF 'gateway'::SCHEMATYPE = _type THEN
       RETURN true;
    ELSE
       RETURN false;
    END IF;
END; $$;


ALTER FUNCTION vgate.schema_is(_type common.schematype) OWNER TO postgres;

--
-- Name: set_default_pool_parameters(text[], text[], text[], text[], text[], text[], text[], boolean, integer, common.dataimpulsepool); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.set_default_pool_parameters(countries text[], cities text[], states text[], zipcodes text[], asns text[], exclude_countries text[], exclude_asn text[], anonymous_filter boolean, rotation_interval integer, pool common.dataimpulsepool) RETURNS jsonb
    LANGUAGE plpgsql
    AS $$
DECLARE
    _current_user TEXT := common.current_user_id();
    sub_id INT;
    params_object JSONB;
BEGIN
    IF common.is_provider() THEN
      _current_user := common.get_header('X-Tg-Id');
      IF _current_user IS NULL THEN
        RAISE EXCEPTION 'You are a provider, but telegram id is not provided';
      END IF;
    END IF;
    SET ROLE TO postgres;

    -- Get user's pool if not specified
    IF pool IS NULL THEN
        SELECT "user".pool INTO pool
        FROM legacy.user
        WHERE user_id = _current_user
        LIMIT 1;
        
        IF pool IS NULL THEN
            pool := 'residential'::common.dataimpulsepool;
        END IF;
    END IF;

    SELECT "user".sub_id::INT
    FROM legacy.user
    WHERE user_id = _current_user AND "user".pool = set_default_pool_parameters.pool
    INTO sub_id;

    IF sub_id IS NULL THEN
        RAISE sqlstate 'PT422' USING
            message = 'No subuser found for this pool type';
    END IF;

    -- Build the parameters object
    params_object := jsonb_build_object(
        'countries', to_jsonb(countries),
        'cities', to_jsonb(cities),
        'states', to_jsonb(states),
        'zipcodes', to_jsonb(zipcodes),
        'asns', to_jsonb(asns),
        'exclude_countries', to_jsonb(exclude_countries),
        'exclude_asn', to_jsonb(exclude_asn),
        'anonymous_filter', anonymous_filter,
        'rotation_interval', rotation_interval
    );

    -- Call dataimpulse function to set default pool parameters
    RETURN dataimpulse.subuser_set_default_pool_parameters(sub_id, params_object)->'default_pool_parameters';
EXCEPTION
    WHEN OTHERS THEN
        RAISE;
END $$;


ALTER FUNCTION vgate.set_default_pool_parameters(countries text[], cities text[], states text[], zipcodes text[], asns text[], exclude_countries text[], exclude_asn text[], anonymous_filter boolean, rotation_interval integer, pool common.dataimpulsepool) OWNER TO postgres;

--
-- Name: show_search_path(); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.show_search_path() RETURNS text
    LANGUAGE plpgsql
    AS $$
BEGIN
    RETURN (CURRENT_SCHEMAS(false) || current_setting('search_path'));
END;
$$;


ALTER FUNCTION vgate.show_search_path() OWNER TO postgres;

--
-- Name: signin(text, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.signin(username text, password text) RETURNS vgate."text/plain"
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
  _role TEXT;
  _confirmed INT;
  _user_id TEXT;
BEGIN
  SELECT 
    legacy.all_user.user_id, 
    legacy.all_user.role
  FROM 
    legacy.all_user
  WHERE 
    legacy.all_user.email = signin.username
    OR legacy.all_user.username = signin.username
    OR legacy.all_user.user_id = signin.username
  INTO _user_id, _role;

  RAISE NOTICE 'user_id %, password %', _user_id, password;
  SELECT basic_auth.check_user_pass(_user_id, password) INTO _user_id;
  IF _user_id IS NULL THEN
    RAISE invalid_password USING message = 'invalid user or password';
  END IF;

  SELECT confirmed INTO _confirmed
   FROM legacy.all_user
   WHERE all_user.user_id = _user_id;

  IF _confirmed = 0 OR _confirmed IS NULL THEN
    RAISE EXCEPTION 'Email not confirmed';
  END IF;

  RETURN (SELECT sign(
         row_to_json(r), common.get_jwt_secret()
       ) AS token
       FROM (SELECT _user_id AS sub, _role AS role) r);
END;
$$;


ALTER FUNCTION vgate.signin(username text, password text) OWNER TO postgres;

--
-- Name: signinup_tg(bigint, text, text, text, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.signinup_tg(id bigint, username text, first_name text, surname text, referral_id text) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
    -- call inner_schema.signup via SEARCH_PATH
    PERFORM vinn.signinup_tg(
	gateway_user_role(CURRENT_SCHEMA),
	id,
	username,
	first_name,
	surname,
	referral_id);
END;
$$;


ALTER FUNCTION vgate.signinup_tg(id bigint, username text, first_name text, surname text, referral_id text) OWNER TO postgres;

--
-- Name: signup(text, text, text, text, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.signup(email text, username text, password text, referral_id text DEFAULT NULL::text, admin_referral_code text DEFAULT NULL::text) RETURNS vgate."text/plain"
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    user_id TEXT;
    confirmation_token TEXT;
BEGIN
    RAISE LOG 'Signup attempt: %', username;

    BEGIN
        user_id := (SELECT vinn.signup(
            gateway_user_role(CURRENT_SCHEMA),
            email,
            username,
            password,
            referral_id
        ));

        IF admin_referral_code IS NOT NULL THEN
            BEGIN
                PERFORM vinn.admin_ref_add_user(admin_referral_code, user_id, 'web');
            EXCEPTION WHEN OTHERS THEN
                RAISE NOTICE 'Error: Failed to add user to admin_ref_users: %', SQLERRM;
            END;
        END IF;
    EXCEPTION
        WHEN SQLSTATE 'PT409' THEN
            RAISE LOG 'Signup error: User with email % or username % already exists', email, username;
            RAISE sqlstate 'PT409' USING message = 'User with this email or username already exists';
        WHEN SQLSTATE 'PT400' THEN
            RAISE LOG 'Signup error: Invalid referral ID for user %', username;
            RAISE sqlstate 'PT400' USING message = 'Invalid referral ID provided';
        WHEN others THEN
            RAISE LOG 'Unexpected error in signup: %', SQLERRM;
            RAISE sqlstate 'PT500' USING message = 'Internal server error during signup';
    END;

    confirmation_token := substr(md5(RANDOM()::TEXT || CLOCK_TIMESTAMP()::TEXT), 1, 32);

    INSERT INTO public.confirmation_inner(token, user_id, exp, used)
    VALUES (confirmation_token, user_id, NOW() + INTERVAL '1 day', false);


    PERFORM vinn.send_email(
        email,
        'Vproxy email confirmation',
        common.confirm_email_html(
          username,
          format(
            'https://vproxy.cc/en/confirm-email?confirmation_token=%s',
            confirmation_token))
    );

    BEGIN
        PERFORM common.send_signup_notification(user_id, username, 'web');
    EXCEPTION WHEN OTHERS THEN
        RAISE LOG 'Failed to send signup notification: %', SQLERRM;
    END;

    RETURN user_id;
END;
$$;


ALTER FUNCTION vgate.signup(email text, username text, password text, referral_id text, admin_referral_code text) OWNER TO postgres;

--
-- Name: telegram_code_signin(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.telegram_code_signin(p_code text) RETURNS vgate."text/plain"
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE 
    v_user_id TEXT;
    v_role TEXT;
    v_token TEXT;
BEGIN
    -- Check if the code is valid
    SELECT user_id, role INTO v_user_id, v_role
    FROM legacy.all_user 
    WHERE tgcode = p_code AND tgcode_expires::BIGINT > EXTRACT(EPOCH FROM NOW())
    LIMIT 1;

    RAISE LOG 'vgate.telegram_code_signin: v_user_id: %, v_role: %', v_user_id, v_role;

    -- If no user found, return an error message
    IF v_user_id IS NULL THEN
        RAISE sqlstate 'PT409' USING message = 'Invalid or expired code';
    END IF;

    -- Invalidate the code after successful authentication
    UPDATE legacy.all_user 
    SET tgcode = NULL, tgcode_expires = NULL 
    WHERE user_id = v_user_id;

    RAISE LOG 'vgate.telegram_code_signin: code is now null';

    -- Generate JWT token
    SELECT sign(row_to_json(r), common.get_jwt_secret()) 
    INTO v_token
    FROM (SELECT v_user_id AS sub, v_role AS role) r;

    RAISE LOG 'vgate.telegram_code_signin: v_token: %', v_token;

    -- Return the token
    RETURN v_token;
END;
$$;


ALTER FUNCTION vgate.telegram_code_signin(p_code text) OWNER TO postgres;

--
-- Name: telegram_stars_payment(jsonb); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.telegram_stars_payment(payment_data jsonb) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
    order_id TEXT;
    stars_amount INTEGER;
    user_id TEXT;
    amount_gb INTEGER;
    pool_type TEXT;
    promocode TEXT;
    amount_usd NUMERIC;
    exchange_rate NUMERIC;
BEGIN
    -- Extract payment data
    order_id := payment_data->>'order_id';
    stars_amount := (payment_data->>'stars_amount')::INTEGER;
    user_id := payment_data->>'user_id';
    amount_gb := (payment_data->>'amount_gb')::INTEGER;
    pool_type := payment_data->>'pool_type';
    promocode := payment_data->>'promocode';
    
    -- Validate required fields
    IF order_id IS NULL OR user_id IS NULL OR amount_gb IS NULL OR pool_type IS NULL THEN
        RAISE EXCEPTION 'Missing required payment data';
    END IF;
    
    -- Get exchange rate
    exchange_rate := telegram_stars.get_exchange_rate();
    amount_usd := stars_amount::NUMERIC / exchange_rate;
    
    -- Log the payment in legacy.payment table
    INSERT INTO legacy.payment (
        user_id,
        paid,
        order_id,
        amount_gb,
        service,
        source,
        date
    ) VALUES (
        user_id,
        amount_usd,
        order_id,
        amount_gb,
        'telegram_stars',
        'bot',
        to_char(NOW(), 'YYYY-MM-DD HH24:MI:SS')
    );
    
    -- Add traffic to user's balance using the existing function
    -- Note: We need to call the function that adds traffic to user balance
    -- This might be a different function name in your system
    -- For now, we'll log the action and let the existing system handle it
    RAISE NOTICE 'Adding traffic: user_id=%, amount_gb=%, pool_type=%, promocode=%', 
        user_id, amount_gb, pool_type, promocode;
    
    -- Log success
    RAISE NOTICE 'Telegram Stars payment processed: order_id=%, user_id=%, amount_gb=%, stars_amount=%', 
        order_id, user_id, amount_gb, stars_amount;
        
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'Failed to process Telegram Stars payment: %', SQLERRM;
END $$;


ALTER FUNCTION vgate.telegram_stars_payment(payment_data jsonb) OWNER TO postgres;

--
-- Name: telegram_stars_payment_2(jsonb); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.telegram_stars_payment_2(jsonb) RETURNS void
    LANGUAGE plpgsql
    AS $_$
DECLARE
    payment_data JSONB := $1;
    order_id TEXT;
    stars_amount INTEGER;
    user_id TEXT;
    _user_id TEXT;
    amount_gb INTEGER;
    pool_type TEXT;
    promocode TEXT;
    amount_usd NUMERIC;
    exchange_rate NUMERIC;
BEGIN
    -- Extract payment data
    order_id := payment_data->>'order_id';
    stars_amount := (payment_data->>'stars_amount')::INTEGER;
    user_id := payment_data->>'user_id';
    _user_id := user_id;
    amount_gb := (payment_data->>'amount_gb')::INTEGER;
    pool_type := payment_data->>'pool_type';
    promocode := payment_data->>'promocode';
    
    -- Validate required fields
    IF order_id IS NULL OR user_id IS NULL OR amount_gb IS NULL OR pool_type IS NULL THEN
        RAISE EXCEPTION 'Missing required payment data';
    END IF;
    
    -- Get exchange rate
    exchange_rate := telegram_stars.get_exchange_rate();
    amount_usd := stars_amount::NUMERIC / exchange_rate;
    
    -- Log the payment in legacy.payment table
    INSERT INTO legacy.payment (
        user_id,
        subuser_id,
        paid,
        order_id,
        amount_gb,
        service,
        source,
        date
    ) VALUES (
        user_id,
        (SELECT sub_id FROM legacy.user u WHERE u.pool::TEXT = pool_type AND u.user_id = _user_id),
        amount_usd,
        order_id,
        amount_gb,
        'telegram_stars',
        'bot',
        to_char(NOW(), 'YYYY-MM-DD HH24:MI:SS')
    );
    
    -- Add traffic to user's balance using the existing function
    -- Note: We need to call the function that adds traffic to user balance
    -- This might be a different function name in your system
    -- For now, we'll log the action and let the existing system handle it
    RAISE NOTICE 'Adding traffic: user_id=%, amount_gb=%, pool_type=%, promocode=%', 
        user_id, amount_gb, pool_type, promocode;

    PERFORM common.process_successful_payment(order_id);
    
    -- Log success
    RAISE NOTICE 'Telegram Stars payment processed: order_id=%, user_id=%, amount_gb=%, stars_amount=%', 
        order_id, user_id, amount_gb, stars_amount;
        
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'Failed to process Telegram Stars payment: %', SQLERRM;
END $_$;


ALTER FUNCTION vgate.telegram_stars_payment_2(jsonb) OWNER TO postgres;

--
-- Name: test(); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.test() RETURNS text
    LANGUAGE plpgsql
    AS $$
BEGIN
    RETURN current_setting('request.jwt.claims');
END;
$$;


ALTER FUNCTION vgate.test() OWNER TO postgres;

--
-- Name: test_array(text[]); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.test_array("array" text[]) RETURNS text[]
    LANGUAGE plpgsql
    AS $$
BEGIN
  RETURN "array";
END $$;


ALTER FUNCTION vgate.test_array("array" text[]) OWNER TO postgres;

--
-- Name: test_bool(); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.test_bool() RETURNS boolean
    LANGUAGE plpgsql
    AS $$
BEGIN
  RETURN TRUE;
END
$$;


ALTER FUNCTION vgate.test_bool() OWNER TO postgres;

--
-- Name: test_rpc(); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.test_rpc() RETURNS jsonb
    LANGUAGE plpgsql
    AS $$
BEGIN
  RETURN jsonb_build_object('status','ok');
END;
$$;


ALTER FUNCTION vgate.test_rpc() OWNER TO postgres;

--
-- Name: tg.is_admin(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate."tg.is_admin"(user_id text) RETURNS json
    LANGUAGE plpgsql
    AS $$
DECLARE
    "is_admin" BOOL;
BEGIN
    "is_admin" := EXISTS (
        SELECT 1
        FROM "legacy"."all_user"
        WHERE "telegram_id" = "tg.is_admin"."user_id"
        AND "role" = 'vgate_admin'
    );

    RETURN json_build_object(
        'is_admin', "is_admin"
    );
END
$$;


ALTER FUNCTION vgate."tg.is_admin"(user_id text) OWNER TO postgres;

--
-- Name: tg.is_support(text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate."tg.is_support"(user_id text) RETURNS json
    LANGUAGE plpgsql
    AS $$
DECLARE
    "is_support" BOOL;
BEGIN
    "is_support" := EXISTS (
        SELECT 1
        FROM "legacy"."all_user"
        WHERE "telegram_id" = "tg.is_support"."user_id"
        AND "role" = 'vgate_support' OR "role" = 'vgate_admin'
    );

    RETURN json_build_object(
        'is_support', "is_support"
    );
END
$$;


ALTER FUNCTION vgate."tg.is_support"(user_id text) OWNER TO postgres;

--
-- Name: translate(common.sha256, text, text, vgate.language, vgate.language); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.translate(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language) RETURNS vgate."text/plain"
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    lang_id INTEGER;
    _country_id INTEGER;
    _content TEXT;
BEGIN
    INSERT INTO vgate.text (id, label, actualized_at)
    VALUES (hash, label, now())
    ON CONFLICT (id) DO NOTHING;

    IF NOT FOUND THEN
        SELECT language_id, country_id FROM common.get_language_id(lable_lang_code) INTO lang_id, _country_id;

        INSERT INTO vgate.translation (text_id, language_id, country_id, content)
        VALUES (hash, lang_id, _country_id, translate.content)
        ON CONFLICT (text_id, language_id, country_id) DO UPDATE SET
            content = EXCLUDED.content,
            updated_at = now();
    ELSE 
        UPDATE vgate.text SET actualized_at = now() WHERE id = hash;
    END IF;

    SELECT language_id, country_id FROM common.get_language_id(lang_code) INTO lang_id, _country_id;

    SELECT translation.content 
    FROM vgate.translation 
    WHERE text_id = hash
        AND language_id = lang_id
        AND country_id = _country_id 
    INTO _content;

    IF FOUND THEN
        RETURN _content;
    END IF;

    -- Look for existing translations with same source content and target language
    SELECT t_target.content 
    FROM vgate.translation t_source
    JOIN vgate.translation t_target ON t_source.text_id = t_target.text_id
    WHERE t_source.content = translate.content  -- same source content
        AND t_source.language_id = (SELECT language_id FROM common.get_language_id(lable_lang_code))
        AND t_source.country_id = (SELECT country_id FROM common.get_language_id(lable_lang_code))
        AND t_target.language_id = lang_id           -- translated to target language 
        AND t_target.country_id = _country_id        -- in target country
        AND t_source.text_id != hash                 -- different text (not the one we're looking for)
    LIMIT 1
    INTO _content;

    IF FOUND THEN
        -- Found a reusable translation, store it for this text_id
        INSERT INTO vgate.translation (text_id, language_id, country_id, content)
        VALUES (hash, lang_id, _country_id, _content)
        ON CONFLICT (text_id, language_id, country_id) DO UPDATE SET
            content = EXCLUDED.content,
            updated_at = now();
        
        RETURN _content;
    END IF;

    -- If still no translation found, return original content
    RETURN translate.content;
END;
$$;


ALTER FUNCTION vgate.translate(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language) OWNER TO postgres;

--
-- Name: translation_dictionary(vgate.language); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.translation_dictionary(lang_code vgate.language) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    lang_id INTEGER;
    _country_id INTEGER;
    result jsonb;
BEGIN
    SELECT language_id, country_id FROM common.get_language_id(lang_code) INTO lang_id, _country_id;

    SELECT jsonb_object_agg(t.text_id, t.content)
    FROM vgate.translation t
    WHERE t.language_id = lang_id
        AND t.country_id = _country_id
    INTO result;

    RETURN COALESCE(result, '{}'::jsonb);
END;
$$;


ALTER FUNCTION vgate.translation_dictionary(lang_code vgate.language) OWNER TO postgres;

--
-- Name: update_blog_article(bigint, text, text, vgate.language, boolean); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.update_blog_article(article_id bigint, title text, content text, language vgate.language, hidden boolean) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    current_user_id text;
    updated_rows integer;
BEGIN
    -- Get current user ID
    current_user_id := common.current_user_id();
    
    -- Update article
    UPDATE legacy.blog_article
    SET 
        title      = CASE WHEN update_blog_article.title    IS NOT NULL THEN trim(update_blog_article.title)   ELSE legacy.blog_article.title END,
        content    = CASE WHEN update_blog_article.content  IS NOT NULL THEN trim(update_blog_article.content) ELSE legacy.blog_article.content END,
        language   = CASE WHEN update_blog_article.language IS NOT NULL THEN update_blog_article.language      ELSE legacy.blog_article.language END,
        hidden     = CASE WHEN update_blog_article.hidden   IS NOT NULL THEN update_blog_article.hidden        ELSE legacy.blog_article.hidden END,
        updated_at = now()
    WHERE id = article_id AND user_id = current_user_id;
    
    GET DIAGNOSTICS updated_rows = ROW_COUNT;
    
    -- Check if article was updated
    IF updated_rows = 0 THEN
        RAISE sqlstate 'PT404' USING
            message = 'Article not found or no changes made';
    END IF;
    
    -- Return success
    RETURN;
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN sqlstate 'PT400' THEN
        RAISE;
    WHEN sqlstate 'PT401' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE warning 'Error updating blog article: %', SQLERRM;
        RAISE sqlstate 'PT500' USING
            message = 'Unexpected server error';
END;
$$;


ALTER FUNCTION vgate.update_blog_article(article_id bigint, title text, content text, language vgate.language, hidden boolean) OWNER TO postgres;

--
-- Name: update_subuser(text, integer, jsonb, integer); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.update_subuser(token text, subuser_id integer, sticky_range jsonb DEFAULT NULL::jsonb, threads integer DEFAULT NULL::integer) RETURNS json
    LANGUAGE plpgsql
    AS $$
DECLARE
    r_id INT;
    data jsonb;
BEGIN
    r_id := (SELECT id FROM resellers WHERE api_key = token);
    IF r_id IS NULL THEN
        RAISE sqlstate 'PT401' USING
            message = 'Unauthorized';
    END IF;

    IF NOT EXISTS (
            SELECT 1 
            FROM reseller_subusers
            WHERE id = subuser_id AND reseller_id = r_id
        ) THEN
        RAISE sqlstate 'PT404' USING
            message = 'Subuser not found',
            detail = 'No subuser associated with the provided id';
    END IF;

    data := json_build_object(
        'subuser_id', subuser_id
    );

    RETURN dataimpulse.update_subuser(
        subuser_id,
        'r_' || r_id,
        sticky_range,
        threads
    );
END
$$;


ALTER FUNCTION vgate.update_subuser(token text, subuser_id integer, sticky_range jsonb, threads integer) OWNER TO postgres;

--
-- Name: update_translation_usage(jsonb); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.update_translation_usage(usage_data jsonb) RETURNS integer
    LANGUAGE sql SECURITY DEFINER
    AS $$
WITH incoming AS (
  SELECT v.id::sha256 as id, v.value::timestamp AS ts
  FROM jsonb_each_text(usage_data) AS v(id, value)
),
updated AS (
  UPDATE vgate.text t
  SET actualized_at = i.ts
  FROM incoming i
  WHERE t.id = i.id
  returning i.id
),
total AS (
  SELECT count(*) AS total FROM incoming
),
matched AS (
  SELECT count(*) AS matched FROM updated
)
SELECT total.total - matched.matched FROM total, matched;
$$;


ALTER FUNCTION vgate.update_translation_usage(usage_data jsonb) OWNER TO postgres;

--
-- Name: upload_blog_article_image(bigint, text); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.upload_blog_article_image(article_id bigint, image_data text) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    current_user_id text;
    image_bytes bytea;
BEGIN
    -- Get current user ID
    current_user_id := common.current_user_id();
    
    -- Verify the user owns the article
    IF NOT EXISTS (
        SELECT 1 FROM legacy.blog_article 
        WHERE id = article_id AND user_id = current_user_id
    ) THEN
        RAISE sqlstate 'PT403' USING
            message = 'Access denied: you can only upload images to your own articles';
    END IF;
    
    -- Decode base64 image data
    BEGIN
        image_bytes := decode(image_data, 'base64');
    EXCEPTION WHEN OTHERS THEN
        RAISE sqlstate 'PT400' USING
            message = 'Invalid base64 image data';
    END;
    
    -- Update the article with image data
    UPDATE legacy.blog_article
    SET 
        image_blob = image_bytes,
        updated_at = NOW()
    WHERE id = article_id;
    
    -- Check if the update affected any rows
    IF NOT FOUND THEN
        RAISE sqlstate 'PT404' USING
            message = 'Article not found';
    END IF;
    
    RETURN;
EXCEPTION
    WHEN sqlstate 'PT403' THEN
        RAISE;
    WHEN sqlstate 'PT400' THEN
        RAISE;
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE warning 'Error uploading blog article image: %', SQLERRM;
        RAISE sqlstate 'PT500' USING
            message = 'Unexpected server error';
END;
$$;


ALTER FUNCTION vgate.upload_blog_article_image(article_id bigint, image_data text) OWNER TO postgres;

--
-- Name: usd_to_kop(numeric); Type: FUNCTION; Schema: vgate; Owner: postgres
--

CREATE FUNCTION vgate.usd_to_kop(price numeric) RETURNS integer
    LANGUAGE plpgsql
    AS $$
BEGIN
    RETURN (TRUNC(price, 2) * current_setting('app.ruble_to_dollar_exchange_rate')::NUMERIC * 100)::INT;
END 
$$;


ALTER FUNCTION vgate.usd_to_kop(price numeric) OWNER TO postgres;

SET default_tablespace = '';

SET default_table_access_method = heap;

--
-- Name: actual_username; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.actual_username (
    username text
);


ALTER TABLE vgate.actual_username OWNER TO postgres;

--
-- Name: bundle; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.bundle (
    id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
    user_id uuid,
    proxy_password bytea NOT NULL,
    ip_whitelist inet[] DEFAULT '{}'::inet[] NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.bundle OWNER TO postgres;

--
-- Name: bundle_proxy; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.bundle_proxy (
    bundle_id uuid NOT NULL,
    proxy_id uuid NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.bundle_proxy OWNER TO postgres;

--
-- Name: check_headers; Type: VIEW; Schema: vgate; Owner: postgres
--

CREATE VIEW vgate.check_headers AS
 SELECT (current_setting('request.headers'::text, true))::json AS headers;


ALTER TABLE vgate.check_headers OWNER TO postgres;

--
-- Name: dataimpulse_subuser; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.dataimpulse_subuser (
    bundle_id uuid,
    owner integer NOT NULL,
    subuser_id integer NOT NULL,
    frozen_balance integer DEFAULT 0 NOT NULL,
    provided_balance numeric DEFAULT 0 NOT NULL,
    pool common.dataimpulsepool NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.dataimpulse_subuser OWNER TO postgres;

--
-- Name: promocode; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.promocode (
    id integer NOT NULL,
    code character varying NOT NULL,
    once_per_user boolean DEFAULT true NOT NULL,
    for_any boolean DEFAULT true NOT NULL,
    max_use_number integer NOT NULL,
    expires_at timestamp without time zone
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.promocode OWNER TO postgres;

--
-- Name: discount_promocode; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.discount_promocode (
    type common.discountype NOT NULL,
    discount numeric NOT NULL
)
INHERITS (vgate.promocode, common.updated_at, common.created_at);


ALTER TABLE vgate.discount_promocode OWNER TO postgres;

--
-- Name: freekassa_nonce; Type: SEQUENCE; Schema: vgate; Owner: postgres
--

CREATE SEQUENCE vgate.freekassa_nonce
    START WITH 2
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE vgate.freekassa_nonce OWNER TO postgres;

--
-- Name: general_state; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.general_state (
    referral_multiplier double precision NOT NULL,
    default_language integer DEFAULT 41 NOT NULL,
    default_country integer DEFAULT 233 NOT NULL,
    dataimpulse_jwt text
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.general_state OWNER TO postgres;

--
-- Name: invoice; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.invoice (
    id text NOT NULL,
    amount numeric NOT NULL,
    user_id uuid NOT NULL,
    payment_system_id integer NOT NULL,
    tariff_id integer,
    general_state jsonb NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.invoice OWNER TO postgres;

--
-- Name: legacy_all_user; Type: VIEW; Schema: vgate; Owner: postgres
--

CREATE VIEW vgate.legacy_all_user AS
 SELECT all_user.created_at,
    all_user.updated_at,
    all_user.user_id,
    all_user.lang,
    all_user.invited_by,
    (0)::bigint AS ref_balance,
    all_user.pers_percent,
    all_user.reg_date,
    all_user.username,
    all_user.email,
    all_user.password,
    all_user.role_id,
    all_user.confirmed,
    all_user.tgcode,
    all_user.tgcode_expires,
    all_user.ref_balance_usd
   FROM legacy.all_user
  WHERE ((NOT common.is_provider()) OR (all_user.user_id = common.current_user_id()));


ALTER TABLE vgate.legacy_all_user OWNER TO postgres;

--
-- Name: legacy_profile; Type: VIEW; Schema: vgate; Owner: postgres
--

CREATE VIEW vgate.legacy_profile AS
 WITH check_role AS (
         SELECT common.is_provider() AS is_provider
        )
 SELECT au.created_at,
    au.updated_at,
    au.user_id,
    COALESCE(au.lang, 'rus'::text) AS lang,
    au.invited_by,
    (0)::bigint AS ref_balance,
    ((((au.pers_percent)::integer * 100))::text || '%'::text) AS pers_percent,
    au.reg_date,
    au.username,
    au.email,
    au.password,
    au.role_id,
    au.confirmed,
    au.tgcode,
    au.tgcode_expires,
    COALESCE(au.ref_balance_usd, (0)::double precision) AS ref_balance_usd,
    COALESCE(( SELECT "user".buy_num
           FROM legacy."user"
          WHERE ("user".user_id = au.user_id)
         LIMIT 1), (0)::bigint) AS purchase_count,
    ( SELECT json_build_object('balance', data.balance, 'balance_format', data.balance_format, 'password', data.password) AS json_build_object
           FROM (legacy."user" u
             JOIN LATERAL json_to_record(dataimpulse.get_subuser((u.sub_id)::integer)) data(id bigint, balance bigint, balance_format text, password text) ON ((data.id = u.sub_id)))
          WHERE ((u.user_id = au.user_id) AND (u.pool = 'datacenter'::common.dataimpulsepool))) AS datacenter,
    ( SELECT json_build_object('balance', data.balance, 'balance_format', data.balance_format, 'password', data.password) AS json_build_object
           FROM (legacy."user" u
             JOIN LATERAL json_to_record(dataimpulse.get_subuser((u.sub_id)::integer)) data(id bigint, balance bigint, balance_format text, password text) ON ((data.id = u.sub_id)))
          WHERE ((u.user_id = au.user_id) AND (u.pool = 'residential'::common.dataimpulsepool))) AS residential,
    ( SELECT json_build_object('balance', data.balance, 'balance_format', data.balance_format, 'password', data.password) AS json_build_object
           FROM (legacy."user" u
             JOIN LATERAL json_to_record(dataimpulse.get_subuser((u.sub_id)::integer)) data(id bigint, balance bigint, balance_format text, password text) ON ((data.id = u.sub_id)))
          WHERE ((u.user_id = au.user_id) AND (u.pool = 'residential_premium'::common.dataimpulsepool))) AS residential_premium,
    ( SELECT json_build_object('balance', data.balance, 'balance_format', data.balance_format, 'password', data.password) AS json_build_object
           FROM (legacy."user" u
             JOIN LATERAL json_to_record(dataimpulse.get_subuser((u.sub_id)::integer)) data(id bigint, balance bigint, balance_format text, password text) ON ((data.id = u.sub_id)))
          WHERE ((u.user_id = au.user_id) AND (u.pool = 'mobile'::common.dataimpulsepool))) AS mobile,
    ( SELECT json_object_agg((u.pool)::text, json_build_object('balance', data.balance, 'balance_format', data.balance_format, 'password', data.password)) AS json_object_agg
           FROM (legacy."user" u
             JOIN LATERAL json_to_record(dataimpulse.get_subuser((u.sub_id)::integer)) data(id bigint, balance bigint, balance_format text, password text) ON ((data.id = u.sub_id)))
          WHERE (u.user_id = au.user_id)) AS pools,
    COALESCE(( SELECT sum(p.amount_gb) AS sum
           FROM (legacy."user" u
             JOIN legacy.payment p ON ((p.user_id = u.user_id)))
          WHERE (u.user_id = au.user_id)), ((0)::bigint)::numeric) AS purchase_sum_gb
   FROM legacy.all_user au,
    check_role
  WHERE ((check_role.is_provider AND (au.user_id = common.get_header('X-Tg-Id'::text))) OR (au.email = common.get_header('X-Email'::text)) OR (au.username = common.get_header('X-Username'::text)) OR ((NOT check_role.is_provider) AND (au.user_id = common.current_user_id())));


ALTER TABLE vgate.legacy_profile OWNER TO postgres;

--
-- Name: legacy_profile_slim; Type: VIEW; Schema: vgate; Owner: postgres
--

CREATE VIEW vgate.legacy_profile_slim AS
 WITH check_role AS (
         SELECT common.is_provider() AS is_provider
        )
 SELECT au.created_at,
    au.updated_at,
    au.user_id,
    COALESCE(au.lang, 'rus'::text) AS lang,
    au.invited_by,
    au.pers_percent,
    au.reg_date,
    au.username,
    au.email,
    au.password,
    au.role_id,
    au.confirmed,
    au.tgcode,
    au.tgcode_expires,
    COALESCE(au.ref_balance_usd, (0)::double precision) AS ref_balance_usd,
    COALESCE(( SELECT "user".buy_num
           FROM legacy."user"
          WHERE ("user".user_id = au.user_id)
         LIMIT 1), (0)::bigint) AS purchase_count,
    ( SELECT json_object_agg((u.pool)::text, '{}'::json) AS json_object_agg
           FROM legacy."user" u
          WHERE (u.user_id = au.user_id)) AS pools
   FROM legacy.all_user au,
    check_role
  WHERE ((check_role.is_provider AND (au.user_id = common.get_header('X-Tg-Id'::text))) OR ((NOT check_role.is_provider) AND (au.user_id = common.current_user_id())));


ALTER TABLE vgate.legacy_profile_slim OWNER TO postgres;

--
-- Name: legacy_referal_info; Type: VIEW; Schema: vgate; Owner: postgres
--

CREATE VIEW vgate.legacy_referal_info AS
 WITH check_role AS (
         SELECT common.is_provider() AS is_provider
        )
 SELECT (a.ref_balance_usd)::text AS balance,
    ((((COALESCE(a.pers_percent, ( SELECT system.value
           FROM legacy.system
          WHERE (system.key = 'ref_percent'::text))))::numeric * 100.0))::integer)::text AS percent,
    jsonb_build_object('telegram', ('https://t.me/V_Proxy_bot?start='::text || a.user_id), 'website', ('https://vproxy.cc?referry='::text || a.user_id)) AS links,
    (( SELECT count(*) AS count
           FROM legacy.all_user u
          WHERE (u.invited_by = a.user_id)))::text AS ref_num
   FROM legacy.all_user a,
    check_role
  WHERE ((check_role.is_provider AND (a.user_id = common.get_header('X-Tg-Id'::text))) OR ((NOT check_role.is_provider) AND (a.user_id = common.current_user_id())));


ALTER TABLE vgate.legacy_referal_info OWNER TO postgres;

--
-- Name: payment; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.payment (
    id text NOT NULL,
    additional_data jsonb DEFAULT '{}'::jsonb NOT NULL,
    user_id uuid NOT NULL,
    currency_id integer NOT NULL,
    payment_system_id integer NOT NULL,
    amount numeric NOT NULL,
    amount_gb integer NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.payment OWNER TO postgres;

--
-- Name: payment_system; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.payment_system (
    id integer NOT NULL,
    name character varying NOT NULL,
    active boolean DEFAULT false NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.payment_system OWNER TO postgres;

--
-- Name: payment_system_id_seq; Type: SEQUENCE; Schema: vgate; Owner: postgres
--

CREATE SEQUENCE vgate.payment_system_id_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE vgate.payment_system_id_seq OWNER TO postgres;

--
-- Name: payment_system_id_seq; Type: SEQUENCE OWNED BY; Schema: vgate; Owner: postgres
--

ALTER SEQUENCE vgate.payment_system_id_seq OWNED BY vgate.payment_system.id;


--
-- Name: payment_systems; Type: VIEW; Schema: vgate; Owner: postgres
--

CREATE VIEW vgate.payment_systems AS
 SELECT available_pay.name,
    available_pay.description
   FROM legacy.available_pay
  WHERE (available_pay.is_available = 'true'::text)
  ORDER BY available_pay."order";


ALTER TABLE vgate.payment_systems OWNER TO postgres;

--
-- Name: promocode_for_user; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.promocode_for_user (
    code_id integer NOT NULL,
    user_id uuid NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.promocode_for_user OWNER TO postgres;

--
-- Name: promocode_id_seq; Type: SEQUENCE; Schema: vgate; Owner: postgres
--

CREATE SEQUENCE vgate.promocode_id_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE vgate.promocode_id_seq OWNER TO postgres;

--
-- Name: promocode_id_seq; Type: SEQUENCE OWNED BY; Schema: vgate; Owner: postgres
--

ALTER SEQUENCE vgate.promocode_id_seq OWNED BY vgate.promocode.id;


--
-- Name: proxy; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.proxy (
    id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
    login character varying NOT NULL,
    host common.host NOT NULL,
    port common.port NOT NULL,
    provider common.provider
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.proxy OWNER TO postgres;

--
-- Name: referral_balance_transaction; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.referral_balance_transaction (
    id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
    user_id uuid NOT NULL,
    amount numeric(12,2) NOT NULL,
    reason common.referralreasontype NOT NULL,
    balance_before numeric(12,2) NOT NULL,
    admin_id uuid,
    referral_multiplier double precision,
    related_payment_id text,
    CONSTRAINT check_referral_balance_transaction CHECK ((((reason = 'AdminAction'::common.referralreasontype) AND (admin_id IS NOT NULL) AND (related_payment_id IS NULL) AND (referral_multiplier IS NULL)) OR ((reason = 'ReferalPurchase'::common.referralreasontype) AND (admin_id IS NULL) AND (related_payment_id IS NOT NULL) AND (referral_multiplier IS NOT NULL)) OR ((reason = 'OwnPurchase'::common.referralreasontype) AND (admin_id IS NULL) AND (related_payment_id IS NOT NULL) AND (referral_multiplier IS NULL))))
)
INHERITS (common.created_at, common.immutable);


ALTER TABLE vgate.referral_balance_transaction OWNER TO postgres;

--
-- Name: reseller_profile; Type: VIEW; Schema: vgate; Owner: postgres
--

CREATE VIEW vgate.reseller_profile AS
 WITH check_role AS (
         SELECT common.is_provider() AS is_provider
        )
 SELECT r.id,
    r.user_id,
    r.api_key,
    r.traffic_amount,
    reseller_inner.bytes_to_gb(r.traffic_amount) AS traffic_amount_gb,
    (reseller_inner.bytes_to_gb(r.traffic_amount) || ' GB'::text) AS traffic_formatted,
    r.created_at,
    r.updated_at,
    COALESCE(( SELECT count(*) AS count
           FROM reseller_inner.reseller_subusers rs
          WHERE (rs.reseller_id = r.id)), (0)::bigint) AS subusers_count
   FROM reseller_inner.resellers r,
    check_role
  WHERE ((check_role.is_provider AND (r.user_id = common.get_header('X-Tg-Id'::text))) OR ((NOT check_role.is_provider) AND (r.user_id = common.current_user_id())));


ALTER TABLE vgate.reseller_profile OWNER TO postgres;

--
-- Name: supported_language; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.supported_language (
    language_id integer NOT NULL,
    country_id integer NOT NULL
)
INHERITS (common.created_at);


ALTER TABLE vgate.supported_language OWNER TO postgres;

--
-- Name: tariff; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.tariff (
    id integer NOT NULL,
    tariff_info_id integer NOT NULL,
    price money NOT NULL,
    currency_id integer NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.tariff OWNER TO postgres;

--
-- Name: tariff_id_seq; Type: SEQUENCE; Schema: vgate; Owner: postgres
--

CREATE SEQUENCE vgate.tariff_id_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE vgate.tariff_id_seq OWNER TO postgres;

--
-- Name: tariff_id_seq; Type: SEQUENCE OWNED BY; Schema: vgate; Owner: postgres
--

ALTER SEQUENCE vgate.tariff_id_seq OWNED BY vgate.tariff.id;


--
-- Name: tariff_info; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.tariff_info (
    id integer NOT NULL,
    amount_gb integer NOT NULL,
    type text NOT NULL,
    data jsonb DEFAULT '{}'::jsonb NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.tariff_info OWNER TO postgres;

--
-- Name: tariff_info_id_seq; Type: SEQUENCE; Schema: vgate; Owner: postgres
--

CREATE SEQUENCE vgate.tariff_info_id_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE vgate.tariff_info_id_seq OWNER TO postgres;

--
-- Name: tariff_info_id_seq; Type: SEQUENCE OWNED BY; Schema: vgate; Owner: postgres
--

ALTER SEQUENCE vgate.tariff_info_id_seq OWNED BY vgate.tariff_info.id;


--
-- Name: text; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.text (
    id common.sha256 NOT NULL,
    actualized_at timestamp with time zone DEFAULT now() NOT NULL,
    label text NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.text OWNER TO postgres;

--
-- Name: COLUMN text.actualized_at; Type: COMMENT; Schema: vgate; Owner: postgres
--

COMMENT ON COLUMN vgate.text.actualized_at IS 'Time when, last time, one of front demonstrated that it need this record. Based on this column we can delete obsolete records.';


--
-- Name: tg_user; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.tg_user (
    user_id uuid NOT NULL,
    username character varying,
    surname character varying,
    first_name character varying NOT NULL,
    tg_id bigint NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.tg_user OWNER TO postgres;

--
-- Name: translation; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.translation (
    id integer NOT NULL,
    text_id common.sha256 NOT NULL,
    language_id integer NOT NULL,
    country_id integer NOT NULL,
    content text NOT NULL,
    type vgate."i18n.translation_type" DEFAULT 'source'::vgate."i18n.translation_type" NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.translation OWNER TO postgres;

--
-- Name: COLUMN translation.type; Type: COMMENT; Schema: vgate; Owner: postgres
--

COMMENT ON COLUMN vgate.translation.type IS 'Specifies the origin of a translation:
- source: original text provided directly by the project
- auto: translation generated automatically (e.g., by AI or a translation service)
- manual: translation added or edited by a human (e.g., developer or project contributor)';


--
-- Name: translation_id_seq; Type: SEQUENCE; Schema: vgate; Owner: postgres
--

CREATE SEQUENCE vgate.translation_id_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE vgate.translation_id_seq OWNER TO postgres;

--
-- Name: translation_id_seq; Type: SEQUENCE OWNED BY; Schema: vgate; Owner: postgres
--

ALTER SEQUENCE vgate.translation_id_seq OWNED BY vgate.translation.id;


--
-- Name: used_promocode; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.used_promocode (
    code_id integer NOT NULL,
    user_id uuid NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.used_promocode OWNER TO postgres;

--
-- Name: user; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate."user" (
    id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
    referral_id uuid,
    referral_balance numeric DEFAULT 0 NOT NULL,
    language_id integer DEFAULT 41 NOT NULL,
    country_id integer DEFAULT 233 NOT NULL,
    rolname text NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate."user" OWNER TO postgres;

--
-- Name: user_used_promo; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.user_used_promo (
    user_id uuid NOT NULL,
    promo_id character varying NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.user_used_promo OWNER TO postgres;

--
-- Name: web_user; Type: TABLE; Schema: vgate; Owner: postgres
--

CREATE TABLE vgate.web_user (
    user_id uuid NOT NULL,
    password_encoded character varying NOT NULL,
    email character varying,
    username character varying NOT NULL
)
INHERITS (common.created_at, common.updated_at);


ALTER TABLE vgate.web_user OWNER TO postgres;

--
-- Name: bundle created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.bundle ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: bundle updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.bundle ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: bundle_proxy created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.bundle_proxy ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: bundle_proxy updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.bundle_proxy ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: dataimpulse_subuser created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.dataimpulse_subuser ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: dataimpulse_subuser updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.dataimpulse_subuser ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: discount_promocode created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.discount_promocode ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: discount_promocode updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.discount_promocode ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: discount_promocode id; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.discount_promocode ALTER COLUMN id SET DEFAULT nextval('vgate.promocode_id_seq'::regclass);


--
-- Name: discount_promocode once_per_user; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.discount_promocode ALTER COLUMN once_per_user SET DEFAULT true;


--
-- Name: discount_promocode for_any; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.discount_promocode ALTER COLUMN for_any SET DEFAULT true;


--
-- Name: general_state created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.general_state ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: general_state updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.general_state ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: invoice created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.invoice ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: invoice updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.invoice ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: payment created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.payment ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: payment updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.payment ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: payment_system created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.payment_system ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: payment_system updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.payment_system ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: payment_system id; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.payment_system ALTER COLUMN id SET DEFAULT nextval('vgate.payment_system_id_seq'::regclass);


--
-- Name: promocode created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.promocode ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: promocode updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.promocode ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: promocode id; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.promocode ALTER COLUMN id SET DEFAULT nextval('vgate.promocode_id_seq'::regclass);


--
-- Name: promocode_for_user created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.promocode_for_user ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: promocode_for_user updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.promocode_for_user ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: proxy created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.proxy ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: proxy updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.proxy ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: referral_balance_transaction created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.referral_balance_transaction ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: supported_language created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.supported_language ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: tariff created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tariff ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: tariff updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tariff ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: tariff id; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tariff ALTER COLUMN id SET DEFAULT nextval('vgate.tariff_id_seq'::regclass);


--
-- Name: tariff_info created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tariff_info ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: tariff_info updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tariff_info ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: tariff_info id; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tariff_info ALTER COLUMN id SET DEFAULT nextval('vgate.tariff_info_id_seq'::regclass);


--
-- Name: text created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.text ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: text updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.text ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: tg_user created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tg_user ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: tg_user updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tg_user ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: translation created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.translation ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: translation updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.translation ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: translation id; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.translation ALTER COLUMN id SET DEFAULT nextval('vgate.translation_id_seq'::regclass);


--
-- Name: used_promocode created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.used_promocode ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: used_promocode updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.used_promocode ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: user created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate."user" ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: user updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate."user" ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: user_used_promo created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.user_used_promo ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: user_used_promo updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.user_used_promo ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: web_user created_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.web_user ALTER COLUMN created_at SET DEFAULT now();


--
-- Name: web_user updated_at; Type: DEFAULT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.web_user ALTER COLUMN updated_at SET DEFAULT now();


--
-- Name: bundle bundle_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.bundle
    ADD CONSTRAINT bundle_pkey PRIMARY KEY (id);


--
-- Name: bundle_proxy bundle_proxy_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.bundle_proxy
    ADD CONSTRAINT bundle_proxy_pkey PRIMARY KEY (bundle_id, proxy_id);


--
-- Name: bundle_proxy bundle_proxy_proxy_id_key; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.bundle_proxy
    ADD CONSTRAINT bundle_proxy_proxy_id_key UNIQUE (proxy_id);


--
-- Name: dataimpulse_subuser dataimpulse_subuser_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.dataimpulse_subuser
    ADD CONSTRAINT dataimpulse_subuser_pkey PRIMARY KEY (subuser_id);


--
-- Name: invoice invoice_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.invoice
    ADD CONSTRAINT invoice_pkey PRIMARY KEY (id);


--
-- Name: payment payment_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.payment
    ADD CONSTRAINT payment_pkey PRIMARY KEY (id);


--
-- Name: payment_system payment_system_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.payment_system
    ADD CONSTRAINT payment_system_pkey PRIMARY KEY (id);


--
-- Name: promocode promocode_code_key; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.promocode
    ADD CONSTRAINT promocode_code_key UNIQUE (code);


--
-- Name: promocode_for_user promocode_for_user_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.promocode_for_user
    ADD CONSTRAINT promocode_for_user_pkey PRIMARY KEY (code_id, user_id);


--
-- Name: promocode promocode_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.promocode
    ADD CONSTRAINT promocode_pkey PRIMARY KEY (id);


--
-- Name: proxy proxy_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.proxy
    ADD CONSTRAINT proxy_pkey PRIMARY KEY (id);


--
-- Name: referral_balance_transaction referral_balance_transaction_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.referral_balance_transaction
    ADD CONSTRAINT referral_balance_transaction_pkey PRIMARY KEY (id);


--
-- Name: supported_language supported_language_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.supported_language
    ADD CONSTRAINT supported_language_pkey PRIMARY KEY (language_id, country_id);


--
-- Name: tariff_info tariff_info_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tariff_info
    ADD CONSTRAINT tariff_info_pkey PRIMARY KEY (id);


--
-- Name: tariff tariff_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tariff
    ADD CONSTRAINT tariff_pkey PRIMARY KEY (id);


--
-- Name: text text_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.text
    ADD CONSTRAINT text_pkey PRIMARY KEY (id);


--
-- Name: tg_user tg_user_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tg_user
    ADD CONSTRAINT tg_user_pkey PRIMARY KEY (user_id);


--
-- Name: tg_user tg_user_tg_id_key; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tg_user
    ADD CONSTRAINT tg_user_tg_id_key UNIQUE (tg_id);


--
-- Name: translation translation_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.translation
    ADD CONSTRAINT translation_pkey PRIMARY KEY (id);


--
-- Name: translation unique_translation; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.translation
    ADD CONSTRAINT unique_translation UNIQUE (text_id, language_id, country_id);


--
-- Name: used_promocode used_promocode_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.used_promocode
    ADD CONSTRAINT used_promocode_pkey PRIMARY KEY (code_id, user_id);


--
-- Name: user user_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate."user"
    ADD CONSTRAINT user_pkey PRIMARY KEY (id);


--
-- Name: user user_rolname_key; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate."user"
    ADD CONSTRAINT user_rolname_key UNIQUE (rolname);


--
-- Name: user_used_promo user_used_promo_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.user_used_promo
    ADD CONSTRAINT user_used_promo_pkey PRIMARY KEY (user_id, promo_id);


--
-- Name: web_user web_user_email_key; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.web_user
    ADD CONSTRAINT web_user_email_key UNIQUE (email);


--
-- Name: web_user web_user_pkey; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.web_user
    ADD CONSTRAINT web_user_pkey PRIMARY KEY (user_id);


--
-- Name: web_user web_user_username_key; Type: CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.web_user
    ADD CONSTRAINT web_user_username_key UNIQUE (username);


--
-- Name: user user_role_sync_trigger; Type: TRIGGER; Schema: vgate; Owner: postgres
--

CREATE TRIGGER user_role_sync_trigger BEFORE INSERT OR UPDATE ON vgate."user" FOR EACH ROW EXECUTE FUNCTION vgate.enforce_role_sync();


--
-- Name: bundle_proxy bundle_proxy_bundle_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.bundle_proxy
    ADD CONSTRAINT bundle_proxy_bundle_id_fkey FOREIGN KEY (bundle_id) REFERENCES vgate.bundle(id);


--
-- Name: bundle_proxy bundle_proxy_proxy_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.bundle_proxy
    ADD CONSTRAINT bundle_proxy_proxy_id_fkey FOREIGN KEY (proxy_id) REFERENCES vgate.proxy(id);


--
-- Name: bundle bundle_user_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.bundle
    ADD CONSTRAINT bundle_user_id_fkey FOREIGN KEY (user_id) REFERENCES vgate."user"(id);


--
-- Name: dataimpulse_subuser dataimpulse_subuser_bundle_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.dataimpulse_subuser
    ADD CONSTRAINT dataimpulse_subuser_bundle_id_fkey FOREIGN KEY (bundle_id) REFERENCES vgate.bundle(id);


--
-- Name: general_state general_state_default_country_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.general_state
    ADD CONSTRAINT general_state_default_country_fkey FOREIGN KEY (default_country) REFERENCES common.country(id);


--
-- Name: general_state general_state_default_language_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.general_state
    ADD CONSTRAINT general_state_default_language_fkey FOREIGN KEY (default_language) REFERENCES common.language(id);


--
-- Name: invoice invoice_payment_system_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.invoice
    ADD CONSTRAINT invoice_payment_system_id_fkey FOREIGN KEY (payment_system_id) REFERENCES vgate.payment_system(id);


--
-- Name: invoice invoice_tariff_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.invoice
    ADD CONSTRAINT invoice_tariff_id_fkey FOREIGN KEY (tariff_id) REFERENCES vgate.tariff(id);


--
-- Name: invoice invoice_user_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.invoice
    ADD CONSTRAINT invoice_user_id_fkey FOREIGN KEY (user_id) REFERENCES vgate."user"(id);


--
-- Name: payment payment_payment_system_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.payment
    ADD CONSTRAINT payment_payment_system_id_fkey FOREIGN KEY (payment_system_id) REFERENCES vgate.payment_system(id);


--
-- Name: payment payment_user_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.payment
    ADD CONSTRAINT payment_user_id_fkey FOREIGN KEY (user_id) REFERENCES vgate."user"(id);


--
-- Name: promocode_for_user promocode_for_user_code_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.promocode_for_user
    ADD CONSTRAINT promocode_for_user_code_id_fkey FOREIGN KEY (code_id) REFERENCES vgate.promocode(id);


--
-- Name: promocode_for_user promocode_for_user_user_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.promocode_for_user
    ADD CONSTRAINT promocode_for_user_user_id_fkey FOREIGN KEY (user_id) REFERENCES vgate."user"(id);


--
-- Name: referral_balance_transaction referral_balance_transaction_admin_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.referral_balance_transaction
    ADD CONSTRAINT referral_balance_transaction_admin_id_fkey FOREIGN KEY (admin_id) REFERENCES vgate."user"(id);


--
-- Name: referral_balance_transaction referral_balance_transaction_related_payment_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.referral_balance_transaction
    ADD CONSTRAINT referral_balance_transaction_related_payment_id_fkey FOREIGN KEY (related_payment_id) REFERENCES vgate.payment(id);


--
-- Name: referral_balance_transaction referral_balance_transaction_user_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.referral_balance_transaction
    ADD CONSTRAINT referral_balance_transaction_user_id_fkey FOREIGN KEY (user_id) REFERENCES vgate."user"(id);


--
-- Name: supported_language supported_language_country_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.supported_language
    ADD CONSTRAINT supported_language_country_id_fkey FOREIGN KEY (country_id) REFERENCES common.country(id);


--
-- Name: supported_language supported_language_language_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.supported_language
    ADD CONSTRAINT supported_language_language_id_fkey FOREIGN KEY (language_id) REFERENCES common.language(id);


--
-- Name: tariff tariff_currency_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tariff
    ADD CONSTRAINT tariff_currency_id_fkey FOREIGN KEY (currency_id) REFERENCES common.currency(id);


--
-- Name: tariff tariff_tariff_info_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tariff
    ADD CONSTRAINT tariff_tariff_info_id_fkey FOREIGN KEY (tariff_info_id) REFERENCES vgate.tariff_info(id);


--
-- Name: tg_user tg_user_user_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.tg_user
    ADD CONSTRAINT tg_user_user_id_fkey FOREIGN KEY (user_id) REFERENCES vgate."user"(id);


--
-- Name: translation translation_country_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.translation
    ADD CONSTRAINT translation_country_id_fkey FOREIGN KEY (country_id) REFERENCES common.country(id);


--
-- Name: translation translation_language_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.translation
    ADD CONSTRAINT translation_language_id_fkey FOREIGN KEY (language_id) REFERENCES common.language(id);


--
-- Name: translation translation_text_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.translation
    ADD CONSTRAINT translation_text_id_fkey FOREIGN KEY (text_id) REFERENCES vgate.text(id);


--
-- Name: used_promocode used_promocode_code_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.used_promocode
    ADD CONSTRAINT used_promocode_code_id_fkey FOREIGN KEY (code_id) REFERENCES vgate.promocode(id);


--
-- Name: used_promocode used_promocode_user_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.used_promocode
    ADD CONSTRAINT used_promocode_user_id_fkey FOREIGN KEY (user_id) REFERENCES vgate."user"(id);


--
-- Name: user user_referral_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate."user"
    ADD CONSTRAINT user_referral_id_fkey FOREIGN KEY (referral_id) REFERENCES vgate."user"(id);


--
-- Name: user user_supported_language_fk; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate."user"
    ADD CONSTRAINT user_supported_language_fk FOREIGN KEY (language_id, country_id) REFERENCES vgate.supported_language(language_id, country_id);


--
-- Name: user_used_promo user_used_promo_promo_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.user_used_promo
    ADD CONSTRAINT user_used_promo_promo_id_fkey FOREIGN KEY (promo_id) REFERENCES vgate.promocode(code);


--
-- Name: user_used_promo user_used_promo_user_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.user_used_promo
    ADD CONSTRAINT user_used_promo_user_id_fkey FOREIGN KEY (user_id) REFERENCES vgate."user"(id);


--
-- Name: web_user web_user_user_id_fkey; Type: FK CONSTRAINT; Schema: vgate; Owner: postgres
--

ALTER TABLE ONLY vgate.web_user
    ADD CONSTRAINT web_user_user_id_fkey FOREIGN KEY (user_id) REFERENCES vgate."user"(id);


--
-- Name: user return_user_if_tg_user_visible; Type: POLICY; Schema: vgate; Owner: postgres
--

CREATE POLICY return_user_if_tg_user_visible ON vgate."user" FOR SELECT USING ((EXISTS ( SELECT 1
   FROM vgate.tg_user t
  WHERE ((t.user_id = "user".id) AND (t.tg_id IS NOT NULL)))));


--
-- Name: tg_user; Type: ROW SECURITY; Schema: vgate; Owner: postgres
--

ALTER TABLE vgate.tg_user ENABLE ROW LEVEL SECURITY;

--
-- Name: user; Type: ROW SECURITY; Schema: vgate; Owner: postgres
--

ALTER TABLE vgate."user" ENABLE ROW LEVEL SECURITY;

--
-- Name: SCHEMA vgate; Type: ACL; Schema: -; Owner: postgres
--

GRANT USAGE ON SCHEMA vgate TO anon;
GRANT USAGE ON SCHEMA vgate TO vgate_user;
GRANT USAGE ON SCHEMA vgate TO vgate_provider;
GRANT USAGE ON SCHEMA vgate TO vgate_admin;
GRANT USAGE ON SCHEMA vgate TO vproxy;


--
-- Name: FUNCTION aaio_callback(status text, merchant_id uuid, invoice_id uuid, order_id text, amount numeric, currency aaio.currency, profit double precision, commission double precision, commission_client double precision, commission_type text, sign text, method text, "desc" text, email text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.aaio_callback(status text, merchant_id uuid, invoice_id uuid, order_id text, amount numeric, currency aaio.currency, profit double precision, commission double precision, commission_client double precision, commission_type text, sign text, method text, "desc" text, email text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.aaio_callback(status text, merchant_id uuid, invoice_id uuid, order_id text, amount numeric, currency aaio.currency, profit double precision, commission double precision, commission_client double precision, commission_type text, sign text, method text, "desc" text, email text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.aaio_callback(status text, merchant_id uuid, invoice_id uuid, order_id text, amount numeric, currency aaio.currency, profit double precision, commission double precision, commission_client double precision, commission_type text, sign text, method text, "desc" text, email text) TO vproxy;


--
-- Name: FUNCTION activate_traffic_promocode(code text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.activate_traffic_promocode(code text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.activate_traffic_promocode(code text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.activate_traffic_promocode(code text) TO vproxy;


--
-- Name: FUNCTION add_ip_to_whitelist(ip inet, pool common.dataimpulsepool); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.add_ip_to_whitelist(ip inet, pool common.dataimpulsepool) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.add_ip_to_whitelist(ip inet, pool common.dataimpulsepool) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.add_ip_to_whitelist(ip inet, pool common.dataimpulsepool) TO vproxy;


--
-- Name: FUNCTION apays_callback(json); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.apays_callback(json) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.apays_callback(json) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.apays_callback(json) TO vproxy;


--
-- Name: FUNCTION calculate(amounts integer[]); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.calculate(amounts integer[]) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.calculate(amounts integer[]) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.calculate(amounts integer[]) TO vproxy;


--
-- Name: FUNCTION calculate(amount integer); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.calculate(amount integer) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.calculate(amount integer) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.calculate(amount integer) TO vproxy;


--
-- Name: FUNCTION calculate_detailed_price(amount integer, pool common.dataimpulsepool, promocode text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.calculate_detailed_price(amount integer, pool common.dataimpulsepool, promocode text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.calculate_detailed_price(amount integer, pool common.dataimpulsepool, promocode text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.calculate_detailed_price(amount integer, pool common.dataimpulsepool, promocode text) TO vproxy;


--
-- Name: FUNCTION can_edit_article(article_id bigint); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.can_edit_article(article_id bigint) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.can_edit_article(article_id bigint) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.can_edit_article(article_id bigint) TO vproxy;


--
-- Name: FUNCTION cardlink_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.cardlink_status, "CurrencyIn" vgate.cardlink_currency, "SignatureValue" text, custom text, "AccountType" text, "AccountNumber" text, "AccountBank" text, "BalanceAmount" text, "BalanceCurrency" text, "ErrorCode" text, "ErrorMessage" text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.cardlink_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.cardlink_status, "CurrencyIn" vgate.cardlink_currency, "SignatureValue" text, custom text, "AccountType" text, "AccountNumber" text, "AccountBank" text, "BalanceAmount" text, "BalanceCurrency" text, "ErrorCode" text, "ErrorMessage" text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.cardlink_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.cardlink_status, "CurrencyIn" vgate.cardlink_currency, "SignatureValue" text, custom text, "AccountType" text, "AccountNumber" text, "AccountBank" text, "BalanceAmount" text, "BalanceCurrency" text, "ErrorCode" text, "ErrorMessage" text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.cardlink_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.cardlink_status, "CurrencyIn" vgate.cardlink_currency, "SignatureValue" text, custom text, "AccountType" text, "AccountNumber" text, "AccountBank" text, "BalanceAmount" text, "BalanceCurrency" text, "ErrorCode" text, "ErrorMessage" text) TO vproxy;


--
-- Name: FUNCTION change_account_password(old_password text, new_password text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.change_account_password(old_password text, new_password text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.change_account_password(old_password text, new_password text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.change_account_password(old_password text, new_password text) TO vproxy;


--
-- Name: FUNCTION change_language(code vgate.language); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.change_language(code vgate.language) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.change_language(code vgate.language) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.change_language(code vgate.language) TO vproxy;


--
-- Name: FUNCTION check_headers(); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.check_headers() TO vgate_provider;
GRANT ALL ON FUNCTION vgate.check_headers() TO vgate_admin;
GRANT ALL ON FUNCTION vgate.check_headers() TO vproxy;


--
-- Name: FUNCTION check_headers(title text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.check_headers(title text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.check_headers(title text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.check_headers(title text) TO vproxy;


--
-- Name: FUNCTION check_tg_user_exists(tg_id bigint); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.check_tg_user_exists(tg_id bigint) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.check_tg_user_exists(tg_id bigint) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.check_tg_user_exists(tg_id bigint) TO vproxy;


--
-- Name: FUNCTION check_user_exists(user_id text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.check_user_exists(user_id text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.check_user_exists(user_id text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.check_user_exists(user_id text) TO vproxy;


--
-- Name: FUNCTION check_user_role(user_id uuid, role text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.check_user_role(user_id uuid, role text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.check_user_role(user_id uuid, role text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.check_user_role(user_id uuid, role text) TO vproxy;
GRANT ALL ON FUNCTION vgate.check_user_role(user_id uuid, role text) TO anon;


--
-- Name: FUNCTION confirm_email(confirmation_token text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.confirm_email(confirmation_token text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.confirm_email(confirmation_token text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.confirm_email(confirmation_token text) TO vproxy;


--
-- Name: FUNCTION create_apays_invoice(amount integer); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.create_apays_invoice(amount integer) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.create_apays_invoice(amount integer) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.create_apays_invoice(amount integer) TO vproxy;


--
-- Name: FUNCTION create_blog_article(title text, content text, language vgate.language, hidden boolean); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.create_blog_article(title text, content text, language vgate.language, hidden boolean) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.create_blog_article(title text, content text, language vgate.language, hidden boolean) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.create_blog_article(title text, content text, language vgate.language, hidden boolean) TO vproxy;


--
-- Name: FUNCTION create_invoice(payment text, amount integer, promocode text, pool common.dataimpulsepool); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.create_invoice(payment text, amount integer, promocode text, pool common.dataimpulsepool) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.create_invoice(payment text, amount integer, promocode text, pool common.dataimpulsepool) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.create_invoice(payment text, amount integer, promocode text, pool common.dataimpulsepool) TO vproxy;


--
-- Name: FUNCTION create_invoice_web(payment_method text, amount integer, pool common.dataimpulsepool, promocode text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.create_invoice_web(payment_method text, amount integer, pool common.dataimpulsepool, promocode text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.create_invoice_web(payment_method text, amount integer, pool common.dataimpulsepool, promocode text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.create_invoice_web(payment_method text, amount integer, pool common.dataimpulsepool, promocode text) TO vproxy;


--
-- Name: FUNCTION create_referral_withdraw_request(amount numeric, comment text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.create_referral_withdraw_request(amount numeric, comment text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.create_referral_withdraw_request(amount numeric, comment text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.create_referral_withdraw_request(amount numeric, comment text) TO vproxy;


--
-- Name: FUNCTION create_subuser(token text, pool_type common.dataimpulsepool, sticky_range jsonb, threads integer, allowed_ips inet[], default_pool_parameters jsonb); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.create_subuser(token text, pool_type common.dataimpulsepool, sticky_range jsonb, threads integer, allowed_ips inet[], default_pool_parameters jsonb) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.create_subuser(token text, pool_type common.dataimpulsepool, sticky_range jsonb, threads integer, allowed_ips inet[], default_pool_parameters jsonb) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.create_subuser(token text, pool_type common.dataimpulsepool, sticky_range jsonb, threads integer, allowed_ips inet[], default_pool_parameters jsonb) TO vproxy;


--
-- Name: FUNCTION create_tgcode(user_id text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.create_tgcode(user_id text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.create_tgcode(user_id text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.create_tgcode(user_id text) TO vproxy;


--
-- Name: FUNCTION cryptomus_callback(json); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.cryptomus_callback(json) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.cryptomus_callback(json) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.cryptomus_callback(json) TO vproxy;


--
-- Name: FUNCTION crystalpay_callback(id text, signature text, url text, state text, type text, method text, required_method text, amount_currency text, rub_amount text, initial_amount text, remaining_amount text, balance_amount text, commission_amount text, description text, redirect_url text, callback_url text, extra text, created_at date, expired_at date, final_at date); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.crystalpay_callback(id text, signature text, url text, state text, type text, method text, required_method text, amount_currency text, rub_amount text, initial_amount text, remaining_amount text, balance_amount text, commission_amount text, description text, redirect_url text, callback_url text, extra text, created_at date, expired_at date, final_at date) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.crystalpay_callback(id text, signature text, url text, state text, type text, method text, required_method text, amount_currency text, rub_amount text, initial_amount text, remaining_amount text, balance_amount text, commission_amount text, description text, redirect_url text, callback_url text, extra text, created_at date, expired_at date, final_at date) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.crystalpay_callback(id text, signature text, url text, state text, type text, method text, required_method text, amount_currency text, rub_amount text, initial_amount text, remaining_amount text, balance_amount text, commission_amount text, description text, redirect_url text, callback_url text, extra text, created_at date, expired_at date, final_at date) TO vproxy;


--
-- Name: FUNCTION daily_statistics(from_date timestamp with time zone, to_date timestamp with time zone); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.daily_statistics(from_date timestamp with time zone, to_date timestamp with time zone) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.daily_statistics(from_date timestamp with time zone, to_date timestamp with time zone) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.daily_statistics(from_date timestamp with time zone, to_date timestamp with time zone) TO vproxy;


--
-- Name: FUNCTION delete_blog_article(article_id bigint); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.delete_blog_article(article_id bigint) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.delete_blog_article(article_id bigint) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.delete_blog_article(article_id bigint) TO vproxy;


--
-- Name: FUNCTION delete_subuser(token text, subuser_id integer); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.delete_subuser(token text, subuser_id integer) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.delete_subuser(token text, subuser_id integer) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.delete_subuser(token text, subuser_id integer) TO vproxy;


--
-- Name: FUNCTION discount_promocode_info(code text, amount integer); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.discount_promocode_info(code text, amount integer) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.discount_promocode_info(code text, amount integer) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.discount_promocode_info(code text, amount integer) TO vproxy;


--
-- Name: FUNCTION enforce_role_sync(); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.enforce_role_sync() TO vgate_provider;
GRANT ALL ON FUNCTION vgate.enforce_role_sync() TO vgate_admin;
GRANT ALL ON FUNCTION vgate.enforce_role_sync() TO vproxy;


--
-- Name: FUNCTION enum(t regtype); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.enum(t regtype) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.enum(t regtype) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.enum(t regtype) TO vproxy;


--
-- Name: FUNCTION freekassa_callback("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.freekassa_callback("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.freekassa_callback("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.freekassa_callback("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text) TO vproxy;


--
-- Name: FUNCTION freekassa_callback_inner("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.freekassa_callback_inner("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.freekassa_callback_inner("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.freekassa_callback_inner("MERCHANT_ID" integer, "AMOUNT" numeric, intid integer, "MERCHANT_ORDER_ID" text, "P_EMAIL" text, "P_PHONE" text, "CUR_ID" integer, "SIGN" text, commission numeric, payer_account text) TO vproxy;


--
-- Name: FUNCTION get_apays_invoice_status(order_id text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_apays_invoice_status(order_id text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_apays_invoice_status(order_id text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_apays_invoice_status(order_id text) TO vproxy;


--
-- Name: FUNCTION get_balance(token text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_balance(token text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_balance(token text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_balance(token text) TO vproxy;


--
-- Name: FUNCTION get_banner(id integer); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_banner(id integer) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_banner(id integer) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_banner(id integer) TO vproxy;


--
-- Name: FUNCTION get_banner_blob(id integer); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_banner_blob(id integer) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_banner_blob(id integer) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_banner_blob(id integer) TO vproxy;


--
-- Name: FUNCTION get_banners(); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_banners() TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_banners() TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_banners() TO vproxy;


--
-- Name: FUNCTION get_blog_article(article_id bigint); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_blog_article(article_id bigint) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_blog_article(article_id bigint) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_blog_article(article_id bigint) TO vproxy;


--
-- Name: FUNCTION get_blog_article_image_blob(article_id bigint); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_blog_article_image_blob(article_id bigint) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_blog_article_image_blob(article_id bigint) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_blog_article_image_blob(article_id bigint) TO vproxy;


--
-- Name: FUNCTION get_blog_articles(limit_count integer, offset_count integer, search_query text, user_language vgate.language); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_blog_articles(limit_count integer, offset_count integer, search_query text, user_language vgate.language) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_blog_articles(limit_count integer, offset_count integer, search_query text, user_language vgate.language) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_blog_articles(limit_count integer, offset_count integer, search_query text, user_language vgate.language) TO vproxy;


--
-- Name: FUNCTION get_current_setting(setting text, OUT response text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_current_setting(setting text, OUT response text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_current_setting(setting text, OUT response text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_current_setting(setting text, OUT response text) TO vproxy;


--
-- Name: FUNCTION get_dataimpulse_pool_stats(pool text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_dataimpulse_pool_stats(pool text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_pool_stats(pool text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_pool_stats(pool text) TO vproxy;


--
-- Name: FUNCTION get_dataimpulse_proxy_asns(pool common.dataimpulsepool, countries text[], states text[], cities text[], zipcodes text[], order_by text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_asns(pool common.dataimpulsepool, countries text[], states text[], cities text[], zipcodes text[], order_by text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_asns(pool common.dataimpulsepool, countries text[], states text[], cities text[], zipcodes text[], order_by text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_asns(pool common.dataimpulsepool, countries text[], states text[], cities text[], zipcodes text[], order_by text) TO vproxy;


--
-- Name: FUNCTION get_dataimpulse_proxy_cities(pool common.dataimpulsepool, countries text[], states text[], zipcodes text[], asns text[], order_by text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_cities(pool common.dataimpulsepool, countries text[], states text[], zipcodes text[], asns text[], order_by text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_cities(pool common.dataimpulsepool, countries text[], states text[], zipcodes text[], asns text[], order_by text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_cities(pool common.dataimpulsepool, countries text[], states text[], zipcodes text[], asns text[], order_by text) TO vproxy;


--
-- Name: FUNCTION get_dataimpulse_proxy_countries(pool common.dataimpulsepool, order_by text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_countries(pool common.dataimpulsepool, order_by text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_countries(pool common.dataimpulsepool, order_by text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_countries(pool common.dataimpulsepool, order_by text) TO vproxy;


--
-- Name: FUNCTION get_dataimpulse_proxy_states(pool common.dataimpulsepool, countries text[], cities text[], zipcodes text[], asns text[], order_by text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_states(pool common.dataimpulsepool, countries text[], cities text[], zipcodes text[], asns text[], order_by text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_states(pool common.dataimpulsepool, countries text[], cities text[], zipcodes text[], asns text[], order_by text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_states(pool common.dataimpulsepool, countries text[], cities text[], zipcodes text[], asns text[], order_by text) TO vproxy;


--
-- Name: FUNCTION get_dataimpulse_proxy_zipcodes(pool common.dataimpulsepool, countries text[], states text[], asns text[], order_by text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_zipcodes(pool common.dataimpulsepool, countries text[], states text[], asns text[], order_by text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_zipcodes(pool common.dataimpulsepool, countries text[], states text[], asns text[], order_by text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_dataimpulse_proxy_zipcodes(pool common.dataimpulsepool, countries text[], states text[], asns text[], order_by text) TO vproxy;


--
-- Name: FUNCTION get_default_pool_parameters(pool common.dataimpulsepool); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_default_pool_parameters(pool common.dataimpulsepool) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_default_pool_parameters(pool common.dataimpulsepool) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_default_pool_parameters(pool common.dataimpulsepool) TO vproxy;


--
-- Name: FUNCTION get_my_articles(limit_count integer, offset_count integer); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_my_articles(limit_count integer, offset_count integer) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_my_articles(limit_count integer, offset_count integer) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_my_articles(limit_count integer, offset_count integer) TO vproxy;


--
-- Name: FUNCTION get_proxy(anonymous text, type text, protocol text, format text, quantity integer, sessionttl integer, pool common.dataimpulsepool, countries text[], cities text[], states text[], excluded_asns text[], included_asns text[], zipcodes text[], region common.proxyregion); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_proxy(anonymous text, type text, protocol text, format text, quantity integer, sessionttl integer, pool common.dataimpulsepool, countries text[], cities text[], states text[], excluded_asns text[], included_asns text[], zipcodes text[], region common.proxyregion) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_proxy(anonymous text, type text, protocol text, format text, quantity integer, sessionttl integer, pool common.dataimpulsepool, countries text[], cities text[], states text[], excluded_asns text[], included_asns text[], zipcodes text[], region common.proxyregion) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_proxy(anonymous text, type text, protocol text, format text, quantity integer, sessionttl integer, pool common.dataimpulsepool, countries text[], cities text[], states text[], excluded_asns text[], included_asns text[], zipcodes text[], region common.proxyregion) TO vproxy;


--
-- Name: FUNCTION get_whitelist_ips(pool common.dataimpulsepool); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.get_whitelist_ips(pool common.dataimpulsepool) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.get_whitelist_ips(pool common.dataimpulsepool) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.get_whitelist_ips(pool common.dataimpulsepool) TO vproxy;


--
-- Name: FUNCTION heleket_callback(json); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.heleket_callback(json) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.heleket_callback(json) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.heleket_callback(json) TO vproxy;


--
-- Name: FUNCTION "i18n.dictionary"(lang_code vgate.language); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate."i18n.dictionary"(lang_code vgate.language) TO vgate_provider;
GRANT ALL ON FUNCTION vgate."i18n.dictionary"(lang_code vgate.language) TO vgate_admin;
GRANT ALL ON FUNCTION vgate."i18n.dictionary"(lang_code vgate.language) TO vproxy;


--
-- Name: FUNCTION "i18n.load"(jsonb); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate."i18n.load"(jsonb) TO vgate_provider;
GRANT ALL ON FUNCTION vgate."i18n.load"(jsonb) TO vgate_admin;
GRANT ALL ON FUNCTION vgate."i18n.load"(jsonb) TO vproxy;


--
-- Name: FUNCTION "i18n.translate"(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate."i18n.translate"(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language) TO vgate_provider;
GRANT ALL ON FUNCTION vgate."i18n.translate"(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language) TO vgate_admin;
GRANT ALL ON FUNCTION vgate."i18n.translate"(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language) TO vproxy;


--
-- Name: FUNCTION is_password_exists(); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.is_password_exists() TO vgate_provider;
GRANT ALL ON FUNCTION vgate.is_password_exists() TO vgate_admin;
GRANT ALL ON FUNCTION vgate.is_password_exists() TO vproxy;


--
-- Name: FUNCTION legacy_get_statistic(period common.period, pool common.dataimpulsepool); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.legacy_get_statistic(period common.period, pool common.dataimpulsepool) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.legacy_get_statistic(period common.period, pool common.dataimpulsepool) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.legacy_get_statistic(period common.period, pool common.dataimpulsepool) TO vproxy;


--
-- Name: FUNCTION merge_users(source_user_id text, target_user_id text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.merge_users(source_user_id text, target_user_id text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.merge_users(source_user_id text, target_user_id text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.merge_users(source_user_id text, target_user_id text) TO vproxy;


--
-- Name: FUNCTION pallyinfo_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.pally_status, "CurrencyIn" vgate.pally_currency, "SignatureValue" text, custom text, "AccountType" text, "AccountNumber" text, "BalanceAmount" text, "BalanceCurrency" text, "AccountBank" text, "ErrorCode" text, "ErrorMessage" text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.pallyinfo_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.pally_status, "CurrencyIn" vgate.pally_currency, "SignatureValue" text, custom text, "AccountType" text, "AccountNumber" text, "BalanceAmount" text, "BalanceCurrency" text, "AccountBank" text, "ErrorCode" text, "ErrorMessage" text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.pallyinfo_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.pally_status, "CurrencyIn" vgate.pally_currency, "SignatureValue" text, custom text, "AccountType" text, "AccountNumber" text, "BalanceAmount" text, "BalanceCurrency" text, "AccountBank" text, "ErrorCode" text, "ErrorMessage" text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.pallyinfo_callback("InvId" text, "OutSum" text, "Commission" text, "TrsId" text, "Status" vgate.pally_status, "CurrencyIn" vgate.pally_currency, "SignatureValue" text, custom text, "AccountType" text, "AccountNumber" text, "BalanceAmount" text, "BalanceCurrency" text, "AccountBank" text, "ErrorCode" text, "ErrorMessage" text) TO vproxy;


--
-- Name: FUNCTION password_recovery(recovery_code text, password text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.password_recovery(recovery_code text, password text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.password_recovery(recovery_code text, password text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.password_recovery(recovery_code text, password text) TO vproxy;


--
-- Name: FUNCTION password_recovery_email(email text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.password_recovery_email(email text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.password_recovery_email(email text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.password_recovery_email(email text) TO vproxy;


--
-- Name: FUNCTION prices(); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.prices() TO vgate_provider;
GRANT ALL ON FUNCTION vgate.prices() TO vgate_admin;
GRANT ALL ON FUNCTION vgate.prices() TO vproxy;


--
-- Name: FUNCTION record_promo_activation(p_user_id text, p_promo_name text, p_promo_type vgate.promotype); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.record_promo_activation(p_user_id text, p_promo_name text, p_promo_type vgate.promotype) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.record_promo_activation(p_user_id text, p_promo_name text, p_promo_type vgate.promotype) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.record_promo_activation(p_user_id text, p_promo_name text, p_promo_type vgate.promotype) TO vproxy;


--
-- Name: FUNCTION referral_payment(amount integer, pool common.dataimpulsepool, promocode text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.referral_payment(amount integer, pool common.dataimpulsepool, promocode text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.referral_payment(amount integer, pool common.dataimpulsepool, promocode text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.referral_payment(amount integer, pool common.dataimpulsepool, promocode text) TO vproxy;


--
-- Name: FUNCTION remove_ip_from_whitelist(ip inet, pool common.dataimpulsepool); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.remove_ip_from_whitelist(ip inet, pool common.dataimpulsepool) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.remove_ip_from_whitelist(ip inet, pool common.dataimpulsepool) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.remove_ip_from_whitelist(ip inet, pool common.dataimpulsepool) TO vproxy;


--
-- Name: FUNCTION request_email_confirmation(user_id text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.request_email_confirmation(user_id text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.request_email_confirmation(user_id text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.request_email_confirmation(user_id text) TO vproxy;


--
-- Name: FUNCTION request_email_confirmation(email vgate.email_address); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.request_email_confirmation(email vgate.email_address) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.request_email_confirmation(email vgate.email_address) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.request_email_confirmation(email vgate.email_address) TO vproxy;


--
-- Name: FUNCTION reseller_token(user_id text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.reseller_token(user_id text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.reseller_token(user_id text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.reseller_token(user_id text) TO vproxy;


--
-- Name: FUNCTION reset_password(pool common.dataimpulsepool); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.reset_password(pool common.dataimpulsepool) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.reset_password(pool common.dataimpulsepool) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.reset_password(pool common.dataimpulsepool) TO vproxy;


--
-- Name: FUNCTION schema_is(_type common.schematype); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.schema_is(_type common.schematype) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.schema_is(_type common.schematype) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.schema_is(_type common.schematype) TO vproxy;


--
-- Name: FUNCTION set_default_pool_parameters(countries text[], cities text[], states text[], zipcodes text[], asns text[], exclude_countries text[], exclude_asn text[], anonymous_filter boolean, rotation_interval integer, pool common.dataimpulsepool); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.set_default_pool_parameters(countries text[], cities text[], states text[], zipcodes text[], asns text[], exclude_countries text[], exclude_asn text[], anonymous_filter boolean, rotation_interval integer, pool common.dataimpulsepool) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.set_default_pool_parameters(countries text[], cities text[], states text[], zipcodes text[], asns text[], exclude_countries text[], exclude_asn text[], anonymous_filter boolean, rotation_interval integer, pool common.dataimpulsepool) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.set_default_pool_parameters(countries text[], cities text[], states text[], zipcodes text[], asns text[], exclude_countries text[], exclude_asn text[], anonymous_filter boolean, rotation_interval integer, pool common.dataimpulsepool) TO vproxy;


--
-- Name: FUNCTION show_search_path(); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.show_search_path() TO vgate_provider;
GRANT ALL ON FUNCTION vgate.show_search_path() TO vgate_admin;
GRANT ALL ON FUNCTION vgate.show_search_path() TO vproxy;


--
-- Name: FUNCTION signin(username text, password text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.signin(username text, password text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.signin(username text, password text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.signin(username text, password text) TO vproxy;


--
-- Name: FUNCTION signinup_tg(id bigint, username text, first_name text, surname text, referral_id text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.signinup_tg(id bigint, username text, first_name text, surname text, referral_id text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.signinup_tg(id bigint, username text, first_name text, surname text, referral_id text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.signinup_tg(id bigint, username text, first_name text, surname text, referral_id text) TO vproxy;


--
-- Name: FUNCTION signup(email text, username text, password text, referral_id text, admin_referral_code text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.signup(email text, username text, password text, referral_id text, admin_referral_code text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.signup(email text, username text, password text, referral_id text, admin_referral_code text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.signup(email text, username text, password text, referral_id text, admin_referral_code text) TO vproxy;


--
-- Name: FUNCTION telegram_code_signin(p_code text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.telegram_code_signin(p_code text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.telegram_code_signin(p_code text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.telegram_code_signin(p_code text) TO vproxy;


--
-- Name: FUNCTION telegram_stars_payment(payment_data jsonb); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.telegram_stars_payment(payment_data jsonb) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.telegram_stars_payment(payment_data jsonb) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.telegram_stars_payment(payment_data jsonb) TO vproxy;


--
-- Name: FUNCTION telegram_stars_payment_2(jsonb); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.telegram_stars_payment_2(jsonb) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.telegram_stars_payment_2(jsonb) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.telegram_stars_payment_2(jsonb) TO vproxy;


--
-- Name: FUNCTION test(); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.test() TO vgate_provider;
GRANT ALL ON FUNCTION vgate.test() TO vgate_admin;
GRANT ALL ON FUNCTION vgate.test() TO vproxy;


--
-- Name: FUNCTION test_array("array" text[]); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.test_array("array" text[]) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.test_array("array" text[]) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.test_array("array" text[]) TO vproxy;


--
-- Name: FUNCTION test_bool(); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.test_bool() TO vgate_provider;
GRANT ALL ON FUNCTION vgate.test_bool() TO vgate_admin;
GRANT ALL ON FUNCTION vgate.test_bool() TO vproxy;


--
-- Name: FUNCTION test_rpc(); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.test_rpc() TO vgate_provider;
GRANT ALL ON FUNCTION vgate.test_rpc() TO vgate_admin;
GRANT ALL ON FUNCTION vgate.test_rpc() TO vproxy;


--
-- Name: FUNCTION "tg.is_admin"(user_id text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate."tg.is_admin"(user_id text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate."tg.is_admin"(user_id text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate."tg.is_admin"(user_id text) TO vproxy;


--
-- Name: FUNCTION "tg.is_support"(user_id text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate."tg.is_support"(user_id text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate."tg.is_support"(user_id text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate."tg.is_support"(user_id text) TO vproxy;


--
-- Name: FUNCTION translate(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.translate(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.translate(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.translate(hash common.sha256, label text, content text, lable_lang_code vgate.language, lang_code vgate.language) TO vproxy;


--
-- Name: FUNCTION translation_dictionary(lang_code vgate.language); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.translation_dictionary(lang_code vgate.language) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.translation_dictionary(lang_code vgate.language) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.translation_dictionary(lang_code vgate.language) TO vproxy;


--
-- Name: FUNCTION update_blog_article(article_id bigint, title text, content text, language vgate.language, hidden boolean); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.update_blog_article(article_id bigint, title text, content text, language vgate.language, hidden boolean) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.update_blog_article(article_id bigint, title text, content text, language vgate.language, hidden boolean) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.update_blog_article(article_id bigint, title text, content text, language vgate.language, hidden boolean) TO vproxy;


--
-- Name: FUNCTION update_subuser(token text, subuser_id integer, sticky_range jsonb, threads integer); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.update_subuser(token text, subuser_id integer, sticky_range jsonb, threads integer) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.update_subuser(token text, subuser_id integer, sticky_range jsonb, threads integer) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.update_subuser(token text, subuser_id integer, sticky_range jsonb, threads integer) TO vproxy;


--
-- Name: FUNCTION update_translation_usage(usage_data jsonb); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.update_translation_usage(usage_data jsonb) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.update_translation_usage(usage_data jsonb) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.update_translation_usage(usage_data jsonb) TO vproxy;


--
-- Name: FUNCTION upload_blog_article_image(article_id bigint, image_data text); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.upload_blog_article_image(article_id bigint, image_data text) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.upload_blog_article_image(article_id bigint, image_data text) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.upload_blog_article_image(article_id bigint, image_data text) TO vproxy;


--
-- Name: FUNCTION usd_to_kop(price numeric); Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON FUNCTION vgate.usd_to_kop(price numeric) TO vgate_provider;
GRANT ALL ON FUNCTION vgate.usd_to_kop(price numeric) TO vgate_admin;
GRANT ALL ON FUNCTION vgate.usd_to_kop(price numeric) TO vproxy;


--
-- Name: TABLE actual_username; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.actual_username TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.actual_username TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.actual_username TO vproxy;


--
-- Name: TABLE bundle; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.bundle TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.bundle TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.bundle TO vproxy;


--
-- Name: TABLE bundle_proxy; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.bundle_proxy TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.bundle_proxy TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.bundle_proxy TO vproxy;


--
-- Name: TABLE check_headers; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.check_headers TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.check_headers TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.check_headers TO vproxy;
GRANT ALL ON TABLE vgate.check_headers TO anon;


--
-- Name: TABLE dataimpulse_subuser; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.dataimpulse_subuser TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.dataimpulse_subuser TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.dataimpulse_subuser TO vproxy;


--
-- Name: TABLE promocode; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.promocode TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.promocode TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.promocode TO vproxy;


--
-- Name: TABLE discount_promocode; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.discount_promocode TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.discount_promocode TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.discount_promocode TO vproxy;


--
-- Name: SEQUENCE freekassa_nonce; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,USAGE ON SEQUENCE vgate.freekassa_nonce TO vgate_provider;
GRANT SELECT,USAGE ON SEQUENCE vgate.freekassa_nonce TO vgate_admin;
GRANT SELECT,USAGE ON SEQUENCE vgate.freekassa_nonce TO vproxy;


--
-- Name: TABLE general_state; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.general_state TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.general_state TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.general_state TO vproxy;


--
-- Name: TABLE invoice; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.invoice TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.invoice TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.invoice TO vproxy;


--
-- Name: TABLE legacy_all_user; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_all_user TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_all_user TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_all_user TO vproxy;


--
-- Name: TABLE legacy_profile; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_profile TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_profile TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_profile TO vproxy;
GRANT SELECT,REFERENCES,TRIGGER,TRUNCATE ON TABLE vgate.legacy_profile TO vgate_user;


--
-- Name: TABLE legacy_profile_slim; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_profile_slim TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_profile_slim TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_profile_slim TO vproxy;
GRANT SELECT,REFERENCES,TRIGGER,TRUNCATE ON TABLE vgate.legacy_profile_slim TO vgate_user;


--
-- Name: TABLE legacy_referal_info; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_referal_info TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_referal_info TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.legacy_referal_info TO vproxy;
GRANT ALL ON TABLE vgate.legacy_referal_info TO vgate_user;


--
-- Name: TABLE payment; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.payment TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.payment TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.payment TO vproxy;


--
-- Name: TABLE payment_system; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.payment_system TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.payment_system TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.payment_system TO vproxy;
GRANT SELECT ON TABLE vgate.payment_system TO anon;


--
-- Name: SEQUENCE payment_system_id_seq; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,USAGE ON SEQUENCE vgate.payment_system_id_seq TO vgate_provider;
GRANT SELECT,USAGE ON SEQUENCE vgate.payment_system_id_seq TO vgate_admin;
GRANT SELECT,USAGE ON SEQUENCE vgate.payment_system_id_seq TO vproxy;


--
-- Name: TABLE payment_systems; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.payment_systems TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.payment_systems TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.payment_systems TO vproxy;
GRANT SELECT ON TABLE vgate.payment_systems TO anon;


--
-- Name: TABLE promocode_for_user; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.promocode_for_user TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.promocode_for_user TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.promocode_for_user TO vproxy;


--
-- Name: SEQUENCE promocode_id_seq; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,USAGE ON SEQUENCE vgate.promocode_id_seq TO vgate_provider;
GRANT SELECT,USAGE ON SEQUENCE vgate.promocode_id_seq TO vgate_admin;
GRANT SELECT,USAGE ON SEQUENCE vgate.promocode_id_seq TO vproxy;


--
-- Name: TABLE proxy; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.proxy TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.proxy TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.proxy TO vproxy;


--
-- Name: TABLE referral_balance_transaction; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.referral_balance_transaction TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.referral_balance_transaction TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.referral_balance_transaction TO vproxy;


--
-- Name: TABLE reseller_profile; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT ALL ON TABLE vgate.reseller_profile TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.reseller_profile TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.reseller_profile TO vproxy;


--
-- Name: TABLE supported_language; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.supported_language TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.supported_language TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.supported_language TO vproxy;


--
-- Name: TABLE tariff; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.tariff TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.tariff TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.tariff TO vproxy;


--
-- Name: SEQUENCE tariff_id_seq; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,USAGE ON SEQUENCE vgate.tariff_id_seq TO vgate_provider;
GRANT SELECT,USAGE ON SEQUENCE vgate.tariff_id_seq TO vgate_admin;
GRANT SELECT,USAGE ON SEQUENCE vgate.tariff_id_seq TO vproxy;


--
-- Name: TABLE tariff_info; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.tariff_info TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.tariff_info TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.tariff_info TO vproxy;


--
-- Name: SEQUENCE tariff_info_id_seq; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,USAGE ON SEQUENCE vgate.tariff_info_id_seq TO vgate_provider;
GRANT SELECT,USAGE ON SEQUENCE vgate.tariff_info_id_seq TO vgate_admin;
GRANT SELECT,USAGE ON SEQUENCE vgate.tariff_info_id_seq TO vproxy;


--
-- Name: TABLE text; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.text TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.text TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.text TO vproxy;


--
-- Name: TABLE tg_user; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.tg_user TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.tg_user TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.tg_user TO vproxy;


--
-- Name: TABLE translation; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.translation TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.translation TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.translation TO vproxy;


--
-- Name: SEQUENCE translation_id_seq; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,USAGE ON SEQUENCE vgate.translation_id_seq TO vgate_provider;
GRANT SELECT,USAGE ON SEQUENCE vgate.translation_id_seq TO vgate_admin;
GRANT SELECT,USAGE ON SEQUENCE vgate.translation_id_seq TO vproxy;


--
-- Name: TABLE used_promocode; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.used_promocode TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.used_promocode TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.used_promocode TO vproxy;


--
-- Name: TABLE "user"; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate."user" TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate."user" TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate."user" TO vproxy;


--
-- Name: TABLE user_used_promo; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.user_used_promo TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.user_used_promo TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.user_used_promo TO vproxy;


--
-- Name: TABLE web_user; Type: ACL; Schema: vgate; Owner: postgres
--

GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.web_user TO vgate_provider;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.web_user TO vgate_admin;
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vgate.web_user TO vproxy;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: vgate; Owner: postgres
--

ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA vgate GRANT SELECT,USAGE ON SEQUENCES  TO vgate_provider;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA vgate GRANT SELECT,USAGE ON SEQUENCES  TO vgate_admin;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA vgate GRANT SELECT,USAGE ON SEQUENCES  TO vproxy;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: vgate; Owner: postgres
--

ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA vgate GRANT ALL ON FUNCTIONS  TO vgate_provider;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA vgate GRANT ALL ON FUNCTIONS  TO vgate_admin;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA vgate GRANT ALL ON FUNCTIONS  TO vproxy;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: vgate; Owner: postgres
--

ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA vgate GRANT SELECT,INSERT,DELETE,UPDATE ON TABLES  TO vgate_provider;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA vgate GRANT SELECT,INSERT,DELETE,UPDATE ON TABLES  TO vgate_admin;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA vgate GRANT SELECT,INSERT,DELETE,UPDATE ON TABLES  TO vproxy;


--
-- PostgreSQL database dump complete
--

