feat(settings): add GoMag API config, Oracle dropdowns, compact 2x2 layout

- Remove ID_GESTIUNE from config (unused)
- Add GoMag API settings (key, shop, days_back, limit) to SQLite — editable without restart
- sync_service reads GoMag settings from SQLite before download
- gomag_client.download_orders accepts api_key/api_shop/limit overrides
- New GET /api/settings/sectii and /api/settings/politici endpoints for Oracle dropdowns
  (nom_sectii.sectie, crm_politici_preturi.nume_lista_preturi)
- id_pol, id_sectie, transport_id_pol, discount_id_pol now use select dropdowns
- order_reader extracts discount_vat from GoMag JSON discounts[].vat
- import_service uses GoMag discount_vat as primary, settings as fallback
- settings.html redesigned to compact 2x2 grid (GoMag API | Import ROA / Transport | Discount)
- settings.js v2: loadDropdowns() sequential before loadSettings()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-03-16 16:39:59 +00:00
parent a0649279cf
commit 227dabd6d4
8 changed files with 268 additions and 97 deletions

View File

@@ -1,11 +1,57 @@
let settAcTimeout = null;
document.addEventListener('DOMContentLoaded', () => {
loadSettings();
document.addEventListener('DOMContentLoaded', async () => {
await loadDropdowns();
await loadSettings();
wireAutocomplete('settTransportCodmat', 'settTransportAc');
wireAutocomplete('settDiscountCodmat', 'settDiscountAc');
});
async function loadDropdowns() {
try {
const [sectiiRes, politiciRes] = await Promise.all([
fetch('/api/settings/sectii'),
fetch('/api/settings/politici')
]);
const sectii = await sectiiRes.json();
const politici = await politiciRes.json();
const sectieEl = document.getElementById('settIdSectie');
if (sectieEl) {
sectieEl.innerHTML = '<option value="">— selectează secție —</option>';
sectii.forEach(s => {
sectieEl.innerHTML += `<option value="${escHtml(s.id)}">${escHtml(s.label)}</option>`;
});
}
const polEl = document.getElementById('settIdPol');
if (polEl) {
polEl.innerHTML = '<option value="">— selectează politică —</option>';
politici.forEach(p => {
polEl.innerHTML += `<option value="${escHtml(p.id)}">${escHtml(p.label)}</option>`;
});
}
const tPolEl = document.getElementById('settTransportIdPol');
if (tPolEl) {
tPolEl.innerHTML = '<option value="">— implicită —</option>';
politici.forEach(p => {
tPolEl.innerHTML += `<option value="${escHtml(p.id)}">${escHtml(p.label)}</option>`;
});
}
const dPolEl = document.getElementById('settDiscountIdPol');
if (dPolEl) {
dPolEl.innerHTML = '<option value="">— implicită —</option>';
politici.forEach(p => {
dPolEl.innerHTML += `<option value="${escHtml(p.id)}">${escHtml(p.label)}</option>`;
});
}
} catch (err) {
console.error('loadDropdowns error:', err);
}
}
async function loadSettings() {
try {
const res = await fetch('/api/settings');
@@ -19,6 +65,10 @@ async function loadSettings() {
if (el('settDiscountIdPol')) el('settDiscountIdPol').value = data.discount_id_pol || '';
if (el('settIdPol')) el('settIdPol').value = data.id_pol || '';
if (el('settIdSectie')) el('settIdSectie').value = data.id_sectie || '';
if (el('settGomagApiKey')) el('settGomagApiKey').value = data.gomag_api_key || '';
if (el('settGomagApiShop')) el('settGomagApiShop').value = data.gomag_api_shop || '';
if (el('settGomagDaysBack')) el('settGomagDaysBack').value = data.gomag_order_days_back || '7';
if (el('settGomagLimit')) el('settGomagLimit').value = data.gomag_limit || '100';
} catch (err) {
console.error('loadSettings error:', err);
}
@@ -35,6 +85,10 @@ async function saveSettings() {
discount_id_pol: el('settDiscountIdPol')?.value?.trim() || '',
id_pol: el('settIdPol')?.value?.trim() || '',
id_sectie: el('settIdSectie')?.value?.trim() || '',
gomag_api_key: el('settGomagApiKey')?.value?.trim() || '',
gomag_api_shop: el('settGomagApiShop')?.value?.trim() || '',
gomag_order_days_back: el('settGomagDaysBack')?.value?.trim() || '7',
gomag_limit: el('settGomagLimit')?.value?.trim() || '100',
};
try {
const res = await fetch('/api/settings', {