diff --git a/app/db/clientes.py b/app/db/clientes.py index 8fdd2a3..4726207 100644 --- a/app/db/clientes.py +++ b/app/db/clientes.py @@ -34,21 +34,22 @@ class ClienteComDependenciasError(Exception): def listar_clientes( busca: str | None = None, limite: int = 100, offset: int = 0, ordenar_por: str = ORDENACAO_PADRAO ) -> list[dict]: - coluna_ordenacao = ORDENACOES_VALIDAS.get(ordenar_por, ORDENACOES_VALIDAS[ORDENACAO_PADRAO]) + coluna = ORDENACOES_VALIDAS.get(ordenar_por, ORDENACOES_VALIDAS[ORDENACAO_PADRAO]) conn = get_connection() try: with conn.cursor() as cur: if busca: + # A busca é restrita à mesma coluna escolhida em "ordenar_por" + # — selecionar "Código" busca só em CODIGO, não em todos os + # campos de uma vez. sql = ( f"SELECT {_COLUNAS_SELECT} FROM CLIENTE " - "WHERE CODIGO LIKE %s OR CNPJ LIKE %s OR RAZAO LIKE %s OR FANTASIA LIKE %s " - f"ORDER BY {coluna_ordenacao} LIMIT %s OFFSET %s" + f"WHERE {coluna} LIKE %s ORDER BY {coluna} LIMIT %s OFFSET %s" ) - termo = f"%{busca}%" - cur.execute(sql, (termo, termo, termo, termo, limite, offset)) + cur.execute(sql, (f"%{busca}%", limite, offset)) else: cur.execute( - f"SELECT {_COLUNAS_SELECT} FROM CLIENTE ORDER BY {coluna_ordenacao} LIMIT %s OFFSET %s", + f"SELECT {_COLUNAS_SELECT} FROM CLIENTE ORDER BY {coluna} LIMIT %s OFFSET %s", (limite, offset), ) return cur.fetchall() @@ -80,17 +81,13 @@ def proximo_codigo_sugerido() -> str: return str(proximo).zfill(6) -def contar_clientes(busca: str | None = None) -> int: +def contar_clientes(busca: str | None = None, ordenar_por: str = ORDENACAO_PADRAO) -> int: + coluna = ORDENACOES_VALIDAS.get(ordenar_por, ORDENACOES_VALIDAS[ORDENACAO_PADRAO]) conn = get_connection() try: with conn.cursor() as cur: if busca: - sql = ( - "SELECT COUNT(*) AS total FROM CLIENTE " - "WHERE CODIGO LIKE %s OR CNPJ LIKE %s OR RAZAO LIKE %s OR FANTASIA LIKE %s" - ) - termo = f"%{busca}%" - cur.execute(sql, (termo, termo, termo, termo)) + cur.execute(f"SELECT COUNT(*) AS total FROM CLIENTE WHERE {coluna} LIKE %s", (f"%{busca}%",)) else: cur.execute("SELECT COUNT(*) AS total FROM CLIENTE") return cur.fetchone()["total"] diff --git a/app/routers/clientes.py b/app/routers/clientes.py index 23110cf..b438eb6 100644 --- a/app/routers/clientes.py +++ b/app/routers/clientes.py @@ -90,7 +90,7 @@ def listar( ordenar_por = db_clientes.ORDENACAO_PADRAO pagina = max(pagina, 1) - total = db_clientes.contar_clientes(busca=busca or None) + total = db_clientes.contar_clientes(busca=busca or None, ordenar_por=ordenar_por) total_paginas = max(math.ceil(total / TAMANHO_PAGINA), 1) pagina = min(pagina, total_paginas) offset = (pagina - 1) * TAMANHO_PAGINA diff --git a/app/templates/clientes_lista.html b/app/templates/clientes_lista.html index 2be3e0a..b275911 100644 --- a/app/templates/clientes_lista.html +++ b/app/templates/clientes_lista.html @@ -4,14 +4,14 @@ {% block conteudo %}

Clientes

- - + +

+ Novo cliente

diff --git a/tests/test_db_clientes.py b/tests/test_db_clientes.py index 081465a..3012d48 100644 --- a/tests/test_db_clientes.py +++ b/tests/test_db_clientes.py @@ -87,8 +87,15 @@ def test_excluir_cliente_sem_dependencias(cliente_id): assert db_clientes.obter_cliente(cliente_id) is None -def test_listar_clientes_ordena_por_codigo(cliente_id): +def test_listar_clientes_busca_e_restrita_a_coluna_escolhida(cliente_id): + # ordenar_por="codigo" restringe a busca à coluna CODIGO — o termo + # "TESTE PAINEL RAZAO" existe em RAZAO/FANTASIA, mas não deve aparecer + # aqui porque a busca não olha para essas colunas quando é "codigo". resultado = db_clientes.listar_clientes(busca="TESTE PAINEL RAZAO", ordenar_por="codigo") + assert len(resultado) == 0 + + # Buscando pelo próprio código, com ordenar_por="codigo", encontra. + resultado = db_clientes.listar_clientes(busca="999901", ordenar_por="codigo") assert resultado[0]["CODIGO"] == "999901" diff --git a/tests/test_main.py b/tests/test_main.py index ae2bcfb..bb95d8d 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -23,7 +23,7 @@ def test_raiz_redireciona_para_clientes_com_login(monkeypatch): from app.routers import clientes as router_clientes monkeypatch.setattr(router_clientes.db_clientes, "listar_clientes", lambda busca=None, limite=100, offset=0: []) - monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None: 0) + monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None, ordenar_por="razao": 0) resposta = client.get("/", headers=_AUTH_HEADERS, follow_redirects=False) assert resposta.status_code == 307 assert resposta.headers["location"] == "/clientes" diff --git a/tests/test_router_clientes.py b/tests/test_router_clientes.py index e16e849..92b7831 100644 --- a/tests/test_router_clientes.py +++ b/tests/test_router_clientes.py @@ -61,7 +61,7 @@ def test_listar_clientes(monkeypatch): {"ID": 1, "CODIGO": "000001", "RAZAO": "Cliente Um", "FANTASIA": "Um", "CNPJ": "11222333000181"} ], ) - monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None: 1) + monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None, ordenar_por="razao": 1) resposta = client.get("/clientes") assert resposta.status_code == 200 assert "Cliente Um" in resposta.text @@ -76,7 +76,7 @@ def test_listar_clientes_pagina_com_controles_de_paginacao(monkeypatch): for i in range(1, 6) ], ) - monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None: 250) + monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None, ordenar_por="razao": 250) resposta = client.get("/clientes?pagina=2") assert resposta.status_code == 200 @@ -94,7 +94,7 @@ def test_listar_clientes_ordenar_por_invalido_cai_no_padrao(monkeypatch): return [] monkeypatch.setattr(router_clientes.db_clientes, "listar_clientes", _listar_clientes) - monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None: 0) + monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None, ordenar_por="razao": 0) client.get("/clientes?ordenar_por=coisa_invalida_qualquer") assert capturado["ordenar_por"] == "razao"