Перейти к содержанию

wallet_debit

Сигнатура: wallet_debit("p_user_id" "uuid", "p_amount" numeric, "p_kind" "text" DEFAULT 'debit'::"text", "p_meta" "jsonb" DEFAULT '{}'::"jsonb") RETURNS "jsonb"
Язык: sql
Security: DEFINER

Тело функции

declare
  cur_balance numeric;
  new_balance numeric;
  tx_id uuid;
begin
  if p_amount is null or p_amount <= 0 then
    raise exception 'INVALID_AMOUNT';
  end if;

  -- гарантируем кошелёк
  perform public.ensure_wallet(p_user_id);

  -- блокируем строку кошелька
  select balance into cur_balance
  from public.wallets
  where user_id = p_user_id
  for update;

  if cur_balance is null then
    raise exception 'WALLET_NOT_FOUND';
  end if;

  if cur_balance < p_amount then
    -- не меняем баланс, просто ошибка
    return jsonb_build_object('ok', false, 'error', 'INSUFFICIENT_FUNDS', 'balance', cur_balance);
  end if;

  new_balance := cur_balance - p_amount;

  -- применяем списание
  update public.wallets
  set balance = new_balance, updated_at = now()
  where user_id = p_user_id;

  -- пишем журнал (отрицательная сумма)
  insert into public.wallet_tx(user_id, amount, kind, meta)
  values (p_user_id, -p_amount, coalesce(p_kind,'debit'), coalesce(p_meta,'{}'::jsonb))
  returning id into tx_id;

  return jsonb_build_object('ok', true, 'tx_id', tx_id, 'balance', new_balance);
end;