bmc_hub/static/js/invoice-fee-settings.js
Christian 4871dd2d9e Add comprehensive test coverage for various modules
- Introduced tests for mail templates including ranking, rendering, and attachment handling.
- Added tests for time billing selection and approval processes, ensuring proper validation and state management.
- Implemented tests for case types in JavaScript, focusing on loading and editing functionality.
- Created tests for contact mail AI integration, ensuring proper parsing and error handling.
- Developed tests for dark theme CSS contrast and loading order.
- Added tests for invoice fee service, covering various scenarios including exemptions and invalid inputs.
- Implemented vendor resource tests, ensuring proper file handling and query validation.
2026-10-08 08:58:02 +02:00

52 lines
3.3 KiB
JavaScript

(() => {
'use strict';
const get = id => document.getElementById(id);
const describe = product => `${product.sku_internal || product.economic_product_number || product.id} · ${product.name} · ${Number(product.sales_price).toLocaleString('da-DK', {minimumFractionDigits:2})} ${product.sales_currency || 'DKK'}`;
window.loadInvoiceFeeProduct = async () => {
const current = get('invoiceFeeProductCurrent');
try {
const response = await fetch('/api/v1/settings/invoice_fee_product_id');
if (!response.ok) throw new Error('Gebyrindstillingen mangler. Kør migrationen først.');
const setting = await response.json();
if (!setting.value) { current.textContent = 'Ingen standardvare valgt. Tidligere gebyrregler gælder.'; return; }
const productResponse = await fetch(`/api/v1/products/${encodeURIComponent(setting.value)}`);
if (!productResponse.ok) throw new Error('Den valgte gebyrvare findes ikke længere. Vælg en ny vare.');
current.textContent = describe(await productResponse.json());
} catch (error) { current.textContent = error.message; }
};
async function save(productId) {
const status = get('invoiceFeeProductStatus');
status.textContent = 'Gemmer…';
try {
const response = await fetch('/api/v1/settings/invoice_fee_product_id', {method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify({value:String(productId)})});
if (!response.ok) throw new Error((await response.json()).detail || 'Kunne ikke gemme');
get('invoiceFeeProductResults').replaceChildren();
await window.loadInvoiceFeeProduct(); status.textContent = 'Gemt. Gælder kun nye ordrer.';
} catch (error) { status.textContent = error.message; }
}
document.addEventListener('DOMContentLoaded', () => {
let timer, sequence = 0;
get('invoiceFeeProductDisable').addEventListener('click', () => save(''));
get('invoiceFeeProductSearch').addEventListener('input', () => {
clearTimeout(timer);
const seq = ++sequence, q = get('invoiceFeeProductSearch').value.trim();
const results = get('invoiceFeeProductResults'); results.replaceChildren();
if (q.length < 2) return;
timer = setTimeout(async () => {
try {
const response = await fetch(`/api/v1/products?q=${encodeURIComponent(q)}&status=active`);
if (!response.ok) throw new Error('Varesøgning fejlede');
const products = await response.json(); if (seq !== sequence) return;
results.replaceChildren();
products.slice(0,20).forEach(product => {
const button = document.createElement('button'); button.type = 'button';
button.className = 'list-group-item list-group-item-action'; button.textContent = describe(product);
button.addEventListener('click', () => save(product.id)); results.append(button);
});
if (!products.length) results.textContent = 'Ingen varer fundet.';
} catch (error) { if (seq === sequence) results.textContent = error.message; }
}, 250);
});
});
})();