feat(editor): editor prestatii unificat in modal - un select, un rand de chips (PRD 5.23)
Inlocuieste cele 3 controale de asociere cod RAR cu un singur rand de chips + un singur select care adauga instant la change. Stare = un hidden chips_state JSON versionat; post_form_chips redus la 2 actiuni (add/remove). Optgroup Sugestii (fuzzy/k-NN) + optiune "Nu se declara la RAR" in select, cu tinta implicita evidentiata si placeholder care o numeste. exclus persistat prin payload_json (treapta noua de precedenta in resolve_prestatii, round-trip complet). Siguranta: itemii exclusi sunt scosi din payload la momentul trimiterii (worker split_prestatii_excluse inainte de build_rar_payload + filtru defensiv), ca sa nu ajunga NICIODATA la RAR ca codPrestatie:null. Suita: 1680 passed, 1 skipped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -535,8 +535,8 @@ def test_picker_flat_arata_cod_si_denumire(client):
|
||||
|
||||
|
||||
def test_adauga_cod_extra_in_mod_operatii(client):
|
||||
"""In mod operatii, actiunea add_extra adauga un cod RAR liber."""
|
||||
acct = _create_account_user("add.extra.ops@test.com")
|
||||
"""In mod operatii, actiunea unificata 'add' fara tinta adauga un cod RAR liber."""
|
||||
_create_account_user("add.extra.ops@test.com")
|
||||
_login(client, "add.extra.ops@test.com")
|
||||
_seed_cod("OE-1", "Schimb ulei motor")
|
||||
_seed_cod("FRN1", "Sistem de franare")
|
||||
@@ -547,11 +547,11 @@ def test_adauga_cod_extra_in_mod_operatii(client):
|
||||
"/form-chips",
|
||||
data={
|
||||
"csrf_token": csrf,
|
||||
"cod_prestatie": ["OE-1"], # chip existent (op mapata)
|
||||
"chip_op_service": ["SchimbUlei"],
|
||||
"chip_denumire": ["Schimb ulei motor"],
|
||||
"chips_action": "add_extra",
|
||||
"chips_add_cod_flat": "FRN1", # codul extra de adaugat
|
||||
"chips_state": json.dumps({"v": 1, "items": [
|
||||
{"cod": "OE-1", "op": "SchimbUlei", "den": "Schimb ulei motor", "exclus": 0},
|
||||
]}),
|
||||
"chips_action": "add",
|
||||
"chips_pick": "FRN1", # codul extra de adaugat, fara tinta -> chip liber
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200, resp.text[:300]
|
||||
@@ -601,32 +601,36 @@ def test_extra_cod_persistat_la_salvare(client):
|
||||
|
||||
|
||||
def test_extra_cod_validat_nomenclator(client):
|
||||
"""add_extra respinge cod necunoscut in nomenclator (invariant ORA-12899)."""
|
||||
acct = _create_account_user("extra.valid@test.com")
|
||||
"""'add' fara tinta respinge cod necunoscut in nomenclator (invariant ORA-12899)."""
|
||||
_create_account_user("extra.valid@test.com")
|
||||
_login(client, "extra.valid@test.com")
|
||||
_seed_cod("OE-1", "Schimb ulei")
|
||||
csrf = _csrf(client)
|
||||
|
||||
# add_extra cu cod INVALID (XX-99 nu e in nomenclator)
|
||||
# add fara tinta cu cod INVALID (XX-99 nu e in nomenclator)
|
||||
resp = client.post(
|
||||
"/form-chips",
|
||||
data={
|
||||
"csrf_token": csrf,
|
||||
"cod_prestatie": ["OE-1"],
|
||||
"chip_op_service": ["SchimbUlei"],
|
||||
"chip_denumire": ["Schimb ulei"],
|
||||
"chips_action": "add_extra",
|
||||
"chips_add_cod_flat": "XX-99", # cod necunoscut
|
||||
"chips_state": json.dumps({"v": 1, "items": [
|
||||
{"cod": "OE-1", "op": "SchimbUlei", "den": "Schimb ulei", "exclus": 0},
|
||||
]}),
|
||||
"chips_action": "add",
|
||||
"chips_pick": "XX-99", # cod necunoscut
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
html = resp.text
|
||||
# XX-99 NU trebuie sa apara ca chip valid (hidden input cu valoarea XX-99)
|
||||
# XX-99 NU trebuie sa apara in starea persistata (chips_state)
|
||||
import re as _re
|
||||
hidden_xx99 = _re.search(r'<input[^>]+name="cod_prestatie"[^>]+value="XX-99"', html)
|
||||
assert hidden_xx99 is None, (
|
||||
f"Codul invalid XX-99 a fost adaugat ca chip! HTML: {html[:500]}"
|
||||
m = _re.search(r'name="chips_state"\s+value=\'([^\']*)\'', html)
|
||||
assert m
|
||||
payload = json.loads(m.group(1).replace(""", '"'))
|
||||
coduri = [it["cod"] for it in payload["items"]]
|
||||
assert "XX-99" not in coduri, (
|
||||
f"Codul invalid XX-99 a fost adaugat ca chip! items={payload['items']}"
|
||||
)
|
||||
assert "chips-extra-error" in html
|
||||
|
||||
|
||||
def test_cod_ales_in_picker_se_salveaza_fara_buton_add(client):
|
||||
@@ -703,12 +707,12 @@ def test_salvare_fara_chip_explicit_nu_e_no_op(client):
|
||||
|
||||
|
||||
def test_picker_by_index_op2_nu_op1(client):
|
||||
"""Codul ales pe picker-ul op#2 aterizeaza pe op#2, NU pe op#1.
|
||||
"""Codul ales pentru op#2 aterizeaza pe op#2, NU pe op#1.
|
||||
|
||||
Verifica alinierea by-index in modul operatii: chips_add_op_index=1 + chips_add_cod_1
|
||||
actualizeaza chips[1] (op#2), nu chips[0] (op#1).
|
||||
Verifica alinierea by-index in modul operatii: chips_target_index=1 +
|
||||
chips_pick actualizeaza chips[1] (op#2), nu chips[0] (op#1).
|
||||
"""
|
||||
acct = _create_account_user("byindex.op2@test.com")
|
||||
_create_account_user("byindex.op2@test.com")
|
||||
_login(client, "byindex.op2@test.com")
|
||||
_seed_cod("OE-1", "Schimb ulei")
|
||||
_seed_cod("FRN1", "Sistem de franare")
|
||||
@@ -719,27 +723,25 @@ def test_picker_by_index_op2_nu_op1(client):
|
||||
"/form-chips",
|
||||
data={
|
||||
"csrf_token": csrf,
|
||||
"cod_prestatie": ["OE-1", ""], # idx 0=OE-1 (mapata), idx 1="" (nemapata)
|
||||
"chip_op_service": ["Op-A", "Op-B"],
|
||||
"chip_denumire": ["Prima", "A doua"],
|
||||
"chips_state": json.dumps({"v": 1, "items": [
|
||||
{"cod": "OE-1", "op": "Op-A", "den": "Prima", "exclus": 0},
|
||||
{"cod": "", "op": "Op-B", "den": "A doua", "exclus": 0},
|
||||
]}),
|
||||
"chips_action": "add",
|
||||
"chips_add_op_index": "1", # adauga pe op#2 (idx=1)
|
||||
"chips_add_cod_1": "FRN1", # picker-ul op#2 contine FRN1
|
||||
"chips_target_index": "1", # adauga pe op#2 (idx=1)
|
||||
"chips_pick": "FRN1",
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200, resp.text[:300]
|
||||
html = resp.text
|
||||
|
||||
import re as _re
|
||||
hidden_vals = _re.findall(r'<input[^>]+name="cod_prestatie"[^>]+value="([^"]*)"', html)
|
||||
assert "OE-1" in hidden_vals, f"OE-1 (op#1) a disparut dupa adaugare pe op#2: {hidden_vals}"
|
||||
assert "FRN1" in hidden_vals, f"FRN1 nu a aterizat pe op#2: {hidden_vals}"
|
||||
# By-index: OE-1 trebuie sa fie INAINTE de FRN1 (idx 0 < idx 1)
|
||||
oe1_pos = hidden_vals.index("OE-1") if "OE-1" in hidden_vals else -1
|
||||
frn1_pos = hidden_vals.index("FRN1") if "FRN1" in hidden_vals else -1
|
||||
assert oe1_pos < frn1_pos, (
|
||||
f"FRN1 (op#2, idx=1) trebuie dupa OE-1 (op#1, idx=0) by-index: {hidden_vals}"
|
||||
)
|
||||
m = _re.search(r'name="chips_state"\s+value=\'([^\']*)\'', html)
|
||||
assert m
|
||||
payload = json.loads(m.group(1).replace(""", '"'))
|
||||
items = payload["items"]
|
||||
assert items[0]["cod"] == "OE-1", f"OE-1 (op#1) a disparut dupa adaugare pe op#2: {items}"
|
||||
assert items[1]["cod"] == "FRN1", f"FRN1 nu a aterizat pe op#2 (idx=1): {items}"
|
||||
|
||||
|
||||
def test_empty_state_picker_nomenclator_gol(client):
|
||||
@@ -774,25 +776,25 @@ def test_empty_state_picker_nomenclator_gol(client):
|
||||
|
||||
|
||||
def test_add_extra_semnal_vizibil_cod_invalid(client):
|
||||
"""add_extra cu cod invalid da semnal vizibil (nu esua silentios).
|
||||
"""'add' fara tinta cu cod invalid da semnal vizibil (nu esua silentios).
|
||||
|
||||
div.chips-extra-error vizibil cand codul e invalid sau selectul e gol.
|
||||
"""
|
||||
acct = _create_account_user("extra.err.signal@test.com")
|
||||
_create_account_user("extra.err.signal@test.com")
|
||||
_login(client, "extra.err.signal@test.com")
|
||||
_seed_cod("OE-1", "Schimb ulei")
|
||||
csrf = _csrf(client)
|
||||
|
||||
# add_extra cu cod necunoscut in nomenclator
|
||||
# add fara tinta cu cod necunoscut in nomenclator
|
||||
resp = client.post(
|
||||
"/form-chips",
|
||||
data={
|
||||
"csrf_token": csrf,
|
||||
"cod_prestatie": ["OE-1"],
|
||||
"chip_op_service": ["SchimbUlei"],
|
||||
"chip_denumire": ["Schimb ulei"],
|
||||
"chips_action": "add_extra",
|
||||
"chips_add_cod_flat": "XX-99", # cod inexistent
|
||||
"chips_state": json.dumps({"v": 1, "items": [
|
||||
{"cod": "OE-1", "op": "SchimbUlei", "den": "Schimb ulei", "exclus": 0},
|
||||
]}),
|
||||
"chips_action": "add",
|
||||
"chips_pick": "XX-99", # cod inexistent
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
@@ -802,7 +804,7 @@ def test_add_extra_semnal_vizibil_cod_invalid(client):
|
||||
|
||||
|
||||
def test_add_per_op_cod_invalid_afiseaza_mesaj(client):
|
||||
"""Actiunea 'add' (picker per operatie) cu cod invalid da semnal vizibil."""
|
||||
"""Actiunea 'add' (picker per operatie, cu tinta) cu cod invalid da semnal vizibil."""
|
||||
_create_account_user("add.op.err@test.com")
|
||||
_login(client, "add.op.err@test.com")
|
||||
_seed_cod("OE-1", "Schimb ulei")
|
||||
@@ -812,12 +814,12 @@ def test_add_per_op_cod_invalid_afiseaza_mesaj(client):
|
||||
"/form-chips",
|
||||
data={
|
||||
"csrf_token": csrf,
|
||||
"cod_prestatie": [""],
|
||||
"chip_op_service": ["SchimbUlei"],
|
||||
"chip_denumire": ["Schimb ulei"],
|
||||
"chips_state": json.dumps({"v": 1, "items": [
|
||||
{"cod": "", "op": "SchimbUlei", "den": "Schimb ulei", "exclus": 0},
|
||||
]}),
|
||||
"chips_action": "add",
|
||||
"chips_add_op_index": "0",
|
||||
"chips_add_cod_0": "XX-99", # cod inexistent
|
||||
"chips_target_index": "0",
|
||||
"chips_pick": "XX-99", # cod inexistent
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
@@ -837,21 +839,19 @@ def test_add_flat_cod_invalid_afiseaza_mesaj(client):
|
||||
"/form-chips",
|
||||
data={
|
||||
"csrf_token": csrf,
|
||||
"cod_prestatie": ["OE-1"],
|
||||
"chip_op_service": [""],
|
||||
"chip_denumire": [""],
|
||||
"chips_action": "add_flat",
|
||||
"chips_add_cod_flat": "XX-99",
|
||||
"chips_state": json.dumps({"v": 1, "items": [{"cod": "OE-1", "op": "", "den": "", "exclus": 0}]}),
|
||||
"chips_action": "add",
|
||||
"chips_pick": "XX-99",
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert "chips-extra-error" in resp.text, (
|
||||
f"Semnal de eroare lipsa la add_flat cu cod invalid: {resp.text[:300]}"
|
||||
f"Semnal de eroare lipsa la add cu cod invalid: {resp.text[:300]}"
|
||||
)
|
||||
|
||||
|
||||
def test_add_flat_duplicat_afiseaza_mesaj(client):
|
||||
"""add_flat cu un cod deja prezent NU dubleaza chip-ul si afiseaza mesaj."""
|
||||
"""'add' fara tinta cu un cod deja prezent NU dubleaza chip-ul si afiseaza mesaj."""
|
||||
_create_account_user("add.flat.dup@test.com")
|
||||
_login(client, "add.flat.dup@test.com")
|
||||
_seed_cod("OE-1", "Schimb ulei")
|
||||
@@ -861,24 +861,24 @@ def test_add_flat_duplicat_afiseaza_mesaj(client):
|
||||
"/form-chips",
|
||||
data={
|
||||
"csrf_token": csrf,
|
||||
"cod_prestatie": ["OE-1"],
|
||||
"chip_op_service": [""],
|
||||
"chip_denumire": [""],
|
||||
"chips_action": "add_flat",
|
||||
"chips_add_cod_flat": "OE-1", # deja in lista
|
||||
"chips_state": json.dumps({"v": 1, "items": [{"cod": "OE-1", "op": "", "den": "", "exclus": 0}]}),
|
||||
"chips_action": "add",
|
||||
"chips_pick": "OE-1", # deja in lista
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
import re as _re
|
||||
hidden = _re.findall(r'<input[^>]+name="cod_prestatie"[^>]+value="OE-1"', resp.text)
|
||||
assert len(hidden) == 1, f"Chip OE-1 duplicat: {len(hidden)} aparitii"
|
||||
m = _re.search(r'name="chips_state"\s+value=\'([^\']*)\'', resp.text)
|
||||
assert m
|
||||
payload = json.loads(m.group(1).replace(""", '"'))
|
||||
assert len(payload["items"]) == 1, f"Chip OE-1 duplicat: {payload['items']}"
|
||||
assert "deja in lista" in resp.text, (
|
||||
f"Mesaj de duplicat lipsa la add_flat: {resp.text[:300]}"
|
||||
f"Mesaj de duplicat lipsa la add fara tinta: {resp.text[:300]}"
|
||||
)
|
||||
|
||||
|
||||
def test_add_extra_duplicat_afiseaza_mesaj(client):
|
||||
"""add_extra cu chip extra identic existent afiseaza mesaj (nu no-op)."""
|
||||
"""'add' fara tinta cu chip liber identic existent afiseaza mesaj (nu no-op)."""
|
||||
_create_account_user("add.extra.dup@test.com")
|
||||
_login(client, "add.extra.dup@test.com")
|
||||
_seed_cod("OE-1", "Schimb ulei")
|
||||
@@ -889,16 +889,17 @@ def test_add_extra_duplicat_afiseaza_mesaj(client):
|
||||
"/form-chips",
|
||||
data={
|
||||
"csrf_token": csrf,
|
||||
"cod_prestatie": ["OE-1", "FRN1"],
|
||||
"chip_op_service": ["SchimbUlei", ""],
|
||||
"chip_denumire": ["Schimb ulei", ""],
|
||||
"chips_action": "add_extra",
|
||||
"chips_add_cod_flat": "FRN1", # chip extra identic deja existent
|
||||
"chips_state": json.dumps({"v": 1, "items": [
|
||||
{"cod": "OE-1", "op": "SchimbUlei", "den": "Schimb ulei", "exclus": 0},
|
||||
{"cod": "FRN1", "op": "", "den": "", "exclus": 0},
|
||||
]}),
|
||||
"chips_action": "add",
|
||||
"chips_pick": "FRN1", # chip liber identic deja existent
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert "deja in lista" in resp.text, (
|
||||
f"Mesaj de duplicat lipsa la add_extra: {resp.text[:300]}"
|
||||
f"Mesaj de duplicat lipsa la add fara tinta: {resp.text[:300]}"
|
||||
)
|
||||
|
||||
|
||||
@@ -914,11 +915,11 @@ def test_add_reusit_marcheaza_chip_nou(client):
|
||||
"/form-chips",
|
||||
data={
|
||||
"csrf_token": csrf,
|
||||
"cod_prestatie": ["OE-1"],
|
||||
"chip_op_service": ["SchimbUlei"],
|
||||
"chip_denumire": ["Schimb ulei"],
|
||||
"chips_action": "add_extra",
|
||||
"chips_add_cod_flat": "FRN1",
|
||||
"chips_state": json.dumps({"v": 1, "items": [
|
||||
{"cod": "OE-1", "op": "SchimbUlei", "den": "Schimb ulei", "exclus": 0},
|
||||
]}),
|
||||
"chips_action": "add",
|
||||
"chips_pick": "FRN1",
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
||||
Reference in New Issue
Block a user