> ## Documentation Index
> Fetch the complete documentation index at: https://docs.quentli.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Filtro de descuentos

> Campos y operadores disponibles para filtrar descuentos.

export const ListFilterBuilder = ({filterType} = {}) => {
  const operatorLabels = {
    contains: 'Contiene',
    endsWith: 'Termina con',
    equals: 'Es igual a',
    gt: 'Es posterior a',
    gte: 'Es igual o posterior a',
    in: 'Es uno de',
    lt: 'Es anterior a',
    lte: 'Es igual o anterior a',
    not: 'No es',
    notIn: 'No es uno de',
    search: 'Busca',
    startsWith: 'Empieza con'
  };
  const [filterId, setFilterId] = useState(filterType ?? listFilterBuilderOptions[0].id);
  const selectedFilter = listFilterBuilderOptions.find(filter => filter.id === filterId) ?? listFilterBuilderOptions[0];
  const fields = selectedFilter.fields;
  const operatorsFor = field => {
    const operators = field.operators.map(operator => [operator, operatorLabels[operator] ?? operator]);
    if (field.type === 'scalar' && field.nullable && field.operators.includes('equals')) {
      operators.unshift(['isNull', 'No tiene valor']);
    }
    return operators;
  };
  const createRule = field => ({
    field: field.key,
    operator: operatorsFor(field)[0]?.[0] ?? '',
    value: ''
  });
  const [logic, setLogic] = useState('AND');
  const [rules, setRules] = useState([createRule(fields[0])]);
  const [advancedFilter, setAdvancedFilter] = useState('');
  const [copied, setCopied] = useState(false);
  const selectFilter = id => {
    const nextFilter = listFilterBuilderOptions.find(filter => filter.id === id) ?? listFilterBuilderOptions[0];
    setFilterId(nextFilter.id);
    setLogic('AND');
    setRules([createRule(nextFilter.fields[0])]);
    setAdvancedFilter('');
    setCopied(false);
  };
  const updateRule = (index, property, value) => {
    setRules(current => current.map((rule, ruleIndex) => {
      if (ruleIndex !== index) return rule;
      if (property !== 'field') return {
        ...rule,
        [property]: value
      };
      const field = fields.find(candidate => candidate.key === value);
      return createRule(field);
    }));
  };
  const addRule = () => setRules(current => [...current, createRule(fields[0])]);
  const removeRule = index => setRules(current => current.filter((rule, ruleIndex) => ruleIndex !== index));
  const filterRules = rules.map(rule => {
    const field = fields.find(candidate => candidate.key === rule.field);
    if (rule.operator === 'isNull') return {
      [field.key]: {
        equals: null
      }
    };
    if (!rule.value) return null;
    const value = field.type === 'boolean' ? rule.value === 'true' : rule.value.trim();
    if (field.type !== 'boolean' && !value) return null;
    if (rule.operator === 'in' || rule.operator === 'notIn') {
      const values = rule.value.split(',').map(value => value.trim()).filter(Boolean);
      return values.length ? {
        [field.key]: {
          [rule.operator]: values
        }
      } : null;
    }
    return rule.operator ? {
      [field.key]: {
        [rule.operator]: value
      }
    } : {
      [field.key]: value
    };
  }).filter(Boolean);
  let filter;
  let advancedFilterError = '';
  if (advancedFilter.trim()) {
    try {
      const parsedFilter = JSON.parse(advancedFilter);
      if (!parsedFilter || typeof parsedFilter !== 'object' || Array.isArray(parsedFilter)) {
        advancedFilterError = 'El filtro avanzado debe ser un objeto JSON.';
      } else {
        filter = parsedFilter;
      }
    } catch {
      advancedFilterError = 'El filtro avanzado debe ser JSON válido.';
    }
  } else if (filterRules.length === 1) {
    filter = filterRules[0];
  } else if (filterRules.length > 1) {
    filter = selectedFilter.allowsLogicalGroups ? {
      [logic]: filterRules
    } : Object.assign({}, ...filterRules);
  }
  const appendQueryParameter = (parts, key, value) => {
    if (value === null) {
      parts.push(key);
    } else if (Array.isArray(value)) {
      value.forEach((item, index) => appendQueryParameter(parts, `${key}[${index}]`, item));
    } else if (typeof value === 'object') {
      Object.entries(value).forEach(([childKey, childValue]) => {
        appendQueryParameter(parts, `${key}[${childKey}]`, childValue);
      });
    } else {
      parts.push(`${key}=${encodeURIComponent(String(value))}`);
    }
  };
  const parts = [];
  if (filter) appendQueryParameter(parts, 'filter', filter);
  const query = parts.join('&');
  const request = `GET ${selectedFilter.path}${query ? `?${query}` : ''}`;
  const copyQuery = async () => {
    if (!query) return;
    try {
      await navigator.clipboard.writeText(query);
      setCopied(true);
      window.setTimeout(() => setCopied(false), 2000);
    } catch {
      setCopied(false);
    }
  };
  return <div className="not-prose my-6 rounded-xl border border-zinc-950/15 bg-zinc-50 p-5 dark:border-white/15 dark:bg-white/5">
      <div className="mb-5 flex flex-wrap items-end justify-between gap-3">
        <div>
          <p className="text-sm font-semibold text-zinc-950 dark:text-white">Constructor de filtros</p>
          <p className="mt-1 text-sm text-zinc-950/65 dark:text-white/65">
            Genera un query string para <code>GET {selectedFilter.path}</code> con <code>{selectedFilter.id}</code>.
          </p>
        </div>
        {filterType ? null : <label className="min-w-56 text-xs font-medium text-zinc-950/70 dark:text-white/70">
            Recurso
            <select value={selectedFilter.id} onChange={event => selectFilter(event.target.value)} className="mt-1 block w-full rounded-md border border-zinc-950/20 bg-white px-2 py-1.5 text-sm text-zinc-950 focus:border-[#4854bb] focus:outline-none focus:ring-2 focus:ring-[#4854bb]/20 dark:border-white/20 dark:bg-zinc-900 dark:text-white">
              {listFilterBuilderOptions.map(filter => <option key={filter.id} value={filter.id}>{filter.label}</option>)}
            </select>
          </label>}
        {rules.length > 1 && selectedFilter.allowsLogicalGroups ? <label className="flex items-center gap-2 text-sm font-medium text-zinc-950 dark:text-white">
          Combinar con
          <select value={logic} onChange={event => setLogic(event.target.value)} className="rounded-md border border-zinc-950/20 bg-white px-2 py-1.5 text-sm focus:border-[#4854bb] focus:outline-none focus:ring-2 focus:ring-[#4854bb]/20 dark:border-white/20 dark:bg-zinc-900">
            <option value="AND">AND</option>
            <option value="OR">OR</option>
          </select>
        </label> : null}
      </div>

      <div className="space-y-3">
        {rules.map((rule, index) => {
    const field = fields.find(candidate => candidate.key === rule.field);
    const operators = operatorsFor(field);
    const acceptsList = rule.operator === 'in' || rule.operator === 'notIn';
    const selectsEnum = field.type === 'enum' && !acceptsList && rule.operator !== 'isNull';
    return <div key={index} className="flex flex-wrap items-end gap-2 rounded-lg border border-zinc-950/10 bg-white p-3 dark:border-white/10 dark:bg-zinc-900">
              <label className="min-w-36 flex-1 text-xs font-medium text-zinc-950/70 dark:text-white/70">
                Campo
                <select value={rule.field} onChange={event => updateRule(index, 'field', event.target.value)} className="mt-1 block w-full rounded-md border border-zinc-950/20 bg-white px-2 py-1.5 text-sm text-zinc-950 focus:border-[#4854bb] focus:outline-none focus:ring-2 focus:ring-[#4854bb]/20 dark:border-white/20 dark:bg-zinc-950 dark:text-white">
                  {fields.map(option => <option key={option.key} value={option.key}>{option.key}</option>)}
                </select>
              </label>

              {field.type !== 'boolean' && field.operators.length > 0 && <label className="min-w-36 flex-1 text-xs font-medium text-zinc-950/70 dark:text-white/70">
                  Operador
                  <select value={rule.operator} onChange={event => updateRule(index, 'operator', event.target.value)} className="mt-1 block w-full rounded-md border border-zinc-950/20 bg-white px-2 py-1.5 text-sm text-zinc-950 focus:border-[#4854bb] focus:outline-none focus:ring-2 focus:ring-[#4854bb]/20 dark:border-white/20 dark:bg-zinc-950 dark:text-white">
                    {operators.map(([value, label]) => <option key={value} value={value}>{label}</option>)}
                  </select>
                </label>}

              {field.type === 'boolean' ? <label className="min-w-36 flex-1 text-xs font-medium text-zinc-950/70 dark:text-white/70">
                  Valor
                  <select value={rule.value} onChange={event => updateRule(index, 'value', event.target.value)} className="mt-1 block w-full rounded-md border border-zinc-950/20 bg-white px-2 py-1.5 text-sm text-zinc-950 focus:border-[#4854bb] focus:outline-none focus:ring-2 focus:ring-[#4854bb]/20 dark:border-white/20 dark:bg-zinc-950 dark:text-white">
                    <option value="">Elige un valor</option>
                    <option value="true">Sí</option>
                    <option value="false">No</option>
                  </select>
                </label> : rule.operator === 'isNull' ? <p className="min-w-36 flex-1 pb-2 text-sm text-zinc-950/60 dark:text-white/60">No se necesita un valor.</p> : selectsEnum ? <label className="min-w-36 flex-1 text-xs font-medium text-zinc-950/70 dark:text-white/70">
                  Valor
                  <select value={rule.value} onChange={event => updateRule(index, 'value', event.target.value)} className="mt-1 block w-full rounded-md border border-zinc-950/20 bg-white px-2 py-1.5 text-sm text-zinc-950 focus:border-[#4854bb] focus:outline-none focus:ring-2 focus:ring-[#4854bb]/20 dark:border-white/20 dark:bg-zinc-950 dark:text-white">
                    <option value="">Elige un valor</option>
                    {field.values.map(value => <option key={value} value={value}>{value}</option>)}
                  </select>
                </label> : <label className="min-w-36 flex-1 text-xs font-medium text-zinc-950/70 dark:text-white/70">
                  {acceptsList ? 'Valores separados por coma' : 'Valor'}
                  <input type="text" value={rule.value} onChange={event => updateRule(index, 'value', event.target.value)} placeholder={field.dateTime ? '2026-01-01T00:00:00.000Z' : acceptsList ? 'VIP, Prioridad' : 'Escribe un valor'} className="mt-1 block w-full rounded-md border border-zinc-950/20 bg-white px-2 py-1.5 text-sm text-zinc-950 focus:border-[#4854bb] focus:outline-none focus:ring-2 focus:ring-[#4854bb]/20 dark:border-white/20 dark:bg-zinc-950 dark:text-white" />
                </label>}

              <button type="button" onClick={() => removeRule(index)} disabled={rules.length === 1} className="shrink-0 rounded-md px-2 py-1.5 text-sm text-zinc-950/70 hover:bg-zinc-950/5 disabled:cursor-not-allowed disabled:opacity-40 dark:text-white/70 dark:hover:bg-white/10" aria-label="Eliminar condición">
                Eliminar
              </button>
            </div>;
  })}
      </div>

      <div className="mt-4 flex flex-wrap items-center gap-3">
        <button type="button" onClick={addRule} className="rounded-md border border-[#4854bb]/35 px-3 py-1.5 text-sm font-medium text-[#4854bb] hover:bg-[#4854bb]/10 dark:border-[#4854bb]/70 dark:text-[#8f98ed] dark:hover:bg-[#4854bb]/20">
          Agregar condición
        </button>
        <button type="button" onClick={copyQuery} disabled={!query} className="rounded-md bg-[#4854bb] px-3 py-1.5 text-sm font-medium text-white hover:bg-[#3d47a1] disabled:cursor-not-allowed disabled:opacity-40">
          {copied ? 'Copiado' : 'Copiar query'}
        </button>
        <span aria-live="polite" className="text-sm text-zinc-950/60 dark:text-white/60">
          {copied ? 'Pega el query en el playground del endpoint.' : ''}
        </span>
      </div>

      {!selectedFilter.allowsLogicalGroups && rules.length > 1 ? <p className="mt-3 text-sm text-zinc-950/60 dark:text-white/60">
          Este esquema no admite grupos <code>AND</code> ni <code>OR</code>; las condiciones se envían al nivel raíz.
        </p> : null}

      <label className="mt-5 block text-xs font-medium text-zinc-950/70 dark:text-white/70">
        Filtro en JSON
        <textarea value={advancedFilter} onChange={event => setAdvancedFilter(event.target.value)} placeholder={'{\n  "tags": { "some": { "name": { "equals": "VIP" } } }\n}'} rows={5} className="mt-1 block w-full rounded-md border border-zinc-950/20 bg-white px-3 py-2 font-mono text-xs text-zinc-950 focus:border-[#4854bb] focus:outline-none focus:ring-2 focus:ring-[#4854bb]/20 dark:border-white/20 dark:bg-zinc-950 dark:text-white" />
      </label>
      <p className="mt-2 text-sm text-zinc-950/60 dark:text-white/60">
        Úsalo el filtro en JSON para relaciones, arreglos, metadatos o grupos anidados.
      </p>
      {advancedFilterError ? <p className="mt-2 text-sm text-red-700 dark:text-red-300">{advancedFilterError}</p> : null}

      <pre className="mt-4 overflow-x-auto rounded-lg bg-zinc-950 p-3 text-xs text-zinc-50 dark:bg-black"><code>{request}</code></pre>
    </div>;
};

export const listFilterBuilderOptions = [{
  "allowsLogicalGroups": true,
  "id": "CustomerFilter",
  "label": "Clientes",
  "path": "/v1/customers",
  "fields": [{
    "key": "id",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "createdAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "updatedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "name",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "archivedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": true,
    "dateTime": true
  }, {
    "key": "email",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "phoneNumber",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "secondaryPhoneNumber",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "username",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "noPayments",
    "type": "boolean",
    "operators": []
  }, {
    "key": "hasTaxProfiles",
    "type": "boolean",
    "operators": []
  }]
}, {
  "allowsLogicalGroups": true,
  "id": "ConceptFilter",
  "label": "Conceptos de pago",
  "path": "/v1/payment-concepts",
  "fields": [{
    "key": "term",
    "type": "scalar",
    "operators": [],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "id",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "createdAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "updatedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "displayName",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "sku",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "description",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "active",
    "type": "boolean",
    "operators": ["equals"]
  }, {
    "key": "amount",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "archivedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": true,
    "dateTime": true
  }, {
    "key": "archivedById",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "recurrentDetailId",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": true,
    "dateTime": false
  }, {
    "key": "groupId",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": true,
    "dateTime": false
  }]
}, {
  "allowsLogicalGroups": true,
  "id": "DiscountFilter",
  "label": "Descuentos",
  "path": "/v1/discounts",
  "fields": [{
    "key": "id",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "createdAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "updatedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "deletedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": true,
    "dateTime": true
  }, {
    "key": "name",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "description",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": true,
    "dateTime": false
  }, {
    "key": "type",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "amountOff",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "percentageOff",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "active",
    "type": "boolean",
    "operators": ["equals"]
  }, {
    "key": "oneOff",
    "type": "boolean",
    "operators": ["equals"]
  }, {
    "key": "expiresAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": true,
    "dateTime": true
  }]
}, {
  "allowsLogicalGroups": true,
  "id": "InvoiceFilter",
  "label": "Solicitudes de pago",
  "path": "/v1/invoices",
  "fields": [{
    "key": "id",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "isPaid",
    "type": "boolean",
    "operators": []
  }, {
    "key": "canceledAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": true,
    "dateTime": true
  }, {
    "key": "canceledById",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "createdAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "updatedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "dueDate",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "expireDate",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": true,
    "dateTime": true
  }, {
    "key": "subscriptionId",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "customerId",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "refundedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": true,
    "dateTime": true
  }, {
    "key": "refundedById",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "collectionMethod",
    "type": "enum",
    "operators": [],
    "values": ["AUTOMATIC", "SEND_REMINDER", "NONE"]
  }]
}, {
  "allowsLogicalGroups": true,
  "id": "TaxInvoiceFilter",
  "label": "Facturas fiscales",
  "path": "/v1/tax-invoices",
  "fields": [{
    "key": "id",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "createdAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "updatedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "issueDate",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "customerId",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "taxId",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "isPublicInvoice",
    "type": "boolean",
    "operators": []
  }, {
    "key": "folio",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "canceledAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "canceledById",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "uuid",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "status",
    "type": "enum",
    "operators": [],
    "values": ["VALID", "CANCELED", "PENDING", "DRAFT", "PENDING_CANCELLATION", "FAILED"]
  }, {
    "key": "cancellationStatus",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "usage",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "paymentMethod",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "paymentForm",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "type",
    "type": "enum",
    "operators": [],
    "values": ["TAX_RECEIPT", "TAX_INVOICE_PPD", "TAX_INVOICE_PUE"]
  }]
}, {
  "allowsLogicalGroups": true,
  "id": "SubscriptionFilter",
  "label": "Suscripciones",
  "path": "/v1/subscriptions",
  "fields": [{
    "key": "id",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "createdAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "updatedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "description",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "customerId",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "collectionMethod",
    "type": "enum",
    "operators": [],
    "values": ["AUTOMATIC", "SEND_REMINDER", "NONE"]
  }, {
    "key": "paymentMethodId",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "nextCollectionDate",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": true,
    "dateTime": true
  }, {
    "key": "firstCollectionDate",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "lastCollectionDate",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": true,
    "dateTime": true
  }, {
    "key": "generationMode",
    "type": "enum",
    "operators": [],
    "values": ["MANUAL", "AUTO"]
  }, {
    "key": "onlyAutomaticCollection",
    "type": "boolean",
    "operators": ["equals"]
  }, {
    "key": "isActive",
    "type": "boolean",
    "operators": ["equals"]
  }, {
    "key": "isCompleted",
    "type": "boolean",
    "operators": ["equals"]
  }, {
    "key": "status",
    "type": "enum",
    "operators": [],
    "values": ["INACTIVE", "ACTIVE", "CANCELED", "COMPLETED"]
  }, {
    "key": "customCancelReason",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }]
}, {
  "allowsLogicalGroups": true,
  "id": "PaymentFilter",
  "label": "Pagos",
  "path": "/v1/payments",
  "fields": [{
    "key": "id",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "createdAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "updatedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "amount",
    "type": "scalar",
    "operators": [],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "status",
    "type": "enum",
    "operators": ["equals", "not", "in", "notIn"],
    "values": ["INCOMPLETE", "COMPLETE", "CANCELED", "INITIATED", "REFUNDED", "DISPUTED", "REVERTED"]
  }, {
    "key": "isCompleted",
    "type": "boolean",
    "operators": []
  }, {
    "key": "skipTaxInvoice",
    "type": "boolean",
    "operators": []
  }, {
    "key": "paymentTime",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "type",
    "type": "enum",
    "operators": ["equals", "not", "in", "notIn"],
    "values": ["TRANSFER", "CARD", "OXXO", "OTHER", "CASH", "DIRECT_DEBIT"]
  }, {
    "key": "payoutId",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "customerId",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "authorizationCode",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "hasRelatedInvoice",
    "type": "boolean",
    "operators": []
  }, {
    "key": "paymentConceptId",
    "type": "scalar",
    "operators": [],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "paymentConceptGroupIds",
    "type": "scalar",
    "operators": [],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "origin",
    "type": "enum",
    "operators": ["equals", "in", "notIn"],
    "values": ["INVOICE", "LISTING", "API"]
  }]
}, {
  "allowsLogicalGroups": false,
  "id": "WebhookFilter",
  "label": "Webhooks",
  "path": "/v1/webhooks",
  "fields": [{
    "key": "id",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "url",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "status",
    "type": "enum",
    "operators": [],
    "values": ["ENABLED", "DISABLED", "BROKEN", "DELETED"]
  }, {
    "key": "createdAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "updatedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }]
}, {
  "allowsLogicalGroups": true,
  "id": "WebhookEventFilter",
  "label": "Eventos de webhook",
  "path": "/v1/webhook-events",
  "fields": [{
    "key": "id",
    "type": "scalar",
    "operators": ["equals", "in", "notIn", "lt", "lte", "gt", "gte", "contains", "startsWith", "endsWith", "search"],
    "nullable": false,
    "dateTime": false
  }, {
    "key": "type",
    "type": "enum",
    "operators": ["equals", "not", "in", "notIn"],
    "values": ["INVOICE_CREATED", "INVOICE_CANCELED", "INVOICE_PAID", "INVOICE_PAID_OTHER", "INVOICE_UPDATED", "PAYMENT_COMPLETED", "PAYMENT_REFUNDED", "PAYMENT_ATTEMPT_FAILED", "PAYMENT_ATTEMPT_SUCCEEDED", "DISPUTE_CREATED", "DISPUTE_RESPONSE_CREATED", "DISPUTE_RESOLVED", "CUSTOMER_CREATED", "CUSTOMER_UPDATED", "CUSTOMER_ARCHIVED", "SUBSCRIPTION_CREATED", "SUBSCRIPTION_UPDATED", "SUBSCRIPTION_CANCELED", "PAYMENT_METHOD_CREATED"]
  }, {
    "key": "status",
    "type": "enum",
    "operators": ["equals", "not", "in", "notIn"],
    "values": ["PENDING", "SUCCESSFUL", "RETRYING", "FAILED"]
  }, {
    "key": "createdAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }, {
    "key": "updatedAt",
    "type": "scalar",
    "operators": ["equals", "lt", "lte", "gt", "gte"],
    "nullable": false,
    "dateTime": true
  }]
}];

<ListFilterBuilder filterType="DiscountFilter" />
