feat(partner): detect and resync partner mismatches on already-imported orders
Detects PF↔PJ transitions and CUI changes after import; auto-resyncs uninvoiced orders (max 5/cycle) and shows visual alert for invoiced ones. - SQLite: partner_mismatch column + batch helpers - sync_service: detection loop + _resync_partner_for_order - dashboard: red dot + attention card indicator - modal: alert with contextual message and resync button Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -809,6 +809,126 @@ class TestAddrMatch:
|
||||
addr_livr_id = 123
|
||||
assert not (addr_livr_id and billing_addr == shipping_addr)
|
||||
|
||||
def test_pf_billing_address_equals_shipping(self):
|
||||
"""PF (individual): is_pj=0 → billing address = shipping (ramburs curier)."""
|
||||
from app.services.import_service import determine_partner_data
|
||||
from app.services.order_reader import OrderBilling, OrderShipping, OrderData
|
||||
billing = OrderBilling(
|
||||
firstname="Ion", lastname="Popescu", phone="0700000000", email="ion@test.com",
|
||||
address="Str Victoriei 10", city="Cluj", region="Cluj", country="RO",
|
||||
company_name="", company_code="", company_reg="", is_company=False
|
||||
)
|
||||
shipping = OrderShipping(
|
||||
firstname="Ion", lastname="Popescu", phone="0700000000", email="ion@test.com",
|
||||
address="Str Victoriei 10", city="Cluj", region="Cluj", country="RO"
|
||||
)
|
||||
order = OrderData(id="PF001", number="PF001", date="2024-01-01T10:00:00",
|
||||
billing=billing, shipping=shipping)
|
||||
pdata = determine_partner_data(order)
|
||||
assert pdata["is_pj"] == 0, "PF order must have is_pj=0"
|
||||
|
||||
def test_pj_uses_billing_from_gomag(self):
|
||||
"""PJ (company): is_pj=1 → billing address from GoMag billing."""
|
||||
from app.services.import_service import determine_partner_data
|
||||
from app.services.order_reader import OrderBilling, OrderShipping, OrderData
|
||||
billing = OrderBilling(
|
||||
firstname="Ion", lastname="Popescu", phone="0700000000", email="ion@test.com",
|
||||
address="Bld Unirii 5", city="Bucuresti", region="Bucuresti", country="RO",
|
||||
company_name="FIRMA SRL", company_code="RO12345678", company_reg="J40/1234/2020",
|
||||
is_company=True
|
||||
)
|
||||
shipping = OrderShipping(
|
||||
firstname="Mihai", lastname="Ionescu", phone="0711111111", email="mihai@test.com",
|
||||
address="Str Libertatii 20", city="Ploiesti", region="Prahova", country="RO"
|
||||
)
|
||||
order = OrderData(id="PJ001", number="PJ001", date="2024-01-01T10:00:00",
|
||||
billing=billing, shipping=shipping)
|
||||
pdata = determine_partner_data(order)
|
||||
assert pdata["is_pj"] == 1, "PJ order must have is_pj=1"
|
||||
assert pdata["denumire"] == "FIRMA SRL"
|
||||
assert pdata["cod_fiscal"] == "RO12345678"
|
||||
|
||||
def test_pj_different_person_still_uses_billing(self):
|
||||
"""Regression: PJ with different billing/shipping persons → still is_pj=1 (billing addr used)."""
|
||||
from app.services.import_service import determine_partner_data
|
||||
from app.services.order_reader import OrderBilling, OrderShipping, OrderData
|
||||
billing = OrderBilling(
|
||||
firstname="Secretara", lastname="Firma", phone="0700000000", email="office@firma.ro",
|
||||
address="Calea Victoriei 1", city="Bucuresti", region="Bucuresti", country="RO",
|
||||
company_name="FIRMA SA", company_code="RO99999999", company_reg="J40/9999/2019",
|
||||
is_company=True
|
||||
)
|
||||
shipping = OrderShipping(
|
||||
firstname="Curier", lastname="Destinatar", phone="0799999999", email="d@test.com",
|
||||
address="Str Livrare 5", city="Iasi", region="Iasi", country="RO"
|
||||
)
|
||||
order = OrderData(id="PJ002", number="PJ002", date="2024-01-01T10:00:00",
|
||||
billing=billing, shipping=shipping)
|
||||
pdata = determine_partner_data(order)
|
||||
assert pdata["is_pj"] == 1, "PJ with different persons must still be is_pj=1"
|
||||
|
||||
def test_pf_different_billing_still_uses_shipping(self):
|
||||
"""Regression: PF with different billing address → still is_pj=0 (shipping addr used for billing)."""
|
||||
from app.services.import_service import determine_partner_data
|
||||
from app.services.order_reader import OrderBilling, OrderShipping, OrderData
|
||||
billing = OrderBilling(
|
||||
firstname="Ana", lastname="Gheorghe", phone="0700000000", email="ana@test.com",
|
||||
address="Str Alta 99", city="Timisoara", region="Timis", country="RO",
|
||||
company_name="", company_code="", company_reg="", is_company=False
|
||||
)
|
||||
shipping = OrderShipping(
|
||||
firstname="Ana", lastname="Gheorghe", phone="0700000000", email="ana@test.com",
|
||||
address="Str Livrare 7", city="Cluj", region="Cluj", country="RO"
|
||||
)
|
||||
order = OrderData(id="PF002", number="PF002", date="2024-01-01T10:00:00",
|
||||
billing=billing, shipping=shipping)
|
||||
pdata = determine_partner_data(order)
|
||||
assert pdata["is_pj"] == 0, "PF must remain is_pj=0 regardless of billing address"
|
||||
|
||||
def test_is_company_cui_fallback(self):
|
||||
"""Company with no name but CUI populated → is_company=True (order_reader parsing)."""
|
||||
from app.services.order_reader import _parse_order
|
||||
order_data = {
|
||||
"number": "CUI001",
|
||||
"date": "2024-01-01T10:00:00",
|
||||
"statusId": 1,
|
||||
"status": "new",
|
||||
"billing": {
|
||||
"firstname": "Ion",
|
||||
"lastname": "Popescu",
|
||||
"phone": "0700000000",
|
||||
"email": "ion@test.com",
|
||||
"address": "Str Test 1",
|
||||
"city": "Bucuresti",
|
||||
"region": "Bucuresti",
|
||||
"country": "RO",
|
||||
"company": {"name": "", "code": "RO12345678", "registrationNo": ""}
|
||||
},
|
||||
"items": [],
|
||||
"total": 100.0,
|
||||
"discountTotal": 0.0,
|
||||
"shippingTotal": 0.0
|
||||
}
|
||||
order = _parse_order("CUI001", order_data, "test.json")
|
||||
assert order.billing.is_company is True, "CUI-only company must be detected as is_company"
|
||||
assert order.billing.company_code == "RO12345678"
|
||||
|
||||
def test_pj_denomination_fallback_empty_company_name(self):
|
||||
"""PJ with CUI but no company_name → denumire falls back to billing person name."""
|
||||
from app.services.import_service import determine_partner_data
|
||||
from app.services.order_reader import OrderBilling, OrderData
|
||||
billing = OrderBilling(
|
||||
firstname="Ion", lastname="Popescu", phone="0700000000", email="ion@test.com",
|
||||
address="Str Test 1", city="Bucuresti", region="Bucuresti", country="RO",
|
||||
company_name="", company_code="RO12345678", company_reg="", is_company=True
|
||||
)
|
||||
order = OrderData(id="CUI002", number="CUI002", date="2024-01-01T10:00:00",
|
||||
billing=billing, shipping=None)
|
||||
pdata = determine_partner_data(order)
|
||||
assert pdata["is_pj"] == 1
|
||||
assert pdata["denumire"] == "POPESCU ION", "Fallback denumire must use billing person name"
|
||||
assert pdata["cod_fiscal"] == "RO12345678"
|
||||
|
||||
|
||||
class TestFormatAddressForOracle:
|
||||
"""Tests for format_address_for_oracle city stripping."""
|
||||
|
||||
Reference in New Issue
Block a user