feat: enhance Letzshop order import with EAN matching and stats

- Add historical order import with pagination support
- Add customer_locale, shipping_country_iso, billing_country_iso columns
- Add gtin/gtin_type columns to Product table for EAN matching
- Fix order stats to count all orders server-side (not just visible page)
- Add GraphQL introspection script with tracking workaround tests
- Enrich inventory units with EAN, MPN, SKU, product name
- Add LetzshopOrderStats schema for proper status counts

Migrations:
- a9a86cef6cca: Add locale and country fields to letzshop_orders
- cb88bc9b5f86: Add gtin columns to products table

🤖 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-18 21:04:33 +01:00
parent 6d6c8b44d3
commit 0ab10128ae
17 changed files with 3451 additions and 94 deletions

View File

@@ -27,6 +27,7 @@ function adminMarketplaceLetzshop() {
importing: false,
exporting: false,
importingOrders: false,
importingHistorical: false,
loadingOrders: false,
loadingJobs: false,
savingCredentials: false,
@@ -34,6 +35,9 @@ function adminMarketplaceLetzshop() {
testingConnection: false,
submittingTracking: false,
// Historical import result
historicalImportResult: null,
// Messages
error: '',
successMessage: '',
@@ -394,8 +398,13 @@ function adminMarketplaceLetzshop() {
this.orders = response.orders || [];
this.totalOrders = response.total || 0;
// Update order stats
this.updateOrderStats();
// Use server-side stats (counts all orders, not just visible page)
if (response.stats) {
this.orderStats = response.stats;
} else {
// Fallback to client-side calculation for backwards compatibility
this.updateOrderStats();
}
} catch (error) {
marketplaceLetzshopLog.error('Failed to load orders:', error);
this.error = error.message || 'Failed to load orders';
@@ -405,13 +414,16 @@ function adminMarketplaceLetzshop() {
},
/**
* Update order stats based on current orders
* Update order stats based on current orders (fallback method)
*
* Note: Server now returns stats with all orders counted.
* This method is kept as a fallback for backwards compatibility.
*/
updateOrderStats() {
// Reset stats
this.orderStats = { pending: 0, confirmed: 0, rejected: 0, shipped: 0 };
// Count from orders list
// Count from orders list (only visible page - not accurate for totals)
for (const order of this.orders) {
if (this.orderStats.hasOwnProperty(order.sync_status)) {
this.orderStats[order.sync_status]++;
@@ -441,6 +453,37 @@ function adminMarketplaceLetzshop() {
}
},
/**
* Import historical orders from Letzshop (all confirmed orders)
*/
async importHistoricalOrders() {
if (!this.selectedVendor || !this.letzshopStatus.is_configured) return;
this.importingHistorical = true;
this.error = '';
this.successMessage = '';
this.historicalImportResult = null;
try {
const response = await apiClient.post(
`/admin/letzshop/vendors/${this.selectedVendor.id}/import-history?state=confirmed`
);
this.historicalImportResult = response;
this.successMessage = `Historical import complete: ${response.imported} imported, ${response.updated} updated`;
marketplaceLetzshopLog.info('Historical import result:', response);
// Reload orders to show new data
await this.loadOrders();
} catch (error) {
marketplaceLetzshopLog.error('Failed to import historical orders:', error);
this.error = error.message || 'Failed to import historical orders';
} finally {
this.importingHistorical = false;
}
},
/**
* Confirm an order
*/