git-subtree-dir: fiscal git-subtree-mainline:d95165fc8fgit-subtree-split:102ba84500
99 lines
5.3 KiB
Python
99 lines
5.3 KiB
Python
"""KB search bug fix: the search must be GLOBAL server-side (filter -> count -> order -> paginate), lenient for humans (distinct from the strict
|
|
fiscal `kb.alias_match`), and find a product regardless of which page it would fall on. Never touches the fiscal auto-fill rule."""
|
|
from sqlalchemy import select
|
|
|
|
from central.app.enrichment import kb
|
|
from central.app.enrichment.observability import kb_search, kb_search_ids
|
|
from central.tests.test_control_panel_pages import _panel_client
|
|
from central.tests.test_product_enrichment_resolver import env # noqa: F401
|
|
from central.tests.test_rtc_security import _become, _post
|
|
|
|
|
|
def seed_product(session, gtin, aliases, ncm=None, client="A"):
|
|
p = kb.upsert_product(session, gtin, aliases[0])
|
|
for a in aliases[1:]:
|
|
kb.add_alias(session, p, a)
|
|
if ncm:
|
|
kb.add_evidence(session, p, "ncm", ncm, "x", family=kb.CLIENT_FAMILY, client_label=client, lineage={"docs": 20, "years": {"2024": 20}})
|
|
session.commit()
|
|
return p
|
|
|
|
|
|
def gtin(body12):
|
|
total = sum(int(d) * (3 if i % 2 == 0 else 1) for i, d in enumerate(reversed(body12)))
|
|
return "0" + body12 + str((10 - total % 10) % 10)
|
|
|
|
|
|
def test_search_is_global_not_limited_to_a_rendered_page(env):
|
|
target = seed_product(env, gtin("789100050001"), ["COCA-COLA ORIGINAL LATA 350 ML"], ncm="22021000")
|
|
for i in range(30): # unrelated noise: if search were page-limited, the target could fall off the visible slice
|
|
seed_product(env, gtin(f"78920005{i:04d}"), [f"PRODUTO IRRELEVANTE {i} CAIXA 1 UN"])
|
|
ids = kb_search_ids(env, "COCA COLA LATA 350") # missing the unit "ML": would fail the strict fiscal alias_match
|
|
assert target.id in ids
|
|
|
|
|
|
def test_search_finds_product_on_first_middle_and_last_page(env):
|
|
target = seed_product(env, gtin("789100050002"), ["COCA-COLA ORIGINAL LATA 350 ML"])
|
|
for i in range(25):
|
|
seed_product(env, gtin(f"78920006{i:04d}"), [f"COCA-COLA ORIGINAL LATA 350 ML VARIANTE {i}"])
|
|
for page in (1, 2, 3):
|
|
res = kb_search(env, "COCA COLA LATA 350", page=page, page_size=10)
|
|
assert res["total"] == 26 and res["pages"] == 3
|
|
found_on_last_page = kb_search(env, "COCA COLA LATA 350", page=3, page_size=10)
|
|
assert len(found_on_last_page["results"]) >= 1
|
|
|
|
|
|
def test_search_by_gtin_exact(env):
|
|
key = gtin("789100050003")
|
|
seed_product(env, key, ["COCA-COLA ORIGINAL LATA 350 ML"])
|
|
body = key[1:]
|
|
assert kb_search_ids(env, body) and kb_search_ids(env, body)[0] == kb_search_ids(env, key)[0]
|
|
assert kb_search_ids(env, "0000000000000") == []
|
|
|
|
|
|
def test_search_by_name_with_and_without_hyphen_and_accents(env):
|
|
p = seed_product(env, gtin("789100050004"), ["ACAI ORIGINAL POLPA 100 G"])
|
|
for query in ("ACAI POLPA 100", "AÇAÍ POLPA 100", "acai polpa 100"):
|
|
assert p.id in kb_search_ids(env, query), query
|
|
|
|
|
|
def test_search_zero_results_for_unknown_product(env):
|
|
seed_product(env, gtin("789100050005"), ["FEIJAO CARIOCA 1 KG"])
|
|
assert kb_search_ids(env, "PRODUTO QUE NAO EXISTE NA BASE") == []
|
|
|
|
|
|
def test_search_before_pagination_semantics(env):
|
|
"""Filter runs over the WHOLE table, THEN the result is paginated - not the other way round."""
|
|
matches = [seed_product(env, gtin(f"78910006{i:04d}"), [f"SABONETE LIQUIDO ERVA DOCE {i} 200 ML"]) for i in range(15)]
|
|
for i in range(40):
|
|
seed_product(env, gtin(f"78910007{i:04d}"), [f"OUTRO PRODUTO {i} QUALQUER"])
|
|
res = kb_search(env, "SABONETE LIQUIDO ERVA DOCE", page=2, page_size=10)
|
|
assert res["total"] == 15 and res["page"] == 2 and len(res["results"]) == 5
|
|
found_ids = {r["gtin_key"] for r in kb_search(env, "SABONETE LIQUIDO ERVA DOCE", page=1, page_size=10)["results"]} | {r["gtin_key"] for r in res["results"]}
|
|
assert found_ids == {p.gtin for p in matches}
|
|
|
|
|
|
def test_conflict_candidates_all_visible_and_none_auto_confirmed(env):
|
|
seed_product(env, gtin("789100050006"), ["COCA COLA LATA 350 ML"], ncm="22030000", client="RINCAO")
|
|
p2 = seed_product(env, gtin("789100050006"), ["REFRIGERANTE COCA COLA LATA 350 ML"], ncm="22021000", client="UNIAO")
|
|
# both aliases resolve to the SAME kb product (same GTIN key), so seeding into it twice just adds evidence
|
|
ids = kb_search_ids(env, "COCA COLA LATA 350")
|
|
assert p2.id in ids
|
|
|
|
|
|
def test_admin_attest_button_authorization_end_to_end():
|
|
client, agent_id, _ = _panel_client()
|
|
with client._session_factory() as s:
|
|
from central.tests.test_enrichment_history import staging
|
|
from central.tests.test_enrichment_history import run as seed_history
|
|
from central.tests.test_product_enrichment_resolver import seed as seed_ncm_dataset
|
|
seed_ncm_dataset(s)
|
|
seed_history(s, [staging("RINCAO", "7891000500071", "19059090", years={2024: 900, 2025: 900}, desc="COCA LATA 350 ML"),
|
|
staging("UNIAO", "7891000500071", "22021000", years={2024: 20, 2025: 13}, desc="REFRIGERANTE COCA COLA LATA 350 ML")])
|
|
_become(client, "PADRAO")
|
|
page = client.get("/?kb_q=COCA COLA LATA 350").text
|
|
assert "Confirmar este NCM" not in page # button hidden for non-admin
|
|
_become(client, "ADMIN")
|
|
page = client.get("/?kb_q=COCA COLA LATA 350").text
|
|
assert "Confirmar este NCM" in page and "22021000" in page and "19059090" in page
|