feat: add import error tracking and translation tabs

Import Error Tracking:
- Add MarketplaceImportError model to store detailed error information
- Store row number, identifier, error type, message, and row data for each error
- Add API endpoint GET /admin/marketplace-import-jobs/{job_id}/errors
- Add UI to view and browse import errors in job details modal
- Support pagination and error type filtering

Translation Tabs:
- Replace flat translation list with tabbed interface on product detail page
- Add language tabs with full language names
- Add copy-to-clipboard functionality for translation content
- Improved UX with better visual separation of translations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-13 13:33:03 +01:00
parent 3316894c27
commit c2f42c2913
14 changed files with 542 additions and 44 deletions

View File

@@ -189,7 +189,7 @@ class TestAdminLetzshopCredentialsAPI:
class TestAdminLetzshopConnectionAPI:
"""Test admin Letzshop connection testing endpoints."""
@patch("app.services.letzshop.client.requests.Session.post")
@patch("app.services.letzshop.client_service.requests.Session.post")
def test_test_vendor_connection(
self, mock_post, client, admin_headers, test_vendor
):
@@ -217,7 +217,7 @@ class TestAdminLetzshopConnectionAPI:
data = response.json()
assert data["success"] is True
@patch("app.services.letzshop.client.requests.Session.post")
@patch("app.services.letzshop.client_service.requests.Session.post")
def test_test_api_key_directly(
self, mock_post, client, admin_headers
):
@@ -287,7 +287,7 @@ class TestAdminLetzshopOrdersAPI:
assert data["total"] == 1
assert data["orders"][0]["customer_email"] == "admin-test@example.com"
@patch("app.services.letzshop.client.requests.Session.post")
@patch("app.services.letzshop.client_service.requests.Session.post")
def test_trigger_vendor_sync(
self, mock_post, client, admin_headers, test_vendor
):

View File

@@ -164,7 +164,7 @@ class TestVendorLetzshopConnectionAPI:
assert data["success"] is False
assert "not configured" in data["error_details"]
@patch("app.services.letzshop.client.requests.Session.post")
@patch("app.services.letzshop.client_service.requests.Session.post")
def test_test_connection_success(
self, mock_post, client, vendor_user_headers, test_vendor_with_vendor_user
):
@@ -192,7 +192,7 @@ class TestVendorLetzshopConnectionAPI:
assert data["success"] is True
assert data["response_time_ms"] is not None
@patch("app.services.letzshop.client.requests.Session.post")
@patch("app.services.letzshop.client_service.requests.Session.post")
def test_test_api_key_without_saving(
self, mock_post, client, vendor_user_headers, test_vendor_with_vendor_user
):
@@ -319,7 +319,7 @@ class TestVendorLetzshopOrdersAPI:
assert response.status_code == 422 # Validation error
@patch("app.services.letzshop.client.requests.Session.post")
@patch("app.services.letzshop.client_service.requests.Session.post")
def test_import_orders_success(
self,
mock_post,
@@ -384,7 +384,7 @@ class TestVendorLetzshopOrdersAPI:
class TestVendorLetzshopFulfillmentAPI:
"""Test vendor Letzshop fulfillment endpoints."""
@patch("app.services.letzshop.client.requests.Session.post")
@patch("app.services.letzshop.client_service.requests.Session.post")
def test_confirm_order(
self,
mock_post,
@@ -438,7 +438,7 @@ class TestVendorLetzshopFulfillmentAPI:
data = response.json()
assert data["success"] is True
@patch("app.services.letzshop.client.requests.Session.post")
@patch("app.services.letzshop.client_service.requests.Session.post")
def test_set_tracking(
self,
mock_post,