backups/2026-03-28-pre-sidebar-refactor/konfigurator-spara.js

Code: DEV-5B1B6C3D Size: 7.5 KB Lines: 164 Path: /home/prodconfig.wenesthosting.com/dev.solargroup.wenest.se/backups/2026-03-28-pre-sidebar-refactor/konfigurator-spara.js

Task / Comment

Open report form
// konfigurator-spara.js
// Visar: spara

// === GENERISK SPARA/AFFÄR FÖR NYA KONFIGURATORER ===
async function saveCfgQuote(category) {
    const configData = collectCfgData(category);
    const payload = {
        category: category,
        config_data: JSON.stringify(configData),
        total_price: configData.total,
        panel_name: configData.description || category,
        panel_count: 0,
        status: 'utkast',
        created_by: gStaffId || null,
        customer_name: pendingKalkylCustomer?.name || null,
        customer_address: pendingKalkylCustomer?.address || null,
        customer_email: pendingKalkylCustomer?.email || null,
        customer_phone: pendingKalkylCustomer?.phone || null,
        customer_personnummer: (pendingKalkylCustomer?.owner1 && pendingKalkylCustomer.owner1.pnr) || null,
        owner_count: pendingKalkylCustomer?.ownerType === '2' ? 2 : (pendingKalkylCustomer?.ownerType === 'brf' ? 0 : 1),
        prospect_data: pendingKalkylCustomer?.solarData || null
    };
    if(currentQuoteId) payload.id = currentQuoteId;
    try {
        const res = await fetch('/api/quotes.php', {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
        const data = await res.json();
        if(data.error){alert('Fel: '+data.error);return;}
        if(data.id) currentQuoteId = data.id;
        var pIdx2 = (pendingKalkylCustomer||{}).prospectIdx;
        if(pIdx2 >= 0 && faltProspects[pIdx2]){
            if(faltProspects[pIdx2].status !== 'offert') faltProspects[pIdx2].status = 'kalkyl';
            if(!faltProspects[pIdx2].quoteIds) faltProspects[pIdx2].quoteIds = faltProspects[pIdx2].quoteId ? [faltProspects[pIdx2].quoteId] : [];
            if(!faltProspects[pIdx2].quoteIds.includes(currentQuoteId)) faltProspects[pIdx2].quoteIds.push(currentQuoteId);
            faltProspects[pIdx2].quoteId = currentQuoteId;
            localStorage.setItem('faltProspects', JSON.stringify(faltProspects));
            renderFaltMarkers(); renderFaltList(); updateFaltStats(); renderLeadsTable();
        }
        alert('Kalkyl sparad!');
    } catch(e){alert('Fel: '+e.message);}
}
function goToCfgAffar(category){alert('Affär-vy för '+category+' — kommer snart');}
function collectCfgData(cat) {
    switch(cat) {
        case 'batteri': {
            const brand=BAT_BRANDS.find(b=>b.id===_batBrand);
            return {description:(brand?brand.name:'')+' '+(_batSize||'')+'kWh',total:_batSizePrice+Object.values(_batAddons).reduce((s,v)=>s+v,0),battery_brand:_batBrand,battery_kwh:_batSize,battery_price:_batSizePrice,addons:_batAddons,deduction:_batDeduction,owners:_batOwners};
        }
        case 'laddbox': {
            const ch=LB_CHARGERS.find(c=>c.id===_lbSelected);
            return {description:ch?ch.brand+' '+ch.model:'',total:_lbPrice,charger_id:_lbSelected,charger_price:_lbPrice,deduction:_lbDeduction,owners:_lbOwners};
        }
        case 'taktvatt': {
            const area=parseInt(document.getElementById('ttArea')?.value)||0;
            const typ=TT_TYPES.find(t=>t.id===_ttSelectedType);
            return {description:(typ?typ.name:'')+' '+area+'m²',total:area*_ttPricePerSqm,type_id:_ttSelectedType,price_sqm:_ttPricePerSqm,area:area,deduction:_ttDeduction,owners:_ttOwners};
        }
        case 'varmepump': {
            const p=VP_PUMPS.find(x=>x.id===_vpSelected);
            return {description:p?p.brand+' '+p.model:'',total:_vpPrice+_vpInstall,pump_id:_vpSelected,pump_price:_vpPrice,install_price:_vpInstall,deduction:_vpDeduction,owners:_vpOwners};
        }
        case 'tak':
            return {description:_takYtor.length+' takyta(or)',total:0,ytor:_takYtor,tillbehor:_takTillbehor,deduction:_takDeduction,owners:_takOwners};
        case 'isolering': {
            const area=parseInt(document.getElementById('isoArea')?.value)||0;
            const price=parseInt(document.getElementById('isoPrice')?.value)||0;
            return {description:(document.getElementById('isoType')?.value||'Isolering')+' '+area+'m²',total:price,area:area,type:document.getElementById('isoType')?.value,thickness:parseInt(document.getElementById('isoThickness')?.value)||0,price:price,deduction:_isoDeduction,owners:_isoOwners};
        }
        default: return {description:cat,total:0};
    }
}

function closePoForm() {
    var ov = document.getElementById('poFormOverlay');
    if(ov) ov.remove();
    loadInkopDeals();
}

async function saveMeasurements(silent) {
    // Always save measurements to deal_measurements
    try {
        var r = await fetch('api/suppliers.php?action=save_measurements', {
            method:'POST', headers:{'Content-Type':'application/json'},
            body: JSON.stringify({
                deal_id: _poFormDealId,
                measurements: _poFormPositions
            })
        });
        var res = await r.json();
        if(!silent) {
            if(res.success) alert('Inmätning sparad! ('+res.saved+' positioner)');
            else alert(res.error||'Fel vid sparning');
        }
        return res.success;
    } catch(e) {
        if(!silent) alert('Fel: '+e.message);
        return false;
    }
}

async function savePoForm() {
    var suppId = document.getElementById('poLeverantor').value;
    if(!suppId) { alert('Välj leverantör under Leverantörsorder'); return; }

    // Save measurements first
    await saveMeasurements(true);

    // Collect positions with data
    var items = [];
    _poFormPositions.forEach(function(p){
        if(!p.product || !p.width || !p.height) return;
        items.push({
            article_name: p.product + ' ' + p.width + 'x' + p.height,
            category: p.product,
            quantity: parseInt(p.pcs)||1,
            unit: 'st',
            width: parseInt(p.width)||null,
            height: parseInt(p.height)||null,
            notes: [p.model, p.color_in, p.color_out, p.glass, p.profile].filter(Boolean).join(', ')
        });
    });

    // Collect Hedlunds items
    _poHedlundsRows.forEach(function(r){
        if(!r.article || !r.quantity) return;
        items.push({
            article_name: r.article,
            category: r.category,
            quantity: parseInt(r.quantity)||1,
            unit: 'st',
            length: parseInt(r.length)||null,
            notes: r.extra||null,
            unit_price: r.price_per_m ? (parseInt(r.length||0)/1000 * parseFloat(r.price_per_m)) : 0
        });
    });

    var notes = [
        'Kund: ' + (document.getElementById('poKundNamn').value||''),
        'Adress: ' + (document.getElementById('poKundAdress').value||''),
        'Montering: ' + (document.getElementById('poKundMontering').value||''),
        'Byggnadsår: ' + (document.getElementById('poKundByggnar').value||''),
        document.getElementById('poKontrollNotes').value||''
    ].filter(Boolean).join('\n');

    try {
        var r = await fetch('api/suppliers.php?action=create_order', {
            method:'POST', headers:{'Content-Type':'application/json'},
            body: JSON.stringify({
                deal_id: _poFormDealId,
                supplier_id: parseInt(suppId),
                order_date: document.getElementById('poOrderDatum').value,
                expected_delivery: document.getElementById('poLevDatum').value||null,
                notes: notes,
                status: 'draft',
                items: items
            })
        });
        var res = await r.json();
        if(res.success) {
            closePoForm();
            showOrderDetail(res.id);
        } else { alert(res.error||'Fel'); }
    } catch(e) { alert('Fel: '+e.message); }
}