feat: MercadoLibre integration + inventory bulk publish + WhatsApp bridge fixes

- Add MercadoLibre OAuth, listings, orders, webhooks and category search
- New marketplace_external_bp.py, meli_service.py, marketplace_external_service.py
- New marketplace_external.html/js with ML management UI
- Inventory: bulk publish to ML with category autocomplete, listing type and shipping selectors
- Inventory: new .btn--meli styles, select/label CSS fixes
- WhatsApp bridge: rate limiting, 440/515/408 error handling, stale watchdog
- DB migration v3.4_meli_integration.sql for marketplace_listings, orders, sync_queue
- Add Celery tasks for ML sync and webhook processing
- Sidebar: MercadoLibre navigation link
This commit is contained in:
2026-05-26 04:24:07 +00:00
parent 50c0dbe7d4
commit a236187f3a
66 changed files with 7335 additions and 498 deletions

View File

@@ -301,16 +301,16 @@
<!-- Tabs Row -->
<div class="tabs-row" role="tablist" aria-label="Módulos de Facturación">
<button class="tab-btn is-active" role="tab" aria-selected="true" aria-controls="panel-facturas" id="tab-facturas" onclick="switchTab('facturas')">
Facturas <span class="tab-btn__badge">247</span>
Facturas <span class="tab-btn__badge" id="badge-facturas">0</span>
</button>
<button class="tab-btn" role="tab" aria-selected="false" aria-controls="panel-notas" id="tab-notas" onclick="switchTab('notas')">
Notas de Crédito <span class="tab-btn__badge">8</span>
Notas de Crédito <span class="tab-btn__badge" id="badge-notas-credito">0</span>
</button>
<button class="tab-btn" role="tab" aria-selected="false" aria-controls="panel-complementos" id="tab-complementos" onclick="switchTab('complementos')">
Complementos de Pago <span class="tab-btn__badge">12</span>
Complementos de Pago <span class="tab-btn__badge" id="badge-complementos">0</span>
</button>
<button class="tab-btn" role="tab" aria-selected="false" aria-controls="panel-cancelaciones" id="tab-cancelaciones" onclick="switchTab('cancelaciones')">
Cancelaciones <span class="tab-btn__badge tab-btn__badge--warn">6</span>
Cancelaciones <span class="tab-btn__badge tab-btn__badge--warn" id="badge-cancelaciones">0</span>
</button>
<button class="tab-btn" role="tab" aria-selected="false" aria-controls="panel-config" id="tab-config" onclick="switchTab('config')">
Configuración CFDI
@@ -1060,5 +1060,33 @@
<script src="/pos/static/js/pwa-install.js" defer></script>
<script src="/pos/static/js/chat.js" defer></script>
<script>
// Load invoicing stats for tab badges
async function loadInvoicingStats() {
const token = localStorage.getItem('pos_token') || '';
try {
const res = await fetch('/pos/api/invoicing/stats', {
headers: token ? { 'Authorization': 'Bearer ' + token } : {}
});
if (!res.ok) return;
const data = await res.json();
const map = {
'badge-facturas': data.facturas,
'badge-notas-credito': data.notas_credito,
'badge-complementos': data.complementos,
'badge-cancelaciones': data.cancelaciones
};
Object.entries(map).forEach(function([id, val]) {
const el = document.getElementById(id);
if (el) el.textContent = val || 0;
});
} catch (e) {
console.error('Failed to load invoicing stats:', e);
}
}
window.loadInvoicingStats = loadInvoicingStats;
loadInvoicingStats();
</script>
</body>
</html>