-- LA VENTA DE CAJA LLEGA COMPLETA: total de verdad y origen.
--
-- (1) El Cerebrito mandaba subtotal_usd pero NO total_usd, y el coalesce lo
--     dejaba en $0: toda venta de caja sincronizada quedaba con total cero en
--     la nube (reportes del panel y cola fiscal). Encontrado leyendo el codigo
--     al armar el puente con la Estacion; en vivo no habia ni una venta '-L'
--     sincronizada todavia, asi que no hay datos que reparar. Desde ahora el
--     total cae al subtotal si no vino (la venta local no lleva delivery), y
--     el Cerebrito nuevo ademas lo manda explicito.
--
-- (2) origen='caja': las ventas del salon local SON ventas de caja. Con esto el
--     documento fiscal sale con canal 'caja' por las DOS vias (la directa del
--     Cerebrito a la Estacion y la cola de la nube), en vez de disfrazarse de
--     pickup, y el panel las distingue igual que las del punto de venta web.

create or replace function public.sincronizar_venta_local(p_venta jsonb)
returns jsonb
language plpgsql
security definer
set search_path to 'public'
as $function$
declare
  v_rest uuid := fn_mi_restaurante();
  v_cuenta_id uuid;
  v_ped jsonb;
  v_item jsonb;
  v_pago jsonb;
  v_rc integer;
  n_pedidos integer := 0;
  n_pagos integer := 0;
begin
  if v_rest is null or not fn_es_staff_de(v_rest) then
    raise exception 'Sin permiso';
  end if;

  -- Cuenta de mesa (solo en ventas de salon); llega YA cerrada.
  if p_venta ? 'cuenta' then
    v_cuenta_id := (p_venta->'cuenta'->>'id')::uuid;
    insert into public.cuentas_mesa (id, restaurante_id, mesa, estado, abierta_en, cerrada_en, mesero_nombre)
    values (
      v_cuenta_id,
      v_rest,
      p_venta->'cuenta'->>'mesa',
      'cerrada',
      coalesce((p_venta->'cuenta'->>'abierta_en')::timestamptz, now()),
      coalesce((p_venta->'cuenta'->>'cerrada_en')::timestamptz, now()),
      nullif(p_venta->'cuenta'->>'mesero_nombre', '')
    )
    on conflict (id) do nothing;
  end if;

  for v_ped in select * from jsonb_array_elements(coalesce(p_venta->'pedidos', '[]'::jsonb)) loop
    insert into public.pedidos (
      id, restaurante_id, codigo, cliente_nombre, cliente_telefono, tipo_entrega, mesa, para_llevar,
      estado, metodo_pago, nota, subtotal_usd, total_usd, tasa_bs, cuenta_id, mesero_nombre, origen,
      recibido_en, confirmado_en, entregado_en
    )
    values (
      (v_ped->>'id')::uuid,
      v_rest,
      v_ped->>'codigo',
      coalesce(nullif(v_ped->>'cliente_nombre', ''), 'Cliente'),
      '',
      coalesce(nullif(v_ped->>'tipo_entrega', ''), 'mesa'),
      nullif(v_ped->>'mesa', ''),
      coalesce((v_ped->>'para_llevar')::boolean, false),
      'entregado',
      nullif(v_ped->>'metodo_pago', ''),
      nullif(v_ped->>'nota', ''),
      coalesce((v_ped->>'subtotal_usd')::numeric, 0),
      -- El total cae al subtotal si no vino: las versiones viejas del
      -- Cerebrito no lo mandaban y quedaba en $0.
      coalesce((v_ped->>'total_usd')::numeric, (v_ped->>'subtotal_usd')::numeric, 0),
      nullif(v_ped->>'tasa_bs', '')::numeric,
      v_cuenta_id,
      nullif(v_ped->>'mesero_nombre', ''),
      'caja',
      coalesce((v_ped->>'recibido_en')::timestamptz, now()),
      coalesce((v_ped->>'confirmado_en')::timestamptz, now()),
      coalesce((v_ped->>'entregado_en')::timestamptz, now())
    )
    on conflict (id) do nothing;
    get diagnostics v_rc = row_count;
    n_pedidos := n_pedidos + v_rc;

    for v_item in select * from jsonb_array_elements(coalesce(v_ped->'items', '[]'::jsonb)) loop
      insert into public.pedido_items (id, pedido_id, producto_id, nombre, precio_usd, cantidad, nota)
      values (
        (v_item->>'id')::uuid,
        (v_ped->>'id')::uuid,
        nullif(v_item->>'producto_id', '')::uuid,
        v_item->>'nombre',
        coalesce((v_item->>'precio_usd')::numeric, 0),
        greatest(coalesce((v_item->>'cantidad')::int, 1), 1),
        nullif(v_item->>'nota', '')
      )
      on conflict (id) do nothing;
    end loop;
  end loop;

  for v_pago in select * from jsonb_array_elements(coalesce(p_venta->'pagos', '[]'::jsonb)) loop
    if v_cuenta_id is not null then
      insert into public.pagos_mesa (id, cuenta_id, restaurante_id, monto_usd, metodo, referencia, propina_usd, verificado, mesero_nombre)
      values (
        (v_pago->>'id')::uuid,
        v_cuenta_id,
        v_rest,
        coalesce((v_pago->>'monto_usd')::numeric, 0),
        coalesce(nullif(v_pago->>'metodo', ''), 'efectivo'),
        nullif(v_pago->>'referencia', ''),
        nullif(v_pago->>'propina_usd', '')::numeric,
        coalesce(nullif(v_pago->>'metodo', ''), 'efectivo') = 'efectivo',
        nullif(v_pago->>'mesero_nombre', '')
      )
      on conflict (id) do nothing;
    else
      insert into public.pagos (id, pedido_id, metodo, monto_usd, referencia, estado)
      values (
        (v_pago->>'id')::uuid,
        (v_pago->>'pedido_id')::uuid,
        coalesce(nullif(v_pago->>'metodo', ''), 'efectivo'),
        coalesce((v_pago->>'monto_usd')::numeric, 0),
        nullif(v_pago->>'referencia', ''),
        'confirmado'
      )
      on conflict (id) do nothing;
    end if;
    get diagnostics v_rc = row_count;
    n_pagos := n_pagos + v_rc;
  end loop;

  return jsonb_build_object('ok', true, 'pedidos_nuevos', n_pedidos, 'pagos_nuevos', n_pagos);
end;
$function$;
