0

I'm trying to make a query, and it keeps bringing something that I don't want. I have a db with users, each user has contracts. Those contracts could be active or past due. When I try to search for the users I want to bring the latest contract they have, to see if that user’s latest contract is active o past due. This is my code:

Everything works except when I try to search for users that their latest contract is past due, because if a user has 2 or more contracts and 1 of them is still active, when I apply my filter for "vencido" it brings that that user with a contract that is past due.

Is there something I'm missing?

Let me know if you need more explanation.

export async function obtenerUsuariosPaginados(
  params: PaginationParams
): Promise<PaginatedResponse<Usuario & { contracts?: Contrato[] }>> {
  const { page, pageSize, search, estado, tipo } = params;
  const start = (page - 1) * pageSize;

  // Base query
  let query = supabase()
    .from("users")
    .select("*, contracts(*)", { count: "exact" })
    .order("apellido", { ascending: true })
    .not("contracts", "is", null) // Only include users with contracts
    .order("fecha_final", {
      ascending: false,
      referencedTable: "contracts",
    }) // Get latest contract first
    .limit(1, { referencedTable: "contracts" }); // Fetch only the latest contract per user

  // Apply search filter
  if (search) {
    const searchLower = search?.toLowerCase();
    query = query.or(
      `apellido.ilike.%${searchLower}%,nombre.ilike.%${searchLower}%,legajo.ilike.%${searchLower}%,cuil.ilike.%${searchLower}%`
    );
  }

  // Apply contract status filter
  const now = new Date().toISOString();
  if (estado) {
    if (estado === "activo") {
      query = query
        .lte("contracts.fecha_inicio", now)
        .gte("contracts.fecha_final", now);
    } else if (estado === "renovar") {
      const twoMonthsBeforeEnd = addMonths(new Date(), 2).toISOString();
      query = query
        .lte("contracts.fecha_inicio", now)
        .lte("contracts.fecha_final", twoMonthsBeforeEnd)
        .gte("contracts.fecha_final", now);
    } else if (estado === "vencido") {
      query = query
        .lt("contracts.fecha_final", now) // Contract is expired
        .not("contracts.fecha_final", "gte", now); // Ensure no newer active contract exists
    }
  }

  // Apply contract type filter
  if (tipo) {
    query = query.eq("contracts.tipo", tipo?.toLowerCase());
  }

  // Apply pagination
  const { data, error, count } = await query.range(start, start + pageSize - 1);

  if (error) throw error;

  const totalPages = Math.ceil((count ?? 0) / pageSize);

  return {
    data: data.map((item) => ({
      ...item,
    })) as (Usuario & { contracts?: Contrato[] })[],
    total: count ?? 0,
    page,
    pageSize,
    totalPages,
  };
}

If estado is "vencido", if a user has 2 o more contracts and the latest is still active, I don't want that user in the end result.

2
  • Can you please share sample output to help debug Commented Feb 9 at 13:32
  • The output I'm getting is an array of users with only one contract, the thing is that the user that has 2 contracts which one of them is active and the other one isn't, in the final result is showing with the past due contract, instead of not showing at all. Commented Feb 9 at 16:24

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.