-- Toman deposit preparation and customer claims. This migration never credits a wallet.
begin;
create table if not exists marketplace_private.toman_deposit_destinations(
 id uuid primary key default gen_random_uuid(),method text not null unique check(method in('card_transfer','paya','account_transfer')),
 enabled boolean not null default false,details jsonb not null default '{"bank_name":"","account_holder":"","iban":null,"card_number":null,"account_number":null,"deposit_identifier":null}',
 version integer not null default 1 check(version>0),updated_at timestamptz not null default clock_timestamp(),updated_by uuid references auth.users(id) on delete restrict
);
insert into marketplace_private.toman_deposit_destinations(method) values('card_transfer'),('paya'),('account_transfer') on conflict(method) do nothing;
create table if not exists marketplace_private.toman_deposit_destination_history(
 id bigint generated always as identity primary key,destination_id uuid not null references marketplace_private.toman_deposit_destinations(id) on delete restrict,
 version integer not null,before_data jsonb not null,after_data jsonb not null,actor_id uuid not null references auth.users(id) on delete restrict,created_at timestamptz not null default clock_timestamp(),unique(destination_id,version)
);
create table if not exists marketplace_private.toman_deposit_requests(
 id uuid primary key default gen_random_uuid(),request_id uuid not null,user_id uuid not null references auth.users(id) on delete restrict,
 amount_rial bigint not null check(amount_rial between 10 and 9999999999990 and amount_rial%10=0),
 method text not null check(method in('gateway','instant_bank','card_transfer','paya','account_transfer','direct_debit')),
 status text not null default 'draft' check(status in('draft','submitted','cancelled')),version integer not null default 1 check(version>0),
 destination_id uuid references marketplace_private.toman_deposit_destinations(id) on delete restrict,destination_version integer,destination_snapshot jsonb,
 bank_id uuid references marketplace_private.bank_accounts(id) on delete restrict,bank_snapshot jsonb,transfer_reference text,
 created_at timestamptz not null default clock_timestamp(),updated_at timestamptz not null default clock_timestamp(),submitted_at timestamptz,cancelled_at timestamptz,
 unique(user_id,request_id),
 check((status='submitted')=(submitted_at is not null and destination_id is not null and destination_version is not null and destination_snapshot is not null and bank_id is not null and bank_snapshot is not null and transfer_reference is not null)),
 check((status='cancelled')=(cancelled_at is not null)),
 check(status='submitted' or (submitted_at is null and destination_id is null and destination_version is null and destination_snapshot is null and bank_id is null and bank_snapshot is null and transfer_reference is null))
);
create unique index if not exists toman_deposit_one_draft on marketplace_private.toman_deposit_requests(user_id) where status='draft';
create unique index if not exists toman_deposit_transfer_once on marketplace_private.toman_deposit_requests(destination_id,transfer_reference) where status='submitted';
create index if not exists toman_deposit_owner_history on marketplace_private.toman_deposit_requests(user_id,created_at desc,id desc);
do $$declare t text;begin
 foreach t in array array['toman_deposit_destinations','toman_deposit_destination_history','toman_deposit_requests'] loop
  execute format('alter table marketplace_private.%I enable row level security',t);
  execute format('revoke all on marketplace_private.%I from public,anon,authenticated,service_role',t);
  execute format('drop trigger if exists toman_deposit_retained on marketplace_private.%I',t);
  execute format('create trigger toman_deposit_retained before delete on marketplace_private.%I for each row execute function marketplace_private.customer_record_retained()',t);
  execute format('drop trigger if exists toman_deposit_truncate_retained on marketplace_private.%I',t);
  execute format('create trigger toman_deposit_truncate_retained before truncate on marketplace_private.%I for each statement execute function marketplace_private.customer_record_retained()',t);
 end loop;
end$$;
drop trigger if exists toman_deposit_history_immutable on marketplace_private.toman_deposit_destination_history;
create trigger toman_deposit_history_immutable before update on marketplace_private.toman_deposit_destination_history for each row execute function marketplace_private.customer_record_retained();

create or replace function marketplace_private.toman_deposit_customer() returns uuid language plpgsql security definer set search_path='' as $$
declare uid uuid:=auth.uid();begin
 if uid is null then raise exception 'not_authenticated' using errcode='42501';end if;
 if not exists(select 1 from marketplace_private.customer_profiles where user_id=uid) or exists(select 1 from marketplace_private.members where user_id=uid) then raise exception 'not_authorized' using errcode='42501';end if;
 perform marketplace_private.customer_access_assert(uid);
 return uid;
end$$;
create or replace function marketplace_private.toman_deposit_details(p_method text,p_enabled boolean,p_details jsonb) returns jsonb language plpgsql immutable set search_path='' as $$
declare d jsonb;k text;v text;s integer:=0;n integer;i integer;begin
 if p_method is null or p_method not in('card_transfer','paya','account_transfer') then raise exception 'deposit_method_unavailable';end if;
 if p_enabled is null or jsonb_typeof(p_details) is distinct from 'object' or octet_length(p_details::text)>2000
 or (select count(*) from jsonb_object_keys(p_details))<>6 or not(p_details ?& array['bank_name','account_holder','iban','card_number','account_number','deposit_identifier']) then raise exception 'invalid_deposit_destination';end if;
 d:=p_details;
 foreach k in array array['bank_name','account_holder','iban','card_number','account_number','deposit_identifier'] loop
  if jsonb_typeof(d->k) not in('string','null') then raise exception 'invalid_deposit_destination';end if;
  v:=trim(d->>k);
  if v ~ '[[:cntrl:]]' or char_length(v)>100 then raise exception 'invalid_deposit_destination';end if;
  d:=jsonb_set(d,array[k],case when k in('bank_name','account_holder') then to_jsonb(coalesce(v,'')) else coalesce(to_jsonb(nullif(v,'')),'null'::jsonb) end);
 end loop;
 v:=d->>'iban';if v is not null and (v!~'^IR[0-9]{24}$' or mod((substring(v,5)||'1827'||substring(v,3,2))::numeric,97)<>1) then raise exception 'invalid_deposit_iban';end if;
 v:=d->>'card_number';if v is not null then
  if v!~'^[0-9]{16}$' or v=repeat(substr(v,1,1),16) then raise exception 'invalid_deposit_card';end if;
  for i in 1..16 loop n:=substr(v,i,1)::integer*case when i%2=1 then 2 else 1 end;s:=s+case when n>9 then n-9 else n end;end loop;
  if s%10<>0 then raise exception 'invalid_deposit_card';end if;
 end if;
 if d->>'account_number' is not null and d->>'account_number'!~'^[0-9]{3,30}$' then raise exception 'invalid_deposit_account';end if;
 if d->>'deposit_identifier' is not null and d->>'deposit_identifier'!~'^[0-9]{3,40}$' then raise exception 'invalid_deposit_identifier';end if;
 if p_enabled and (length(d->>'bank_name')<2 or length(d->>'account_holder')<2
 or (p_method='card_transfer' and d->>'card_number' is null)
 or (p_method='paya' and (d->>'iban' is null or d->>'deposit_identifier' is null))
 or (p_method='account_transfer' and d->>'account_number' is null)) then raise exception 'deposit_destination_incomplete';end if;
 return d;
end$$;
create or replace function marketplace_private.toman_deposit_methods(p_admin boolean default false) returns jsonb language sql stable security definer set search_path='' as $$
 select jsonb_agg(jsonb_build_object('id',m.id,'enabled',coalesce(d.enabled,false),
 'reason',case when m.id='gateway' then 'gateway_disabled' when m.id in('instant_bank','direct_debit') then 'integration_unavailable' when coalesce(d.enabled,false) then null else 'destination_not_configured' end,
 'destinations',case when d.id is not null and (p_admin or d.enabled) then jsonb_build_array(d.details||jsonb_build_object('id',d.id,'method',d.method,'enabled',d.enabled,'version',d.version,'updated_at',d.updated_at)) else '[]'::jsonb end) order by m.ordinal)
 from (values('gateway',1),('instant_bank',2),('card_transfer',3),('paya',4),('account_transfer',5),('direct_debit',6)) m(id,ordinal)
 left join marketplace_private.toman_deposit_destinations d on d.method=m.id;
$$;
create or replace function marketplace_private.toman_deposit_json(p marketplace_private.toman_deposit_requests) returns jsonb language sql immutable set search_path='' as $$
 select jsonb_build_object('id',p.id,'request_id',p.request_id,'amount_rial',p.amount_rial::text,'method',p.method,'status',p.status,'version',p.version,
 'destination_id',p.destination_id,'destination_version',p.destination_version,'destination',p.destination_snapshot,'bank_account_id',p.bank_id,'bank',p.bank_snapshot,'transfer_reference',p.transfer_reference,
 'created_at',p.created_at,'updated_at',p.updated_at,'submitted_at',p.submitted_at,'cancelled_at',p.cancelled_at);
$$;
create or replace function marketplace_private.toman_deposit_capture() returns trigger language plpgsql security definer set search_path='' as $$
declare b jsonb:='{}';a jsonb;changed text[];event text;begin
 a:=marketplace_private.toman_deposit_json(new)-'id'-'request_id'-'created_at'-'updated_at'-'version';
 if tg_op='UPDATE' then
  if old.status<>'draft' or new.user_id<>old.user_id or new.id<>old.id or new.request_id<>old.request_id or new.created_at<>old.created_at or new.version<>old.version+1 then raise exception 'deposit_request_immutable';end if;
  b:=marketplace_private.toman_deposit_json(old)-'id'-'request_id'-'created_at'-'updated_at'-'version';
 end if;
 select array_agg(k order by k) into changed from jsonb_object_keys(a||b) k where a->k is distinct from b->k;
 event:=case when new.status='submitted' then 'deposit_submitted' when new.status='cancelled' then 'deposit_cancelled' when tg_op='INSERT' then 'deposit_draft_saved' else 'deposit_draft_changed' end;
 insert into marketplace_private.customer_activity(user_id,category,action,entity,entity_id,before_data,after_data,changed_fields,actor_id,actor_kind,source,source_key)
 values(new.user_id,'wallet',event,'toman_deposit_requests',new.id::text,b,a,coalesce(changed,'{}'),auth.uid(),'customer','toman_deposit','toman-deposit:'||new.id||':'||new.version);
 return new;
end$$;
drop trigger if exists toman_deposit_capture on marketplace_private.toman_deposit_requests;
create trigger toman_deposit_capture before insert or update on marketplace_private.toman_deposit_requests for each row execute function marketplace_private.toman_deposit_capture();

create or replace function public.marketplace_toman_deposit_state(p_before text default null,p_limit integer default 25) returns jsonb language plpgsql security definer set search_path='' as $$
declare uid uuid:=marketplace_private.toman_deposit_customer();cursor_data jsonb;cursor_at timestamptz;cursor_id uuid;items jsonb;next_cursor text;more boolean;draft jsonb;banks jsonb;begin
 if p_limit is null or p_limit not between 1 and 100 then raise exception 'invalid_deposit_filter';end if;
 if p_before is not null then
  begin
   if octet_length(p_before)>200 then raise exception 'invalid_deposit_cursor';end if;
   cursor_data:=p_before::jsonb;
   if jsonb_typeof(cursor_data)<>'object' or (select count(*) from jsonb_object_keys(cursor_data))<>2 or not(cursor_data ?& array['created_at','id'])
   or jsonb_typeof(cursor_data->'created_at')<>'string' or jsonb_typeof(cursor_data->'id')<>'string' then raise exception 'invalid_deposit_cursor';end if;
   cursor_at:=(cursor_data->>'created_at')::timestamptz;cursor_id:=(cursor_data->>'id')::uuid;
   if not isfinite(cursor_at) or not exists(select 1 from marketplace_private.toman_deposit_requests where user_id=uid and id=cursor_id and created_at=cursor_at) then raise exception 'invalid_deposit_cursor';end if;
  exception when others then raise exception 'invalid_deposit_cursor';end;
 end if;
 with page as materialized(select * from marketplace_private.toman_deposit_requests where user_id=uid and(p_before is null or (created_at,id)<(cursor_at,cursor_id)) order by created_at desc,id desc limit p_limit+1),
 shown as(select * from page order by created_at desc,id desc limit p_limit)
 select coalesce((select jsonb_agg(marketplace_private.toman_deposit_json(s) order by s.created_at desc,s.id desc) from shown s),'[]'),
 (select count(*)>p_limit from page),case when (select count(*)>p_limit from page) then (select jsonb_build_object('created_at',created_at,'id',id)::text from shown order by created_at,id limit 1) end
 into items,more,next_cursor;
 select marketplace_private.toman_deposit_json(r) into draft from marketplace_private.toman_deposit_requests r where user_id=uid and status='draft';
 select coalesce(jsonb_agg(jsonb_build_object('id',b.id,'bank_name',b.bank_name,'iban',b.iban,'card_last4',b.card_last4,'status',b.status,'card_link_status',b.card_link_status,'ownership_checked_at',b.ownership_checked_at,
 'eligible',coalesce(b.status='verified' and b.ownership_checked_at is not null and b.ownership_national_id=i.national_id and marketplace_private.national_id_valid(i.national_id) and i.status='verified' and a.verification_status='verified',false)) order by b.is_primary desc,b.created_at desc),'[]') into banks
 from marketplace_private.bank_accounts b left join marketplace_private.accounts a on a.user_id=b.user_id
 left join lateral(select r.status,r.national_id from marketplace_private.identity_requests r where r.user_id=b.user_id order by r.created_at desc,r.id desc limit 1)i on true where b.user_id=uid;
 return jsonb_build_object('methods',marketplace_private.toman_deposit_methods(),'draft',draft,'history',items,'has_more',more,'next_cursor',next_cursor,'bank_accounts',banks,'limits',jsonb_build_object('min_amount_rial','10','max_amount_rial','9999999999990'));
end$$;
create or replace function public.marketplace_toman_deposit_save(p_request uuid,p_amount_rial bigint,p_method text,p_version integer) returns jsonb language plpgsql security definer set search_path='' as $$
declare uid uuid:=marketplace_private.toman_deposit_customer();r marketplace_private.toman_deposit_requests;begin
 if p_request is null or p_amount_rial is null or p_amount_rial not between 10 and 9999999999990 or p_amount_rial%10<>0 or p_method is null or p_method not in('gateway','instant_bank','card_transfer','paya','account_transfer','direct_debit') or p_version is null or p_version<0 then raise exception 'invalid_deposit_request';end if;
 if p_method='gateway' then raise exception 'deposit_method_unavailable';end if;
 perform pg_advisory_xact_lock(hashtextextended('toman-deposit:'||uid,0));
 select * into r from marketplace_private.toman_deposit_requests where user_id=uid and request_id=p_request for update;
 if r.id is not null then
  if r.status<>'draft' then raise exception 'deposit_not_draft';end if;
  if r.amount_rial=p_amount_rial and r.method=p_method and p_version in(r.version,r.version-1) then return jsonb_build_object('request',marketplace_private.toman_deposit_json(r));end if;
  if r.version<>p_version then raise exception 'deposit_version_conflict';end if;
 elsif p_version<>0 then raise exception 'deposit_not_found';
 elsif exists(select 1 from marketplace_private.toman_deposit_requests where user_id=uid and status='draft') then raise exception 'deposit_draft_exists';end if;
 if (select count(*) from marketplace_private.customer_activity where user_id=uid and source='toman_deposit' and created_at>clock_timestamp()-interval '1 hour')>=60 then raise exception 'deposit_rate_limit';end if;
 if r.id is null then
  if (select count(*) from marketplace_private.toman_deposit_requests where user_id=uid and created_at>clock_timestamp()-interval '1 hour')>=10 then raise exception 'deposit_rate_limit';end if;
  insert into marketplace_private.toman_deposit_requests(user_id,request_id,amount_rial,method) values(uid,p_request,p_amount_rial,p_method) returning * into r;
 else update marketplace_private.toman_deposit_requests set amount_rial=p_amount_rial,method=p_method,version=version+1,updated_at=clock_timestamp() where id=r.id returning * into r;end if;
 return jsonb_build_object('request',marketplace_private.toman_deposit_json(r));
end$$;
create or replace function public.marketplace_toman_deposit_cancel(p_request uuid,p_version integer) returns jsonb language plpgsql security definer set search_path='' as $$
declare uid uuid:=marketplace_private.toman_deposit_customer();r marketplace_private.toman_deposit_requests;begin
 if p_request is null or p_version is null or p_version<1 then raise exception 'invalid_deposit_request';end if;
 perform pg_advisory_xact_lock(hashtextextended('toman-deposit:'||uid,0));
 select * into r from marketplace_private.toman_deposit_requests where user_id=uid and request_id=p_request for update;
 if r.id is null then raise exception 'deposit_not_found';end if;
 if r.status='cancelled' and p_version in(r.version,r.version-1) then return jsonb_build_object('request',marketplace_private.toman_deposit_json(r));end if;
 if r.status<>'draft' then raise exception 'deposit_not_draft';end if;
 if r.version<>p_version then raise exception 'deposit_version_conflict';end if;
 update marketplace_private.toman_deposit_requests set status='cancelled',cancelled_at=clock_timestamp(),updated_at=clock_timestamp(),version=version+1 where id=r.id returning * into r;
 return jsonb_build_object('request',marketplace_private.toman_deposit_json(r));
end$$;
create or replace function public.marketplace_toman_deposit_submit(p_request uuid,p_version integer,p_destination uuid,p_destination_version integer,p_bank uuid,p_transfer_reference text) returns jsonb language plpgsql security definer set search_path='' as $$
declare uid uuid:=marketplace_private.toman_deposit_customer();r marketplace_private.toman_deposit_requests;d marketplace_private.toman_deposit_destinations;b marketplace_private.bank_accounts;identity_row marketplace_private.identity_requests;reference_value text:=upper(p_transfer_reference);begin
 if p_request is null or p_version is null or p_version<1 or p_destination is null or p_destination_version is null or p_destination_version<1 or p_bank is null or p_transfer_reference is null or p_transfer_reference!~'^[A-Za-z0-9-]{3,100}$' or p_transfer_reference!~'[A-Za-z0-9]' then raise exception 'invalid_deposit_submission';end if;
 perform pg_advisory_xact_lock(hashtextextended('toman-deposit:'||uid,0));
 select * into r from marketplace_private.toman_deposit_requests where user_id=uid and request_id=p_request for update;
 if r.id is null then raise exception 'deposit_not_found';end if;
 if r.method not in('card_transfer','paya','account_transfer') then raise exception 'deposit_method_unavailable';end if;
 if r.status='submitted' then
  if p_version not in(r.version,r.version-1) or r.destination_id is distinct from p_destination or r.destination_version is distinct from p_destination_version or r.bank_id is distinct from p_bank or r.transfer_reference is distinct from reference_value then raise exception 'deposit_submission_conflict';end if;
  return jsonb_build_object('request',marketplace_private.toman_deposit_json(r));
 end if;
 if r.status<>'draft' then raise exception 'deposit_not_draft';end if;
 if r.version<>p_version then raise exception 'deposit_version_conflict';end if;
 select * into d from marketplace_private.toman_deposit_destinations where id=p_destination and method=r.method for share;
 if d.id is null or not d.enabled then raise exception 'deposit_method_unavailable';end if;
 if d.version<>p_destination_version then raise exception 'deposit_destination_changed';end if;
 perform marketplace_private.toman_deposit_details(d.method,true,d.details);
 select * into identity_row from marketplace_private.identity_requests where user_id=uid order by created_at desc,id desc limit 1 for share;
 if identity_row.status is distinct from 'verified' or not marketplace_private.national_id_valid(identity_row.national_id) or not exists(select 1 from marketplace_private.accounts where user_id=uid and verification_status='verified') then raise exception 'deposit_identity_required';end if;
 select * into b from marketplace_private.bank_accounts where id=p_bank and user_id=uid for share;
 if b.id is null or b.status is distinct from 'verified' or b.ownership_checked_at is null or b.ownership_national_id is distinct from identity_row.national_id or (r.method='card_transfer' and b.card_link_status is distinct from 'verified') then raise exception 'deposit_verified_bank_required';end if;
 perform pg_advisory_xact_lock(hashtextextended('toman-transfer:'||d.id||':'||reference_value,0));
 if exists(select 1 from marketplace_private.toman_deposit_requests where destination_id=d.id and transfer_reference=reference_value and status='submitted') then raise exception 'deposit_transfer_reference_used';end if;
 update marketplace_private.toman_deposit_requests set status='submitted',submitted_at=clock_timestamp(),updated_at=clock_timestamp(),version=version+1,
 destination_id=d.id,destination_version=d.version,destination_snapshot=d.details,
 bank_id=b.id,bank_snapshot=jsonb_build_object('id',b.id,'bank_name',b.bank_name,'iban_last4',right(b.iban,4),'card_last4',b.card_last4),transfer_reference=reference_value where id=r.id returning * into r;
 insert into marketplace_private.notifications(user_id,event_key,title,body,kind,severity,action_url,sender_name)
 values(uid,'toman-deposit-submitted:'||r.id,jsonb_build_object('fa','درخواست بررسی واریز ثبت شد','en','Deposit review request received','ar','تم استلام طلب مراجعة الإيداع'),
 jsonb_build_object('fa','درخواست شما برای بررسی ثبت شد. موجودی کیف پول فقط پس از تطبیق واقعی تراکنش بانکی افزایش می‌یابد.','en','Your transfer claim is pending review. The wallet balance changes only after a verified bank payment.','ar','طلب التحويل قيد المراجعة. لا يتغير رصيد المحفظة إلا بعد التحقق من الدفع البنكي.'),'wallet','info','/wallet/deposit','پشتیبانی پلانک');
 return jsonb_build_object('request',marketplace_private.toman_deposit_json(r));
end$$;

create or replace function public.marketplace_admin_toman_deposit_settings() returns jsonb language plpgsql security definer set search_path='' as $$
begin
 if public.marketplace_role() is distinct from 'owner' then raise exception 'not_authorized' using errcode='42501';end if;
 return jsonb_build_object('methods',marketplace_private.toman_deposit_methods(true));
end$$;
create or replace function public.marketplace_admin_toman_deposit_configure(p_method text,p_version integer,p_enabled boolean,p_details jsonb) returns jsonb language plpgsql security definer set search_path='' as $$
declare d marketplace_private.toman_deposit_destinations;validated_details jsonb;before_value jsonb;after_value jsonb;begin
 if public.marketplace_role() is distinct from 'owner' then raise exception 'not_authorized' using errcode='42501';end if;
 if p_version is null or p_version<1 then raise exception 'invalid_deposit_destination';end if;
 validated_details:=marketplace_private.toman_deposit_details(p_method,p_enabled,p_details);
 select * into d from marketplace_private.toman_deposit_destinations where method=p_method for update;
 if d.id is null then raise exception 'deposit_method_unavailable';end if;
 if d.enabled=p_enabled and d.details=validated_details and p_version in(d.version,d.version-1) then return public.marketplace_admin_toman_deposit_settings();end if;
 if d.version<>p_version then raise exception 'deposit_destination_version_conflict';end if;
 before_value:=jsonb_build_object('enabled',d.enabled,'details',d.details,'version',d.version);
 update marketplace_private.toman_deposit_destinations set enabled=p_enabled,details=validated_details,version=version+1,updated_at=clock_timestamp(),updated_by=auth.uid() where id=d.id returning * into d;
 after_value:=jsonb_build_object('enabled',d.enabled,'details',d.details,'version',d.version);
 insert into marketplace_private.toman_deposit_destination_history(destination_id,version,before_data,after_data,actor_id) values(d.id,d.version,before_value,after_value,auth.uid());
 insert into marketplace_private.audit_log(actor,entity,record_id,operation) values(auth.uid(),'toman_deposit_destinations',d.id::text,'deposit_destination_configured');
 return public.marketplace_admin_toman_deposit_settings();
end$$;
-- Extend title search without replacing earlier inquiry/login/title behavior.
do $$declare definition text;marker text:='case lower(p_action)';replacement text:='case lower(p_action)
 when ''deposit_draft_saved'' then ''ذخیره پیش‌نویس واریز تومان''
 when ''deposit_draft_changed'' then ''تغییر پیش‌نویس واریز تومان''
 when ''deposit_submitted'' then ''ارسال درخواست بررسی واریز تومان''
 when ''deposit_cancelled'' then ''لغو پیش‌نویس واریز تومان''';begin
 select pg_get_functiondef('marketplace_private.customer_activity_title(text,text)'::regprocedure) into definition;
 if position('deposit_draft_saved' in definition)=0 then
  if position(marker in definition)=0 then raise exception 'deposit_activity_title_contract_missing';end if;
  execute overlay(definition placing replacement from position(marker in definition) for length(marker));
 end if;
end$$;
-- A generic profile/activity approval is not financial reconciliation.
-- Keep all prior review exclusions and disallow this new entity on that approval path.
do $$declare definition text;marker text:='select coalesce(p_actor_kind<>''admin'',false)';begin
 select pg_get_functiondef('marketplace_private.customer_activity_reviewable(text,text,text)'::regprocedure) into definition;
 if position('toman_deposit_requests' in definition)=0 then
  if position(marker in definition)=0 then raise exception 'deposit_activity_review_contract_missing';end if;
  execute replace(definition,marker,'select p_entity is distinct from ''toman_deposit_requests'' and coalesce(p_actor_kind<>''admin'',false)');
 end if;
end$$;
do $$declare f record;begin
 for f in select p.oid::regprocedure as signature from pg_proc p join pg_namespace n on n.oid=p.pronamespace where n.nspname='marketplace_private' and p.proname like 'toman_deposit_%' loop execute format('revoke all on function %s from public,anon,authenticated,service_role',f.signature);end loop;
end$$;
revoke all on function public.marketplace_toman_deposit_state(text,integer),public.marketplace_toman_deposit_save(uuid,bigint,text,integer),public.marketplace_toman_deposit_cancel(uuid,integer),public.marketplace_toman_deposit_submit(uuid,integer,uuid,integer,uuid,text),public.marketplace_admin_toman_deposit_settings(),public.marketplace_admin_toman_deposit_configure(text,integer,boolean,jsonb) from public,anon,authenticated,service_role;
grant execute on function public.marketplace_toman_deposit_state(text,integer),public.marketplace_toman_deposit_save(uuid,bigint,text,integer),public.marketplace_toman_deposit_cancel(uuid,integer),public.marketplace_toman_deposit_submit(uuid,integer,uuid,integer,uuid,text),public.marketplace_admin_toman_deposit_settings(),public.marketplace_admin_toman_deposit_configure(text,integer,boolean,jsonb) to authenticated;
comment on table marketplace_private.toman_deposit_requests is 'Customer deposit drafts and unverified transfer claims only. Submitted never means bank-confirmed or credited. Gateway, instant bank and direct debit remain unavailable.';
comment on table marketplace_private.toman_deposit_destination_history is 'Immutable history of owner/AAL2 receiving-account configuration. Empty disabled defaults contain no fabricated receiving account.';
notify pgrst,'reload schema';
commit;
