In parseaza_adresa_semicolon, text după NR ("5 la non stop", "21 sat
Grozavesti corbii mari") era împins în p_numar și trunchiat brutal la
10 chars ("5 LA NON S", "21 SAT GRO").
Fix: când p_numar > 10 chars, prima componentă rămâne numar; restul se
clasifică:
- "SAT X ..." → p_localitate := "X ..." (satul = localitate, TIER
L1/L2/L3 existent rezolvă id_loc)
- "COM/ORAS/MUN X" → aruncat (deja în p_localitate din GoMag city)
- altceva (landmark ex "LA NON STOP") → concatenat în p_strada
Semnătura parseaza_adresa_semicolon neschimbată. Zero callers afectați.
Teste: landmark → strada, SAT → localitate, numar normal neschimbat.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
470 lines
20 KiB
Python
470 lines
20 KiB
Python
"""
|
|
Oracle Integration Tests — Regula adrese PJ/PF
|
|
===============================================
|
|
Verifică că comenzile importate respectă regula:
|
|
PF (fără CUI): id_adresa_facturare = id_adresa_livrare
|
|
PJ (cu CUI): adresa_facturare_roa se potrivește cu adresa billing GoMag
|
|
|
|
Testele principale sunt E2E (importă comenzi sintetice în Oracle și verifică).
|
|
Testele de regresie verifică comenzile existente din SQLite.
|
|
|
|
Run:
|
|
pytest api/tests/test_address_rules_oracle.py -v
|
|
./test.sh oracle
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import time
|
|
|
|
import pytest
|
|
|
|
pytestmark = pytest.mark.oracle
|
|
|
|
_script_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
|
|
_project_root = os.path.dirname(_script_dir)
|
|
|
|
from dotenv import load_dotenv
|
|
_env_path = os.path.join(_script_dir, ".env")
|
|
load_dotenv(_env_path, override=True)
|
|
|
|
_tns_admin = os.environ.get("TNS_ADMIN", "")
|
|
if _tns_admin and os.path.isfile(_tns_admin):
|
|
os.environ["TNS_ADMIN"] = os.path.dirname(_tns_admin)
|
|
elif not _tns_admin:
|
|
os.environ["TNS_ADMIN"] = _script_dir
|
|
|
|
if _script_dir not in sys.path:
|
|
sys.path.insert(0, _script_dir)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Fixtures
|
|
# ---------------------------------------------------------------------------
|
|
|
|
@pytest.fixture(scope="module")
|
|
def oracle_env():
|
|
"""Re-aplică .env și actualizează settings pentru Oracle."""
|
|
load_dotenv(_env_path, override=True)
|
|
_tns = os.environ.get("TNS_ADMIN", "")
|
|
if _tns and os.path.isfile(_tns):
|
|
os.environ["TNS_ADMIN"] = os.path.dirname(_tns)
|
|
|
|
from app.config import settings
|
|
settings.ORACLE_USER = os.environ.get("ORACLE_USER", "MARIUSM_AUTO")
|
|
settings.ORACLE_PASSWORD = os.environ.get("ORACLE_PASSWORD", "ROMFASTSOFT")
|
|
settings.ORACLE_DSN = os.environ.get("ORACLE_DSN", "ROA_CENTRAL")
|
|
settings.TNS_ADMIN = os.environ.get("TNS_ADMIN", _script_dir)
|
|
settings.FORCE_THIN_MODE = os.environ.get("FORCE_THIN_MODE", "") == "true"
|
|
return settings
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def client(oracle_env):
|
|
from fastapi.testclient import TestClient
|
|
from app.main import app
|
|
with TestClient(app) as c:
|
|
yield c
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def oracle_pool(oracle_env):
|
|
"""Pool Oracle direct pentru verificări în DB."""
|
|
from app import database
|
|
database.init_oracle()
|
|
yield database.pool
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def real_codmat(client):
|
|
"""CODMAT real din Oracle pentru liniile comenzii sintetice."""
|
|
for term in ["01", "PH", "CA", "A"]:
|
|
resp = client.get("/api/articles/search", params={"q": term})
|
|
if resp.status_code == 200:
|
|
results = resp.json().get("results", [])
|
|
if results:
|
|
return results[0]["codmat"]
|
|
pytest.skip("Nu s-a găsit niciun CODMAT în Oracle pentru test")
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def app_settings(client):
|
|
"""Setările aplicației (id_pol, id_sectie, etc.)."""
|
|
resp = client.get("/api/sync/schedule")
|
|
assert resp.status_code == 200
|
|
import sqlite3
|
|
from app.config import settings as _s
|
|
db_path = _s.SQLITE_DB_PATH if os.path.isabs(_s.SQLITE_DB_PATH) else os.path.join(_script_dir, _s.SQLITE_DB_PATH)
|
|
conn = sqlite3.connect(db_path)
|
|
conn.row_factory = sqlite3.Row
|
|
rows = conn.execute("SELECT key, value FROM app_settings").fetchall()
|
|
conn.close()
|
|
return {r["key"]: r["value"] for r in rows}
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def run_id():
|
|
return f"pytest-addr-{int(time.time())}"
|
|
|
|
|
|
def _build_pj_order(run_id, real_codmat):
|
|
"""Comandă sintetică PJ: companie cu billing ≠ shipping."""
|
|
from app.services.order_reader import OrderBilling, OrderShipping, OrderData, OrderItem
|
|
billing = OrderBilling(
|
|
firstname="Test", lastname="PJ", phone="0700000000", email="pj@pytest.local",
|
|
address="Bld Unirii 1", city="Bucuresti", region="Bucuresti", country="RO",
|
|
company_name="PYTEST COMPANY SRL", company_code="RO99000001", company_reg="J40/9999/2026",
|
|
is_company=True
|
|
)
|
|
shipping = OrderShipping(
|
|
firstname="Curier", lastname="Destinatar", phone="0799999999", email="ship@pytest.local",
|
|
address="Str Livrare 99", city="Cluj-Napoca", region="Cluj", country="RO"
|
|
)
|
|
return OrderData(
|
|
id=f"{run_id}-PJ",
|
|
number=f"{run_id}-PJ",
|
|
date="2026-01-15T10:00:00",
|
|
status="new", status_id="1",
|
|
billing=billing, shipping=shipping,
|
|
items=[OrderItem(sku="PYTEST-SKU-PJ", name="Test PJ Item",
|
|
price=10.0, quantity=1.0, vat=19.0)],
|
|
total=10.0, delivery_cost=0.0, discount_total=0.0
|
|
)
|
|
|
|
|
|
def _build_pf_order(run_id, real_codmat):
|
|
"""Comandă sintetică PF: persoană fizică, billing ≠ shipping (dar billing ROA trebuie = shipping)."""
|
|
from app.services.order_reader import OrderBilling, OrderShipping, OrderData, OrderItem
|
|
billing = OrderBilling(
|
|
firstname="Ion", lastname="Popescu", phone="0700000001", email="pf@pytest.local",
|
|
address="Str Alta 5", city="Timisoara", region="Timis", country="RO",
|
|
company_name="", company_code="", company_reg="", is_company=False
|
|
)
|
|
shipping = OrderShipping(
|
|
firstname="Ion", lastname="Popescu", phone="0700000001", email="pf@pytest.local",
|
|
address="Str Livrare 10", city="Iasi", region="Iasi", country="RO"
|
|
)
|
|
return OrderData(
|
|
id=f"{run_id}-PF",
|
|
number=f"{run_id}-PF",
|
|
date="2026-01-15T10:00:00",
|
|
status="new", status_id="1",
|
|
billing=billing, shipping=shipping,
|
|
items=[OrderItem(sku="PYTEST-SKU-PF", name="Test PF Item",
|
|
price=10.0, quantity=1.0, vat=19.0)],
|
|
total=10.0, delivery_cost=0.0, discount_total=0.0
|
|
)
|
|
|
|
|
|
def _cleanup_test_orders(oracle_pool, run_id):
|
|
"""Șterge comenzile de test din Oracle."""
|
|
try:
|
|
conn = oracle_pool.acquire()
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"DELETE FROM comenzi WHERE comanda_externa LIKE :1",
|
|
[f"{run_id}%"]
|
|
)
|
|
conn.commit()
|
|
oracle_pool.release(conn)
|
|
except Exception as e:
|
|
print(f"Cleanup warning: {e}")
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Test E2E: import PJ + PF sintetice în Oracle
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class TestAddressRulesE2E:
|
|
"""Import comenzi sintetice și verifică adresele în Oracle."""
|
|
|
|
@pytest.fixture(scope="class", autouse=True)
|
|
def cleanup(self, oracle_pool, run_id):
|
|
yield
|
|
_cleanup_test_orders(oracle_pool, run_id)
|
|
|
|
def test_pj_billing_addr_is_gomag_billing(self, oracle_pool, real_codmat, app_settings, run_id):
|
|
"""PJ: adresa facturare în Oracle provine din GoMag billing (nu shipping)."""
|
|
from app.services.import_service import import_single_order
|
|
from app.services.order_reader import OrderItem
|
|
|
|
order = _build_pj_order(run_id, real_codmat)
|
|
# Replace test SKU with real codmat via mapping (or just use items with real SKU)
|
|
order.items = [OrderItem(sku=real_codmat, name="Test PJ",
|
|
price=10.0, quantity=1.0, vat=19.0)]
|
|
|
|
id_pol = int(app_settings.get("id_pol") or 0) or None
|
|
id_sectie = int(app_settings.get("id_sectie") or 0) or None
|
|
|
|
result = import_single_order(order, id_pol=id_pol, id_sectie=id_sectie,
|
|
app_settings=app_settings)
|
|
|
|
if not result["success"]:
|
|
pytest.skip(f"Import PJ eșuat (SKU probabil nemapat): {result.get('error')}")
|
|
|
|
id_fact = result["id_adresa_facturare"]
|
|
id_livr = result["id_adresa_livrare"]
|
|
|
|
assert id_fact is not None, "PJ: id_adresa_facturare lipsește din result"
|
|
assert id_livr is not None, "PJ: id_adresa_livrare lipsește din result"
|
|
|
|
# PJ cu billing ≠ shipping: adresele trebuie să fie DIFERITE
|
|
assert id_fact != id_livr, (
|
|
f"PJ cu billing≠shipping trebuie să aibă id_fact({id_fact}) ≠ id_livr({id_livr}). "
|
|
f"Regula veche (different_person) s-ar comporta la fel, dar acum PJ folosește billing GoMag."
|
|
)
|
|
|
|
# Verifică în Oracle că adresele există
|
|
conn = oracle_pool.acquire()
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"SELECT id_livrare, id_facturare FROM comenzi WHERE comanda_externa = :1",
|
|
[order.number]
|
|
)
|
|
row = cur.fetchone()
|
|
oracle_pool.release(conn)
|
|
|
|
assert row is not None, f"Comanda {order.number} nu s-a găsit în Oracle comenzi"
|
|
assert row[0] == id_livr, f"id_livrare Oracle ({row[0]}) ≠ result ({id_livr})"
|
|
assert row[1] == id_fact, f"id_facturare Oracle ({row[1]}) ≠ result ({id_fact})"
|
|
|
|
def test_pf_billing_addr_equals_shipping(self, oracle_pool, real_codmat, app_settings, run_id):
|
|
"""PF: adresa facturare în Oracle = adresa livrare (ramburs curier)."""
|
|
from app.services.import_service import import_single_order
|
|
from app.services.order_reader import OrderItem
|
|
|
|
order = _build_pf_order(run_id, real_codmat)
|
|
order.items = [OrderItem(sku=real_codmat, name="Test PF",
|
|
price=10.0, quantity=1.0, vat=19.0)]
|
|
|
|
id_pol = int(app_settings.get("id_pol") or 0) or None
|
|
id_sectie = int(app_settings.get("id_sectie") or 0) or None
|
|
|
|
result = import_single_order(order, id_pol=id_pol, id_sectie=id_sectie,
|
|
app_settings=app_settings)
|
|
|
|
if not result["success"]:
|
|
pytest.skip(f"Import PF eșuat: {result.get('error')}")
|
|
|
|
id_fact = result["id_adresa_facturare"]
|
|
id_livr = result["id_adresa_livrare"]
|
|
|
|
assert id_fact is not None, "PF: id_adresa_facturare lipsește din result"
|
|
assert id_livr is not None, "PF: id_adresa_livrare lipsește din result"
|
|
|
|
# PF: id_facturare TREBUIE să fie = id_livrare
|
|
assert id_fact == id_livr, (
|
|
f"PF trebuie să aibă id_fact({id_fact}) = id_livr({id_livr}) — "
|
|
f"ramburs curier pe adresa de livrare"
|
|
)
|
|
|
|
# Verifică în Oracle
|
|
conn = oracle_pool.acquire()
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"SELECT id_livrare, id_facturare FROM comenzi WHERE comanda_externa = :1",
|
|
[order.number]
|
|
)
|
|
row = cur.fetchone()
|
|
oracle_pool.release(conn)
|
|
|
|
assert row is not None, f"Comanda {order.number} nu s-a găsit în Oracle comenzi"
|
|
assert row[1] == row[0], (
|
|
f"Oracle: id_facturare({row[1]}) ≠ id_livrare({row[0]}) pentru PF"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Test: parsare componente adresă (strada, numar, bloc, scara, apart, etaj)
|
|
# Apelează direct parseaza_adresa_semicolon din Oracle — fără import comandă.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class TestAddressComponentParsing:
|
|
"""Verifică extragerea componentelor adresei direct prin parseaza_adresa_semicolon."""
|
|
|
|
def _parse_address(self, oracle_pool, address, city="Bucuresti", region="Bucuresti"):
|
|
"""Call Oracle parseaza_adresa_semicolon and return parsed components."""
|
|
from app.services.import_service import format_address_for_oracle
|
|
formatted = format_address_for_oracle(address, city, region)
|
|
|
|
conn = oracle_pool.acquire()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
p_judet = cur.var(str, 200)
|
|
p_localitate = cur.var(str, 200)
|
|
p_strada = cur.var(str, 100)
|
|
p_numar = cur.var(str, 100)
|
|
p_sector = cur.var(str, 100)
|
|
p_bloc = cur.var(str, 30)
|
|
p_scara = cur.var(str, 10)
|
|
p_apart = cur.var(str, 10)
|
|
p_etaj = cur.var(str, 20)
|
|
|
|
cur.callproc("PACK_IMPORT_PARTENERI.parseaza_adresa_semicolon", [
|
|
formatted, p_judet, p_localitate, p_strada, p_numar,
|
|
p_sector, p_bloc, p_scara, p_apart, p_etaj
|
|
])
|
|
|
|
return {
|
|
"strada": p_strada.getvalue(),
|
|
"numar": p_numar.getvalue(),
|
|
"bloc": p_bloc.getvalue(),
|
|
"scara": p_scara.getvalue(),
|
|
"apart": p_apart.getvalue(),
|
|
"etaj": p_etaj.getvalue(),
|
|
"localitate": p_localitate.getvalue(),
|
|
"judet": p_judet.getvalue(),
|
|
}
|
|
finally:
|
|
oracle_pool.release(conn)
|
|
|
|
def test_full_address_all_components(self, oracle_pool):
|
|
"""Adresa completă cu nr, bl, sc, ap — toate componentele se extrag din strada."""
|
|
addr = self._parse_address(oracle_pool,
|
|
"Bd. 1 Decembrie 1918 nr. 26 bl. 6 sc. 2 ap. 36")
|
|
assert addr["numar"] == "26", f"numar={addr['numar']}"
|
|
assert addr["bloc"] == "6", f"bloc={addr['bloc']}"
|
|
assert addr["scara"] == "2", f"scara={addr['scara']}"
|
|
assert addr["apart"] == "36", f"apart={addr['apart']}"
|
|
assert "SC" not in (addr["strada"] or ""), f"SC ramas in strada: {addr['strada']}"
|
|
assert "AP" not in (addr["strada"] or ""), f"AP ramas in strada: {addr['strada']}"
|
|
|
|
def test_alphanumeric_bloc_and_letter_scara(self, oracle_pool):
|
|
"""Bloc alfanumeric (VN9) și scara literă (A) + etaj."""
|
|
addr = self._parse_address(oracle_pool,
|
|
"Strada Becatei nr 29 bl. VN9 sc. A et. 10 ap. 42")
|
|
assert addr["numar"] == "29", f"numar={addr['numar']}"
|
|
assert addr["bloc"] == "VN9", f"bloc={addr['bloc']}"
|
|
assert addr["scara"] == "A", f"scara={addr['scara']}"
|
|
assert addr["etaj"] == "10", f"etaj={addr['etaj']}"
|
|
assert addr["apart"] == "42", f"apart={addr['apart']}"
|
|
|
|
def test_address_without_commas_uppercase(self, oracle_pool):
|
|
"""Adresa uppercase fără virgule — keywords spațiu-separate."""
|
|
addr = self._parse_address(oracle_pool,
|
|
"STR DACIA NR 15 BLOC Z2 SC 1 AP 7 ET 3")
|
|
assert addr["numar"] == "15", f"numar={addr['numar']}"
|
|
assert addr["bloc"] == "Z2", f"bloc={addr['bloc']}"
|
|
assert addr["scara"] == "1", f"scara={addr['scara']}"
|
|
assert addr["apart"] == "7", f"apart={addr['apart']}"
|
|
assert addr["etaj"] == "3", f"etaj={addr['etaj']}"
|
|
|
|
def test_address_with_existing_commas(self, oracle_pool):
|
|
"""Adresa care deja are virgule — nu se strică parsarea."""
|
|
addr = self._parse_address(oracle_pool,
|
|
"Str Victoriei, nr. 10, bl. A1, sc. B, et. 2, ap. 15")
|
|
assert addr["numar"] == "10", f"numar={addr['numar']}"
|
|
assert addr["bloc"] == "A1", f"bloc={addr['bloc']}"
|
|
assert addr["scara"] == "B", f"scara={addr['scara']}"
|
|
assert addr["etaj"] == "2", f"etaj={addr['etaj']}"
|
|
assert addr["apart"] == "15", f"apart={addr['apart']}"
|
|
|
|
def test_no_keywords_street_unchanged(self, oracle_pool):
|
|
"""Adresa simplă fără keywords — strada rămâne intactă."""
|
|
addr = self._parse_address(oracle_pool, "Strada Victoriei 10")
|
|
assert "VICTORIEI" in (addr["strada"] or ""), f"strada={addr['strada']}"
|
|
|
|
def test_blocuri_neighborhood_not_extracted_as_bloc(self, oracle_pool):
|
|
"""'Blocuri' in street name must NOT be parsed as BLOC keyword."""
|
|
result = self._parse_address(oracle_pool, "Str Principala Modarzau Blocuri", "Zemes", "Bacau")
|
|
assert "MODARZAU BLOCURI" in (result.get("strada") or ""), f"strada should contain MODARZAU BLOCURI, got {result}"
|
|
assert result.get("bloc") is None, f"bloc should be NULL for neighborhood name, got {result.get('bloc')}"
|
|
|
|
def test_numar_overflow_with_landmark(self, oracle_pool):
|
|
"""'nr 5 la non stop' — numar=5, landmark overflow muta in strada."""
|
|
addr = self._parse_address(oracle_pool, "Str zorilor nr 5 la non stop", "Brasov", "Brasov")
|
|
assert addr["numar"] == "5", f"numar={addr['numar']!r} (asteptat '5')"
|
|
assert "ZORILOR" in (addr["strada"] or ""), f"strada={addr['strada']!r}"
|
|
assert "NON" in (addr["strada"] or ""), f"landmark lipsa din strada: {addr['strada']!r}"
|
|
|
|
def test_numar_overflow_with_sat_localitate(self, oracle_pool):
|
|
"""'nr21 sat Grozavesti corbii mari' — numar=21, SAT overwrite p_localitate (satul = localitate)."""
|
|
addr = self._parse_address(oracle_pool, "Pe deal nr21 sat Grozavesti corbii mari", "Corbii Mari", "Dambovita")
|
|
assert addr["numar"] == "21", f"numar={addr['numar']!r} (asteptat '21')"
|
|
assert "DEAL" in (addr["strada"] or ""), f"strada={addr['strada']!r}"
|
|
assert "GROZAVESTI" not in (addr["strada"] or ""), f"SAT in strada: {addr['strada']!r}"
|
|
# SAT ... a fost mutat in p_localitate (override din GoMag "CORBII MARI")
|
|
assert "GROZAVESTI" in (addr["localitate"] or "").upper(), (
|
|
f"localitate={addr['localitate']!r} (astept sa contina GROZAVESTI)"
|
|
)
|
|
|
|
def test_numar_normal_not_affected(self, oracle_pool):
|
|
"""Numar normal (<= 10 chars) nu e atins de overflow fix."""
|
|
addr = self._parse_address(oracle_pool, "Str Mihai Viteazu nr 10", "Cluj-Napoca", "Cluj")
|
|
assert addr["numar"] == "10", f"numar={addr['numar']!r}"
|
|
assert "VITEAZU" in (addr["strada"] or ""), f"strada={addr['strada']!r}"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Test regresie: comenzi existente în SQLite
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class TestAddressRulesRegression:
|
|
"""Verifică că comenzile existente importate după fix respectă regula PJ/PF."""
|
|
|
|
FIX_DATE = "2026-04-08" # data când a fost aplicat fix-ul
|
|
|
|
@pytest.fixture(scope="class")
|
|
def sqlite_rows(self):
|
|
"""Comenzi cu adrese populate importate după data fix-ului."""
|
|
import sqlite3
|
|
from app.config import settings
|
|
db_path = os.environ.get("SQLITE_DB_PATH", os.path.join(_script_dir, "orders.db"))
|
|
if not os.path.exists(db_path):
|
|
pytest.skip(f"SQLite DB lipsă: {db_path}")
|
|
|
|
conn = sqlite3.connect(db_path)
|
|
conn.row_factory = sqlite3.Row
|
|
rows = conn.execute("""
|
|
SELECT order_number, cod_fiscal_gomag,
|
|
id_adresa_facturare, id_adresa_livrare,
|
|
adresa_facturare_gomag, adresa_livrare_gomag,
|
|
adresa_facturare_roa, adresa_livrare_roa,
|
|
first_seen_at
|
|
FROM orders
|
|
WHERE id_adresa_facturare IS NOT NULL
|
|
AND id_adresa_livrare IS NOT NULL
|
|
AND first_seen_at >= ?
|
|
""", (self.FIX_DATE,)).fetchall()
|
|
conn.close()
|
|
return rows
|
|
|
|
def test_pf_id_facturare_equals_id_livrare(self, sqlite_rows):
|
|
"""PF noi: id_adresa_facturare = id_adresa_livrare."""
|
|
pf_rows = [r for r in sqlite_rows if not r["cod_fiscal_gomag"]]
|
|
if not pf_rows:
|
|
pytest.skip(f"Nicio comandă PF importată după {self.FIX_DATE}")
|
|
|
|
violations = [
|
|
f"{r['order_number']}: id_fact={r['id_adresa_facturare']} id_livr={r['id_adresa_livrare']}"
|
|
for r in pf_rows
|
|
if r["id_adresa_facturare"] != r["id_adresa_livrare"]
|
|
]
|
|
assert not violations, (
|
|
f"PF comenzi cu id_fact ≠ id_livr ({len(violations)}):\n" + "\n".join(violations[:10])
|
|
)
|
|
|
|
def test_pj_billing_roa_matches_gomag_billing(self, sqlite_rows):
|
|
"""PJ noi: adresa_facturare_roa se potrivește cu GoMag billing address."""
|
|
from app.services.sync_service import _addr_match
|
|
|
|
pj_rows = [
|
|
r for r in sqlite_rows
|
|
if r["cod_fiscal_gomag"] and r["adresa_facturare_gomag"] and r["adresa_facturare_roa"]
|
|
]
|
|
if not pj_rows:
|
|
pytest.skip(f"Nicio comandă PJ cu adrese populate importată după {self.FIX_DATE}")
|
|
|
|
violations = []
|
|
for r in pj_rows:
|
|
if not _addr_match(r["adresa_facturare_gomag"], r["adresa_facturare_roa"]):
|
|
violations.append(
|
|
f"{r['order_number']}: billing_gomag={r['adresa_facturare_gomag']!r} "
|
|
f"fact_roa={r['adresa_facturare_roa']!r}"
|
|
)
|
|
|
|
assert not violations, (
|
|
f"PJ comenzi cu adresa_facturare_roa care nu corespunde GoMag billing ({len(violations)}):\n"
|
|
+ "\n".join(violations[:10])
|
|
)
|