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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user