Changeset 3446582
- Timestamp:
- 01/25/2026 03:43:15 PM (4 weeks ago)
- Location:
- keiste-solar-report
- Files:
-
- 12 edited
- 1 copied
-
tags/1.0.25 (copied) (copied from keiste-solar-report/trunk)
-
tags/1.0.25/assets/js/charts.js (modified) (2 diffs)
-
tags/1.0.25/assets/js/solar-calculator-main.js (modified) (10 diffs)
-
tags/1.0.25/includes/class-ksrad-calculator.php (modified) (1 diff)
-
tags/1.0.25/includes/plugin-init.php (modified) (2 diffs)
-
tags/1.0.25/keiste-solar-report.php (modified) (14 diffs)
-
tags/1.0.25/readme.txt (modified) (1 diff)
-
trunk/assets/js/charts.js (modified) (2 diffs)
-
trunk/assets/js/solar-calculator-main.js (modified) (10 diffs)
-
trunk/includes/class-ksrad-calculator.php (modified) (1 diff)
-
trunk/includes/plugin-init.php (modified) (2 diffs)
-
trunk/keiste-solar-report.php (modified) (14 diffs)
-
trunk/readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
keiste-solar-report/tags/1.0.25/assets/js/charts.js
r3415762 r3446582 24 24 // ===== BREAK-EVEN CHART ===== 25 25 function calculateBreakEvenDataSimple(config) { 26 console.log('[CHART] calculateBreakEvenDataSimple called with config:', config); 27 26 28 const yearlyEnergy = config.yearlyEnergyDcKwh; 27 29 const panelCount = config.panelsCount; 28 const electricityRate = parseFloat(document.getElementById('electricityRate')?.value) || 0.45; 29 30 const exportRate = (() => { 31 const v = document.getElementById('exportRate')?.value; 32 const p = parseFloat(String(v || '').replace(/[^0-9.\-]/g, '')); 33 return Number.isFinite(p) ? (p / 100) : 0.4; 34 })(); 30 31 // Get values from config or inputs 32 const cfg = window.KSRAD_CalcConfig || {}; 33 const electricityRate = parseFloat(document.getElementById('electricityRate')?.value) || 0.36; 34 const feedInTariff = 0.21; // Standard FIT rate 35 const billMonthly = parseFloat(document.getElementById('electricityBill')?.value) || 0; 36 37 const exportRatePercent = cfg.defaultExportRate || 0.05; 35 38 36 39 const inclGrant = document.getElementById('inclGrant')?.checked; 37 const inclACA = document.getElementById('inclACA')?.checked;38 40 const inclLoan = document.getElementById('inclLoan')?.checked; 39 41 const degradation = 0.005; 40 41 // Compute installation cost 42 const installedCapacityKwp = yearlyEnergy / 1000; 43 let computedInstallCost = 0; 44 if (installedCapacityKwp <= 100) { 45 computedInstallCost = installedCapacityKwp * 1500; 46 } else if (installedCapacityKwp <= 250) { 47 computedInstallCost = (100 * 1500) + ((installedCapacityKwp - 100) * 1300); 48 } else { 49 computedInstallCost = (100 * 1500) + (150 * 1300) + ((installedCapacityKwp - 250) * 1100); 50 } 51 52 const seaiGrant = inclGrant ? Math.min(computedInstallCost * 0.3, 162000) : 0; 53 const acaGrant = inclACA ? (computedInstallCost * 0.125) : 0; 54 const totalGrant = seaiGrant + acaGrant; 55 const totalCost = computedInstallCost - totalGrant; 42 const annualIncrease = 0.05; // 5% bill increase per year 43 44 // Get actual net install cost from the calculator 45 // We need to recalculate it here to match what keyFigures does 46 const baseCost = config.installCost || 0; 47 48 console.log('[CHART] baseCost:', baseCost); 49 console.log('[CHART] billMonthly:', billMonthly); 50 console.log('[CHART] inclGrant:', inclGrant); 51 console.log('[CHART] inclLoan:', inclLoan); 52 53 // Get grant settings based on building type 54 const getGrantAmount = () => { 55 try { 56 const grants = cfg.grantSettings || {}; 57 const btEl = document.getElementById('userBuildingType'); 58 const selected = (btEl && btEl.value) ? btEl.value.trim() : 'Residential'; 59 const isResidential = (selected === 'Residential'); 60 const category = isResidential ? 'Residential' : 'Non-Residential'; 61 const grantSettings = grants[category] || { rate: 0.30, cap: 162000 }; 62 return inclGrant ? Math.min(baseCost * grantSettings.rate, grantSettings.cap) : 0; 63 } catch (e) { 64 return inclGrant ? Math.min(baseCost * 0.30, 162000) : 0; 65 } 66 }; 67 68 const seaiGrant = getGrantAmount(); 69 const principal = Math.max(0, baseCost - seaiGrant); 70 71 console.log('[CHART] seaiGrant:', seaiGrant); 72 console.log('[CHART] principal:', principal); 73 74 // Calculate loan payments if applicable 75 const loanAPR = 0.07; // 7% APR 76 const loanYears = 7; 77 let yearlyLoanCost = 0; 78 let totalCost = principal; 79 80 if (inclLoan) { 81 const m = 12; 82 const n = loanYears * m; 83 const r = loanAPR / m; 84 const monthlyRepay = principal * (r / (1 - Math.pow(1 + r, -n))); 85 yearlyLoanCost = monthlyRepay * 12; 86 totalCost = yearlyLoanCost * loanYears; 87 } 88 89 console.log('[CHART] yearlyLoanCost:', yearlyLoanCost); 90 console.log('[CHART] totalCost (investment):', totalCost); 91 92 // Calculate annual usage from bill 93 const annualUsageKwh = (billMonthly * 12) / electricityRate; 94 95 console.log('[CHART] annualUsageKwh:', annualUsageKwh); 56 96 57 97 const years = Array.from({ length: 25 }, (_, i) => i); … … 59 99 const yearDegradation = Math.pow(1 - degradation, year); 60 100 const yearlyEnergyProduction = yearlyEnergy * yearDegradation; 61 const selfConsumedEnergy = yearlyEnergyProduction * (1 - exportRate); 62 const exportedEnergy = yearlyEnergyProduction * exportRate; 63 const yearlySaving = (selfConsumedEnergy * electricityRate) + (exportedEnergy * exportRate); 64 65 const totalSaving = year === 0 ? 0 : years 101 102 // Calculate self-consumption and export (same logic as main calculator) 103 const maxSelfConsumption = yearlyEnergyProduction * (1 - exportRatePercent); 104 const actualSelfConsumption = Math.min(maxSelfConsumption, annualUsageKwh); 105 const exportedEnergy = yearlyEnergyProduction - actualSelfConsumption; 106 107 // Apply escalating electricity rate 108 const escalatedRate = electricityRate * Math.pow(1 + annualIncrease, year); 109 110 // Year's savings 111 const yearlySaving = (actualSelfConsumption * escalatedRate) + (exportedEnergy * feedInTariff); 112 113 // Year's loan cost (only for first 7 years if loan) 114 const yearLoanCost = (inclLoan && year < loanYears) ? yearlyLoanCost : 0; 115 116 // Net saving for this year 117 const netYearlySaving = yearlySaving - yearLoanCost; 118 119 // Cumulative savings up to this year 120 const totalSaving = year === 0 ? -totalCost : years 66 121 .slice(1, year + 1) 67 122 .reduce((acc, y) => { 68 123 const yDegradation = Math.pow(1 - degradation, y); 69 124 const yEnergyProduction = yearlyEnergy * yDegradation; 70 const ySelfConsumed = yEnergyProduction * (1 - exportRate); 71 const yExported = yEnergyProduction * exportRate; 72 return acc + (ySelfConsumed * electricityRate) + (yExported * exportRate); 73 }, 0); 74 75 return totalSaving - totalCost; 125 const yMaxSelfConsumption = yEnergyProduction * (1 - exportRatePercent); 126 const yActualSelfConsumption = Math.min(yMaxSelfConsumption, annualUsageKwh); 127 const yExported = yEnergyProduction - yActualSelfConsumption; 128 const yEscalatedRate = electricityRate * Math.pow(1 + annualIncrease, y); 129 const ySaving = (yActualSelfConsumption * yEscalatedRate) + (yExported * feedInTariff); 130 const yLoanCost = (inclLoan && y < loanYears) ? yearlyLoanCost : 0; 131 return acc + (ySaving - yLoanCost); 132 }, -totalCost); 133 134 return totalSaving; 76 135 }); 136 137 const breakEvenYear = savings.findIndex(saving => saving >= 0); 138 console.log('[CHART] Break-even year:', breakEvenYear); 139 console.log('[CHART] First 5 years cumulative savings:', savings.slice(0, 5)); 77 140 78 141 return { 79 142 cost: totalCost, 80 143 savings: savings, 81 breakEvenYear: savings.findIndex(saving => saving >= 0)144 breakEvenYear: breakEvenYear 82 145 }; 83 146 } -
keiste-solar-report/tags/1.0.25/assets/js/solar-calculator-main.js
r3419489 r3446582 302 302 console.log('install_cost', install_cost); 303 303 304 const net_install_cost = Math.round(Number(baseCost - seaiGrant + (inclLoan ? (baseCost - seaiGrant) * interest : 0)));305 console.log('net_install_cost', net_install_cost);306 307 304 // Production 308 305 const yearlyEnergyKWhYr0 = yearlyEnergy; // year 0 nominal from config … … 315 312 const monthlyRepay = Math.round(inclLoan ? principal * (r / (1 - Math.pow(1 + r, -n))) : 0); 316 313 const yearlyLoanCost = Math.round(inclLoan ? monthlyRepay * 12 : 0); 314 315 // Net install cost: if loan, show total loan payments; otherwise show upfront cost after grant 316 const net_install_cost = inclLoan ? Math.round(yearlyLoanCost * LENGTH_OF_PAYBACK) : Math.round(baseCost - seaiGrant); 317 console.log('net_install_cost', net_install_cost); 317 318 318 319 // Total 25-year savings (benefits - cost + ACA if included) … … 341 342 342 343 // First-year annual saving (calculate this BEFORE payback so we can use it) 343 const savings_year0 = (() => { 344 // Current electricity usage based on their bill 345 const current_usage_kwh = (billMonthly * 12) / RETAIL; 346 console.log('Bill calculation - billMonthly:', billMonthly, 'RETAIL:', RETAIL, 'current_usage_kwh:', current_usage_kwh); 347 348 // Total solar production (use actual config data, not formula) 349 const annual_solar_kwh = yearlyEnergy > 0 ? yearlyEnergy : (panels * DAY_POWER_AVG * DAYS_IN_YR); 350 console.log('Annual solar production:', annual_solar_kwh, 'kWh (from yearlyEnergy:', yearlyEnergy, ')'); 351 352 // Self-consumption: what they can use themselves (capped by their actual usage) 353 const max_self_consumption_kwh = annual_solar_kwh * (1 - exportRate); 354 const actual_self_consumption_kwh = Math.min(max_self_consumption_kwh, current_usage_kwh); 355 console.log('Export rate:', exportRate, 'Max self:', max_self_consumption_kwh, 'Actual self:', actual_self_consumption_kwh, 'Current usage:', current_usage_kwh); 356 357 // Export: everything not self-consumed 358 const export_kwh = annual_solar_kwh - actual_self_consumption_kwh; 359 console.log('Export kWh:', export_kwh); 360 361 // Financial benefits 362 const bill_savings = actual_self_consumption_kwh * RETAIL; // Avoided electricity cost 363 const export_income = export_kwh * FIT; // Export income 364 console.log('Bill savings:', bill_savings, '(', actual_self_consumption_kwh, '*', RETAIL, ')'); 365 console.log('Export income:', export_income, '(', export_kwh, '*', FIT, ')'); 366 367 const loan_cost = inclLoan ? yearlyLoanCost : 0; 368 const acaBump = (inclACA ? acaAllowance : 0); 369 370 return bill_savings + export_income - loan_cost + acaBump; 371 })(); 344 // ===== FIXED PRODUCTION & SAVINGS MODEL ===== 345 346 // Annual usage derived from bill 347 const current_usage_kwh = (billMonthly * MONTHS_IN_YR) / RETAIL; 348 349 // Total solar production 350 const annual_solar_kwh = 351 panels * 352 PANEL_POWER_W / 1000 * 353 DAY_POWER_AVG * 354 DAYS_IN_YR; 355 356 // Self-consumption is limited by actual usage 357 const max_self_consumption_kwh = annual_solar_kwh * (1 - exportRate); 358 const actual_self_consumption_kwh = Math.min(max_self_consumption_kwh, current_usage_kwh); 359 360 // Export is what's left after self-consumption 361 const export_kwh = annual_solar_kwh - actual_self_consumption_kwh; 362 363 // --- FINANCIALS --- 364 const bill_savings = actual_self_consumption_kwh * RETAIL; 365 const export_income = export_kwh * FIT; 366 367 // Total benefit (before loan / adjustments) 368 const savings_year0 = bill_savings + export_income - yearlyLoanCost; 369 370 console.log( 371 'YEAR 0 BREAKDOWN:\n' + 372 ' annual_solar_kwh: ' + annual_solar_kwh + '\n' + 373 ' current_usage_kwh: ' + current_usage_kwh + '\n' + 374 ' exportRate: ' + exportRate + '\n' + 375 ' max_self_consumption_kwh: ' + max_self_consumption_kwh + '\n' + 376 ' actual_self_consumption_kwh: ' + actual_self_consumption_kwh + '\n' + 377 ' export_kwh: ' + export_kwh + '\n' + 378 ' RETAIL: ' + RETAIL + '\n' + 379 ' FIT: ' + FIT + '\n' + 380 ' bill_savings: ' + bill_savings + '\n' + 381 ' export_income: ' + export_income + '\n' + 382 ' yearlyLoanCost: ' + yearlyLoanCost + '\n' + 383 ' savings_year0: ' + savings_year0 384 ); 372 385 373 386 // Monthly charge (Year 0) - based on actual savings 374 const monthly_charge = (savings_year0 / 12) - billMonthly; 375 387 // Only show meaningful net income when there's a bill to offset 388 const monthly_charge = billMonthly > 0 ? (savings_year0 / 12) - billMonthly : 0; 389 376 390 // Payback period (years) - uses actual net annual savings 377 const payback_period = (() => { 378 // Investment amount to pay back 379 const investment = inclLoan ? loanCost25 : net_install_cost; 380 381 // Net annual savings (year 0) - this is what actually goes back into your pocket 382 const annualSavings = savings_year0; 383 384 // Payback = Investment / Annual Savings 385 return annualSavings > 0 ? investment / annualSavings : 0; 386 })(); 391 // Investment amount to pay back 392 const investment = inclLoan ? loanCost25 : net_install_cost; 393 // Payback = Investment / Annual Savings 394 const payback_period = savings_year0 > 0 ? investment / savings_year0 : 0; 387 395 388 396 // ROI over 25 years (%) … … 394 402 // CO2 reduction over life 395 403 const co2_reduction = CO2_COEFFICIENT_TONNES * 396 Array.from({ length: YRS_OF_SYSTEM }, (_, y) =>404 Array.from({ length: YRS_OF_SYSTEM }, (_, y) => 397 405 panels * DAY_POWER_AVG * Math.pow(1 - SOLAR_PANEL_DEGRADATION, y) * DAYS_IN_YR 398 406 ).reduce((a, b) => a + b, 0); … … 407 415 408 416 // ========= 5) GUI UPDATES ========= 417 function updateGrantDescription() { 418 // Update the grant description text based on current building type 419 try { 420 const cfg = window.KSRAD_CalcConfig || {}; 421 const grants = cfg.grantSettings || {}; 422 const btEl = document.getElementById('userBuildingType'); 423 const selected = (btEl && btEl.value) ? btEl.value.trim() : 'Residential'; 424 425 const isResidential = (selected === 'Residential'); 426 const category = isResidential ? 'Residential' : 'Non-Residential'; 427 428 const grantRate = grants[category] ? (grants[category].rate || 0.30) : 0.30; 429 const grantCap = grants[category] ? (grants[category].cap || 162000) : 162000; 430 431 // Find and update grant description elements 432 const grantDescElements = document.querySelectorAll('.grant-description, [data-grant-description]'); 433 grantDescElements.forEach(el => { 434 const percentDisplay = Math.round(grantRate * 100); 435 const capDisplay = CURRENCY_SYMBOL + grantCap.toLocaleString('en-IE'); 436 el.textContent = `${percentDisplay}% Grant (max ${capDisplay})`; 437 }); 438 } catch (e) { 439 console.error('Error updating grant description:', e); 440 } 441 } 442 409 443 function updateResults(state, figs) { 410 444 const setTxt = (id, txt) => { … … 419 453 setTxt('installationCost', fmtEuro(figs.install_cost)); 420 454 setTxt('grant', fmtEuro(figs.seaiGrant)); 455 456 // Update grant description text dynamically 457 updateGrantDescription(); 458 421 459 setTxt('panelCount', fmtNum(state.panels, 0)); 422 460 // Annual energy production display: support both legacy `yearlyEnergy` and current `yearlyEnergyValue` IDs … … 453 491 }); 454 492 }; 493 494 // Only show meaningful figures when there's a bill 495 if (!state.billMonthly || state.billMonthly === 0) { 496 setTxt('netCost', CURRENCY_SYMBOL + '0'); 497 setTxt('totalSavings', CURRENCY_SYMBOL + '0'); 498 setTxt('roi', '0%'); 499 setTxt('co2Reduction', '0 t'); 500 setTxt('annualSavings', CURRENCY_SYMBOL + '0'); 501 setTxt('paybackPeriod', '0 years'); 502 return; 503 } 504 455 505 // #installation-details 456 506 setTxt('netCost', fmtEuro(figs.net_install_cost)); … … 478 528 if (window.breakEvenChart && window.breakEvenChart.data && typeof window.calculateBreakEvenDataSimple === 'function') { 479 529 try { 530 console.log('[updateBreakEvenChart] Inside try block, billMonthly:', state.billMonthly); 531 480 532 // On page load with no bill, show zero baseline 481 533 if (!state.billMonthly || state.billMonthly === 0) { … … 487 539 } 488 540 489 const cfg = { panelsCount: state.panels, yearlyEnergyDcKwh: figs.yearlyEnergyKWh || (state.panels * DAY_POWER_AVG * DAYS_IN_YR) }; 541 console.log('[updateBreakEvenChart] About to create config object'); 542 console.log('[updateBreakEvenChart] figs.yearlyEnergyKWh:', figs.yearlyEnergyKWh); 543 console.log('[updateBreakEvenChart] figs.baseCost:', figs.baseCost); 544 545 const cfg = { 546 panelsCount: state.panels, 547 yearlyEnergyDcKwh: figs.yearlyEnergyKWh || (state.panels * DAY_POWER_AVG * DAYS_IN_YR), 548 installCost: figs.baseCost 549 }; 490 550 console.log('Calling calculateBreakEvenDataSimple with:', cfg); 491 551 const be = window.calculateBreakEvenDataSimple(cfg); … … 713 773 console.log('[INIT] solar-calculator-main.js initializing...'); 714 774 console.log('[INIT] document.readyState:', document.readyState); 715 // Apply configuration from PHP if available 775 776 // Apply configuration from PHP if available (don't wait, just use defaults if not ready) 716 777 if (window.KSRAD_CalcConfig) { 717 778 console.log('[INIT] KSRAD_CalcConfig found:', window.KSRAD_CalcConfig); 718 779 CURRENCY_SYMBOL = window.KSRAD_CalcConfig.currencySymbol || CURRENCY_SYMBOL; 719 720 // Also expose globally for consistency with other scripts721 780 window.CURRENCY_SYMBOL = CURRENCY_SYMBOL; 722 781 } else { 723 console.warn('[INIT] KSRAD_CalcConfig not found ');782 console.warn('[INIT] KSRAD_CalcConfig not found - using defaults'); 724 783 } 725 784 -
keiste-solar-report/tags/1.0.25/includes/class-ksrad-calculator.php
r3415762 r3446582 3 3 * Solar Calculator class for Keiste Solar Report 4 4 * 5 <<<<<<< HEAD 6 ======= 7 * This code is just the placeholder code. 8 >>>>>>> fed100d (added UK no solar. grant % defaults to zero now. the math is still off though.) 5 9 * Handles solar panel calculations and renders the calculator frontend. 6 10 * -
keiste-solar-report/tags/1.0.25/includes/plugin-init.php
r3420871 r3446582 217 217 'googleSolarApiKey' => ksrad_get_option('google_solar_api_key', ''), 218 218 'reportKey' => ksrad_get_option('report_key', ''), 219 'defaultElectricityRate' => ksrad_get_option('default_electricity_rate', '0. 17'),220 'defaultExportRate' => ksrad_get_option('default_export_rate', ' 10'),221 'defaultFeedInTariff' => ksrad_get_option('default_feed_in_tariff', '0. 15'),219 'defaultElectricityRate' => ksrad_get_option('default_electricity_rate', '0.36'), 220 'defaultExportRate' => ksrad_get_option('default_export_rate', '5'), 221 'defaultFeedInTariff' => ksrad_get_option('default_feed_in_tariff', '0.20'), 222 222 'defaultLoanApr' => ksrad_get_option('default_loan_apr', '5'), 223 223 'loanTerm' => ksrad_get_option('loan_term', '7'), 224 224 'annualPriceIncrease' => ksrad_get_option('annual_price_increase', '5'), 225 'currency' => ksrad_get_option('currency', ' $'),226 'country' => ksrad_get_option('country', ' United States'),227 'systemCostRatio' => ksrad_get_option('system_cost_ratio', ' 650'),225 'currency' => ksrad_get_option('currency', '€'), 226 'country' => ksrad_get_option('country', 'Republic of Ireland'), 227 'systemCostRatio' => ksrad_get_option('system_cost_ratio', '1600'), 228 228 'grantRateDomestic' => ksrad_get_option('grant_rate_domestic', '30'), 229 229 'grantCapDomestic' => ksrad_get_option('grant_cap_domestic', '7500'), … … 311 311 'report_key' => '', 312 312 'logo_url' => '', 313 'default_electricity_rate' => '0. 17',314 'default_export_rate' => ' 10',315 'default_feed_in_tariff' => '0. 14',313 'default_electricity_rate' => '0.34', 314 'default_export_rate' => '5', 315 'default_feed_in_tariff' => '0.20', 316 316 'default_loan_apr' => '5', 317 317 'loan_term' => '7', 318 318 'annual_price_increase' => '5', 319 'currency' => ' $',320 'country' => ' United States',321 'system_cost_ratio' => ' 650',322 'cost_domestic' => ' 650',323 'cost_small' => ' 600',324 'cost_medium' => ' 500',325 'cost_large' => ' 425',319 'currency' => '€', 320 'country' => 'Republic of Ireland', 321 'system_cost_ratio' => '1800', 322 'cost_domestic' => '1800', 323 'cost_small' => '1600', 324 'cost_medium' => '1200', 325 'cost_large' => '1000', 326 326 'grant_rate_domestic' => '30', 327 327 'grant_cap_domestic' => '7500', -
keiste-solar-report/tags/1.0.25/keiste-solar-report.php
r3420878 r3446582 5 5 * Plugin URI: https://keiste.com/keiste-solar-report 6 6 * Description: Comprehensive solar panel analysis tool with ROI calculations, Google Solar API integration, interactive charts, and PDF report generation. 7 * Version: 1.0.2 47 * Version: 1.0.25 8 8 * Author: Dara Burke, Keiste 9 9 * Author URI: https://keiste.com … … 34 34 // Define plugin constants (only once) with ksrad_ namespace 35 35 if (!defined('KSRAD_VERSION')) { 36 define('KSRAD_VERSION', '1.0.2 4');36 define('KSRAD_VERSION', '1.0.25'); 37 37 } 38 38 if (!defined('KSRAD_PLUGIN_DIR')) { … … 325 325 <div class="container"> 326 326 327 <div class="text-center mt-4">327 <div class="text-center"> 328 328 <?php 329 329 $ksrad_logo_url = ksrad_get_option('logo_url', ''); … … 333 333 } 334 334 ?> 335 <a href="<?php echo esc_url(home_url('/ ')); ?>">335 <a href="<?php echo esc_url(home_url('/keiste-solar-report/')); ?>"> 336 336 <img src="<?php echo esc_url($ksrad_logo_url); ?>" alt="Company Logo" 337 337 class="img-fluid logo-image" style="max-width: 130px; width: 100%;"> … … 359 359 ?> 360 360 <h1>Solar Report<sup style="color: red;font-size: 16px;vertical-align: middle;top: -14px;"> <?php echo esc_html($ksrad_country_code); ?></sup></h1> 361 <div style="text-align: center; margin: 30px 0;"> 362 <a href="<?php echo esc_url(remove_query_arg(['lat', 'lng', 'business_name'])); ?>" 363 class="btn btn-secondary" 364 style="display: inline-block; padding: 8px 16px; background: #6c757d; color: white; text-decoration: none; border-radius: 8px; font-size: 14px; transition: background 0.3s;" 365 onmouseover="this.style.background='#5a6268';" 366 onmouseout="this.style.background='#6c757d';"> 367 🔄 Start Again 368 </a> 369 </div> 361 370 </div> 362 371 363 372 364 <!-- Initial Page (when NOT an AJAX request) --> 365 <?php if (!$ksrad_isAjaxRequest): ?> 366 <div id="ajaxHeader" class="alert alert-info" role="alert" 373 <!-- Initial Page Header --> 374 <div id="ajaxHeader" class="alert alert-info" role="alert" 367 375 style="text-align: center; background: #FDFDFB; border: 2px solid #E8E8E6; border-radius: 12px; padding: 2rem; margin: 2rem auto; max-width: 600px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);"> 368 376 <h3 style="color: #2A2A28; margin-bottom: 1rem; font-size: 1.3em; font-weight: 600;">🔍 How Much Can You Save With Solar? … … 451 459 452 460 </div> 453 454 <?php endif; ?>455 461 456 462 <?php if (empty(ksrad_get_option('google_solar_api_key', ''))): ?> … … 704 710 <div class="results-section" id="results"> 705 711 <h4 class="text-center">Your Return on Investment (ROI)</h4> 712 <span class="text-center">enter your electricity bill (above)</span> 706 713 <!-- END .section.site-overview --> 707 714 <div class="row mt-4"> … … 713 720 <div class="resultsCol" style="border-left: unset;"> 714 721 <span class="highlight" id="netIncome">0</span> 715 <div class="ms-2 underWrite">MONTHLY INC/EXP</div>722 <div class="ms-2 underWrite">MONTHLY PROFIT/LOSS</div> 716 723 </div> 717 724 </div> … … 775 782 776 783 <?php if (!apply_filters('ksrad_is_premium', false)): ?> 777 <p class="mt-3 align-center" ><a href="https://keiste.com/how-is-our-math/" style="color: #5A5A58;font-size: 0.9rem;" >How is our math?</a></p>784 <p class="mt-3 align-center" style="visibility: hidden;"><a href="https://keiste.com/how-is-our-math/" style="color: #5A5A58;font-size: 0.9rem;" >How is our math?</a></p> 778 785 <?php endif; ?> 779 786 … … 846 853 // Display grant help with correct percent and currency formatting 847 854 $ksrad_currency_symbol = ksrad_get_option('currency', '€'); 848 $ksrad_grant_rate = floatval(ksrad_get_option(' seai_grant_rate', '30')); // default 30%849 $ksrad_grant_cap = floatval(ksrad_get_option(' seai_grant_cap', '162000')); // sensible numeric default855 $ksrad_grant_rate = floatval(ksrad_get_option('grant_rate_domestic', '0')); // default 30% 856 $ksrad_grant_cap = floatval(ksrad_get_option('grant_cap_domestic', '0')); // sensible numeric default 850 857 ?> 851 <div class="input-help-right"><?php echo esc_html($ksrad_grant_rate); ?>% Grant (max <?php echo esc_html($ksrad_currency_symbol); ?><?php echo number_format($ksrad_grant_cap, 0); ?>)</div> 858 <div class="input-help-right"> 859 <span class="grant-description"><?php echo esc_html($ksrad_grant_rate); ?>% Grant (max <?php echo esc_html($ksrad_currency_symbol); ?><?php echo number_format($ksrad_grant_cap, 0); ?>)</span> 860 </div> 852 861 </div> 853 862 </div> … … 927 936 // Currency symbol and getPanelCount - expose globally for external scripts 928 937 window.CURRENCY_SYMBOL = '<?php echo esc_js(ksrad_get_option('currency', '€')); ?>'; 929 938 // if it's the UK, the remove include grant setting 939 if (window.CURRENCY_SYMBOL == '£') { 940 document.getElementById("inclGrant").disabled = true; 941 } 930 942 window.getPanelCount = function getPanelCount() { 931 943 const range = document.querySelector('input[type="range"]#panelCount'); … … 1133 1145 <?php endif; ?> 1134 1146 1147 </div><!-- End .middle-column --> 1148 1135 1149 <?php endif; ?> 1136 1150 </div><!-- End .newContainer --> … … 1151 1165 window.KSRAD_CalcConfig = Object.assign({}, window.KSRAD_CalcConfig || {}, { 1152 1166 currencySymbol: '<?php echo esc_js(ksrad_get_option('currency', '€')); ?>', 1153 defaultExportRate: <?php echo esc_js(floatval(ksrad_get_option('default_export_rate', ' 10')) / 100); ?>,1167 defaultExportRate: <?php echo esc_js(floatval(ksrad_get_option('default_export_rate', '5')) / 100); ?>, 1154 1168 // Grant settings by building type 1155 1169 grantSettings: { … … 1179 1193 <h6 style="color: #2a2a28; text-align: center;font-family: 'Brush Script MT', cursive;margin-top: 2rem;"><a href="https://keiste.com" target="_blank" rel="noopener noreferrer" class="bad-script-regular">Get Your Keiste Solar Report</a></h6> 1180 1194 <?php endif; ?> 1181 1182 < /div><!-- #keiste-solar-report-wrapper -->1195 </div> 1196 <!-- #keiste-solar-report-wrapper --> 1183 1197 <?php 1184 1198 // Return the buffered content to shortcode handler -
keiste-solar-report/tags/1.0.25/readme.txt
r3420878 r3446582 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1.0.2 47 Stable tag: 1.0.25 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html -
keiste-solar-report/trunk/assets/js/charts.js
r3415762 r3446582 24 24 // ===== BREAK-EVEN CHART ===== 25 25 function calculateBreakEvenDataSimple(config) { 26 console.log('[CHART] calculateBreakEvenDataSimple called with config:', config); 27 26 28 const yearlyEnergy = config.yearlyEnergyDcKwh; 27 29 const panelCount = config.panelsCount; 28 const electricityRate = parseFloat(document.getElementById('electricityRate')?.value) || 0.45; 29 30 const exportRate = (() => { 31 const v = document.getElementById('exportRate')?.value; 32 const p = parseFloat(String(v || '').replace(/[^0-9.\-]/g, '')); 33 return Number.isFinite(p) ? (p / 100) : 0.4; 34 })(); 30 31 // Get values from config or inputs 32 const cfg = window.KSRAD_CalcConfig || {}; 33 const electricityRate = parseFloat(document.getElementById('electricityRate')?.value) || 0.36; 34 const feedInTariff = 0.21; // Standard FIT rate 35 const billMonthly = parseFloat(document.getElementById('electricityBill')?.value) || 0; 36 37 const exportRatePercent = cfg.defaultExportRate || 0.05; 35 38 36 39 const inclGrant = document.getElementById('inclGrant')?.checked; 37 const inclACA = document.getElementById('inclACA')?.checked;38 40 const inclLoan = document.getElementById('inclLoan')?.checked; 39 41 const degradation = 0.005; 40 41 // Compute installation cost 42 const installedCapacityKwp = yearlyEnergy / 1000; 43 let computedInstallCost = 0; 44 if (installedCapacityKwp <= 100) { 45 computedInstallCost = installedCapacityKwp * 1500; 46 } else if (installedCapacityKwp <= 250) { 47 computedInstallCost = (100 * 1500) + ((installedCapacityKwp - 100) * 1300); 48 } else { 49 computedInstallCost = (100 * 1500) + (150 * 1300) + ((installedCapacityKwp - 250) * 1100); 50 } 51 52 const seaiGrant = inclGrant ? Math.min(computedInstallCost * 0.3, 162000) : 0; 53 const acaGrant = inclACA ? (computedInstallCost * 0.125) : 0; 54 const totalGrant = seaiGrant + acaGrant; 55 const totalCost = computedInstallCost - totalGrant; 42 const annualIncrease = 0.05; // 5% bill increase per year 43 44 // Get actual net install cost from the calculator 45 // We need to recalculate it here to match what keyFigures does 46 const baseCost = config.installCost || 0; 47 48 console.log('[CHART] baseCost:', baseCost); 49 console.log('[CHART] billMonthly:', billMonthly); 50 console.log('[CHART] inclGrant:', inclGrant); 51 console.log('[CHART] inclLoan:', inclLoan); 52 53 // Get grant settings based on building type 54 const getGrantAmount = () => { 55 try { 56 const grants = cfg.grantSettings || {}; 57 const btEl = document.getElementById('userBuildingType'); 58 const selected = (btEl && btEl.value) ? btEl.value.trim() : 'Residential'; 59 const isResidential = (selected === 'Residential'); 60 const category = isResidential ? 'Residential' : 'Non-Residential'; 61 const grantSettings = grants[category] || { rate: 0.30, cap: 162000 }; 62 return inclGrant ? Math.min(baseCost * grantSettings.rate, grantSettings.cap) : 0; 63 } catch (e) { 64 return inclGrant ? Math.min(baseCost * 0.30, 162000) : 0; 65 } 66 }; 67 68 const seaiGrant = getGrantAmount(); 69 const principal = Math.max(0, baseCost - seaiGrant); 70 71 console.log('[CHART] seaiGrant:', seaiGrant); 72 console.log('[CHART] principal:', principal); 73 74 // Calculate loan payments if applicable 75 const loanAPR = 0.07; // 7% APR 76 const loanYears = 7; 77 let yearlyLoanCost = 0; 78 let totalCost = principal; 79 80 if (inclLoan) { 81 const m = 12; 82 const n = loanYears * m; 83 const r = loanAPR / m; 84 const monthlyRepay = principal * (r / (1 - Math.pow(1 + r, -n))); 85 yearlyLoanCost = monthlyRepay * 12; 86 totalCost = yearlyLoanCost * loanYears; 87 } 88 89 console.log('[CHART] yearlyLoanCost:', yearlyLoanCost); 90 console.log('[CHART] totalCost (investment):', totalCost); 91 92 // Calculate annual usage from bill 93 const annualUsageKwh = (billMonthly * 12) / electricityRate; 94 95 console.log('[CHART] annualUsageKwh:', annualUsageKwh); 56 96 57 97 const years = Array.from({ length: 25 }, (_, i) => i); … … 59 99 const yearDegradation = Math.pow(1 - degradation, year); 60 100 const yearlyEnergyProduction = yearlyEnergy * yearDegradation; 61 const selfConsumedEnergy = yearlyEnergyProduction * (1 - exportRate); 62 const exportedEnergy = yearlyEnergyProduction * exportRate; 63 const yearlySaving = (selfConsumedEnergy * electricityRate) + (exportedEnergy * exportRate); 64 65 const totalSaving = year === 0 ? 0 : years 101 102 // Calculate self-consumption and export (same logic as main calculator) 103 const maxSelfConsumption = yearlyEnergyProduction * (1 - exportRatePercent); 104 const actualSelfConsumption = Math.min(maxSelfConsumption, annualUsageKwh); 105 const exportedEnergy = yearlyEnergyProduction - actualSelfConsumption; 106 107 // Apply escalating electricity rate 108 const escalatedRate = electricityRate * Math.pow(1 + annualIncrease, year); 109 110 // Year's savings 111 const yearlySaving = (actualSelfConsumption * escalatedRate) + (exportedEnergy * feedInTariff); 112 113 // Year's loan cost (only for first 7 years if loan) 114 const yearLoanCost = (inclLoan && year < loanYears) ? yearlyLoanCost : 0; 115 116 // Net saving for this year 117 const netYearlySaving = yearlySaving - yearLoanCost; 118 119 // Cumulative savings up to this year 120 const totalSaving = year === 0 ? -totalCost : years 66 121 .slice(1, year + 1) 67 122 .reduce((acc, y) => { 68 123 const yDegradation = Math.pow(1 - degradation, y); 69 124 const yEnergyProduction = yearlyEnergy * yDegradation; 70 const ySelfConsumed = yEnergyProduction * (1 - exportRate); 71 const yExported = yEnergyProduction * exportRate; 72 return acc + (ySelfConsumed * electricityRate) + (yExported * exportRate); 73 }, 0); 74 75 return totalSaving - totalCost; 125 const yMaxSelfConsumption = yEnergyProduction * (1 - exportRatePercent); 126 const yActualSelfConsumption = Math.min(yMaxSelfConsumption, annualUsageKwh); 127 const yExported = yEnergyProduction - yActualSelfConsumption; 128 const yEscalatedRate = electricityRate * Math.pow(1 + annualIncrease, y); 129 const ySaving = (yActualSelfConsumption * yEscalatedRate) + (yExported * feedInTariff); 130 const yLoanCost = (inclLoan && y < loanYears) ? yearlyLoanCost : 0; 131 return acc + (ySaving - yLoanCost); 132 }, -totalCost); 133 134 return totalSaving; 76 135 }); 136 137 const breakEvenYear = savings.findIndex(saving => saving >= 0); 138 console.log('[CHART] Break-even year:', breakEvenYear); 139 console.log('[CHART] First 5 years cumulative savings:', savings.slice(0, 5)); 77 140 78 141 return { 79 142 cost: totalCost, 80 143 savings: savings, 81 breakEvenYear: savings.findIndex(saving => saving >= 0)144 breakEvenYear: breakEvenYear 82 145 }; 83 146 } -
keiste-solar-report/trunk/assets/js/solar-calculator-main.js
r3419489 r3446582 302 302 console.log('install_cost', install_cost); 303 303 304 const net_install_cost = Math.round(Number(baseCost - seaiGrant + (inclLoan ? (baseCost - seaiGrant) * interest : 0)));305 console.log('net_install_cost', net_install_cost);306 307 304 // Production 308 305 const yearlyEnergyKWhYr0 = yearlyEnergy; // year 0 nominal from config … … 315 312 const monthlyRepay = Math.round(inclLoan ? principal * (r / (1 - Math.pow(1 + r, -n))) : 0); 316 313 const yearlyLoanCost = Math.round(inclLoan ? monthlyRepay * 12 : 0); 314 315 // Net install cost: if loan, show total loan payments; otherwise show upfront cost after grant 316 const net_install_cost = inclLoan ? Math.round(yearlyLoanCost * LENGTH_OF_PAYBACK) : Math.round(baseCost - seaiGrant); 317 console.log('net_install_cost', net_install_cost); 317 318 318 319 // Total 25-year savings (benefits - cost + ACA if included) … … 341 342 342 343 // First-year annual saving (calculate this BEFORE payback so we can use it) 343 const savings_year0 = (() => { 344 // Current electricity usage based on their bill 345 const current_usage_kwh = (billMonthly * 12) / RETAIL; 346 console.log('Bill calculation - billMonthly:', billMonthly, 'RETAIL:', RETAIL, 'current_usage_kwh:', current_usage_kwh); 347 348 // Total solar production (use actual config data, not formula) 349 const annual_solar_kwh = yearlyEnergy > 0 ? yearlyEnergy : (panels * DAY_POWER_AVG * DAYS_IN_YR); 350 console.log('Annual solar production:', annual_solar_kwh, 'kWh (from yearlyEnergy:', yearlyEnergy, ')'); 351 352 // Self-consumption: what they can use themselves (capped by their actual usage) 353 const max_self_consumption_kwh = annual_solar_kwh * (1 - exportRate); 354 const actual_self_consumption_kwh = Math.min(max_self_consumption_kwh, current_usage_kwh); 355 console.log('Export rate:', exportRate, 'Max self:', max_self_consumption_kwh, 'Actual self:', actual_self_consumption_kwh, 'Current usage:', current_usage_kwh); 356 357 // Export: everything not self-consumed 358 const export_kwh = annual_solar_kwh - actual_self_consumption_kwh; 359 console.log('Export kWh:', export_kwh); 360 361 // Financial benefits 362 const bill_savings = actual_self_consumption_kwh * RETAIL; // Avoided electricity cost 363 const export_income = export_kwh * FIT; // Export income 364 console.log('Bill savings:', bill_savings, '(', actual_self_consumption_kwh, '*', RETAIL, ')'); 365 console.log('Export income:', export_income, '(', export_kwh, '*', FIT, ')'); 366 367 const loan_cost = inclLoan ? yearlyLoanCost : 0; 368 const acaBump = (inclACA ? acaAllowance : 0); 369 370 return bill_savings + export_income - loan_cost + acaBump; 371 })(); 344 // ===== FIXED PRODUCTION & SAVINGS MODEL ===== 345 346 // Annual usage derived from bill 347 const current_usage_kwh = (billMonthly * MONTHS_IN_YR) / RETAIL; 348 349 // Total solar production 350 const annual_solar_kwh = 351 panels * 352 PANEL_POWER_W / 1000 * 353 DAY_POWER_AVG * 354 DAYS_IN_YR; 355 356 // Self-consumption is limited by actual usage 357 const max_self_consumption_kwh = annual_solar_kwh * (1 - exportRate); 358 const actual_self_consumption_kwh = Math.min(max_self_consumption_kwh, current_usage_kwh); 359 360 // Export is what's left after self-consumption 361 const export_kwh = annual_solar_kwh - actual_self_consumption_kwh; 362 363 // --- FINANCIALS --- 364 const bill_savings = actual_self_consumption_kwh * RETAIL; 365 const export_income = export_kwh * FIT; 366 367 // Total benefit (before loan / adjustments) 368 const savings_year0 = bill_savings + export_income - yearlyLoanCost; 369 370 console.log( 371 'YEAR 0 BREAKDOWN:\n' + 372 ' annual_solar_kwh: ' + annual_solar_kwh + '\n' + 373 ' current_usage_kwh: ' + current_usage_kwh + '\n' + 374 ' exportRate: ' + exportRate + '\n' + 375 ' max_self_consumption_kwh: ' + max_self_consumption_kwh + '\n' + 376 ' actual_self_consumption_kwh: ' + actual_self_consumption_kwh + '\n' + 377 ' export_kwh: ' + export_kwh + '\n' + 378 ' RETAIL: ' + RETAIL + '\n' + 379 ' FIT: ' + FIT + '\n' + 380 ' bill_savings: ' + bill_savings + '\n' + 381 ' export_income: ' + export_income + '\n' + 382 ' yearlyLoanCost: ' + yearlyLoanCost + '\n' + 383 ' savings_year0: ' + savings_year0 384 ); 372 385 373 386 // Monthly charge (Year 0) - based on actual savings 374 const monthly_charge = (savings_year0 / 12) - billMonthly; 375 387 // Only show meaningful net income when there's a bill to offset 388 const monthly_charge = billMonthly > 0 ? (savings_year0 / 12) - billMonthly : 0; 389 376 390 // Payback period (years) - uses actual net annual savings 377 const payback_period = (() => { 378 // Investment amount to pay back 379 const investment = inclLoan ? loanCost25 : net_install_cost; 380 381 // Net annual savings (year 0) - this is what actually goes back into your pocket 382 const annualSavings = savings_year0; 383 384 // Payback = Investment / Annual Savings 385 return annualSavings > 0 ? investment / annualSavings : 0; 386 })(); 391 // Investment amount to pay back 392 const investment = inclLoan ? loanCost25 : net_install_cost; 393 // Payback = Investment / Annual Savings 394 const payback_period = savings_year0 > 0 ? investment / savings_year0 : 0; 387 395 388 396 // ROI over 25 years (%) … … 394 402 // CO2 reduction over life 395 403 const co2_reduction = CO2_COEFFICIENT_TONNES * 396 Array.from({ length: YRS_OF_SYSTEM }, (_, y) =>404 Array.from({ length: YRS_OF_SYSTEM }, (_, y) => 397 405 panels * DAY_POWER_AVG * Math.pow(1 - SOLAR_PANEL_DEGRADATION, y) * DAYS_IN_YR 398 406 ).reduce((a, b) => a + b, 0); … … 407 415 408 416 // ========= 5) GUI UPDATES ========= 417 function updateGrantDescription() { 418 // Update the grant description text based on current building type 419 try { 420 const cfg = window.KSRAD_CalcConfig || {}; 421 const grants = cfg.grantSettings || {}; 422 const btEl = document.getElementById('userBuildingType'); 423 const selected = (btEl && btEl.value) ? btEl.value.trim() : 'Residential'; 424 425 const isResidential = (selected === 'Residential'); 426 const category = isResidential ? 'Residential' : 'Non-Residential'; 427 428 const grantRate = grants[category] ? (grants[category].rate || 0.30) : 0.30; 429 const grantCap = grants[category] ? (grants[category].cap || 162000) : 162000; 430 431 // Find and update grant description elements 432 const grantDescElements = document.querySelectorAll('.grant-description, [data-grant-description]'); 433 grantDescElements.forEach(el => { 434 const percentDisplay = Math.round(grantRate * 100); 435 const capDisplay = CURRENCY_SYMBOL + grantCap.toLocaleString('en-IE'); 436 el.textContent = `${percentDisplay}% Grant (max ${capDisplay})`; 437 }); 438 } catch (e) { 439 console.error('Error updating grant description:', e); 440 } 441 } 442 409 443 function updateResults(state, figs) { 410 444 const setTxt = (id, txt) => { … … 419 453 setTxt('installationCost', fmtEuro(figs.install_cost)); 420 454 setTxt('grant', fmtEuro(figs.seaiGrant)); 455 456 // Update grant description text dynamically 457 updateGrantDescription(); 458 421 459 setTxt('panelCount', fmtNum(state.panels, 0)); 422 460 // Annual energy production display: support both legacy `yearlyEnergy` and current `yearlyEnergyValue` IDs … … 453 491 }); 454 492 }; 493 494 // Only show meaningful figures when there's a bill 495 if (!state.billMonthly || state.billMonthly === 0) { 496 setTxt('netCost', CURRENCY_SYMBOL + '0'); 497 setTxt('totalSavings', CURRENCY_SYMBOL + '0'); 498 setTxt('roi', '0%'); 499 setTxt('co2Reduction', '0 t'); 500 setTxt('annualSavings', CURRENCY_SYMBOL + '0'); 501 setTxt('paybackPeriod', '0 years'); 502 return; 503 } 504 455 505 // #installation-details 456 506 setTxt('netCost', fmtEuro(figs.net_install_cost)); … … 478 528 if (window.breakEvenChart && window.breakEvenChart.data && typeof window.calculateBreakEvenDataSimple === 'function') { 479 529 try { 530 console.log('[updateBreakEvenChart] Inside try block, billMonthly:', state.billMonthly); 531 480 532 // On page load with no bill, show zero baseline 481 533 if (!state.billMonthly || state.billMonthly === 0) { … … 487 539 } 488 540 489 const cfg = { panelsCount: state.panels, yearlyEnergyDcKwh: figs.yearlyEnergyKWh || (state.panels * DAY_POWER_AVG * DAYS_IN_YR) }; 541 console.log('[updateBreakEvenChart] About to create config object'); 542 console.log('[updateBreakEvenChart] figs.yearlyEnergyKWh:', figs.yearlyEnergyKWh); 543 console.log('[updateBreakEvenChart] figs.baseCost:', figs.baseCost); 544 545 const cfg = { 546 panelsCount: state.panels, 547 yearlyEnergyDcKwh: figs.yearlyEnergyKWh || (state.panels * DAY_POWER_AVG * DAYS_IN_YR), 548 installCost: figs.baseCost 549 }; 490 550 console.log('Calling calculateBreakEvenDataSimple with:', cfg); 491 551 const be = window.calculateBreakEvenDataSimple(cfg); … … 713 773 console.log('[INIT] solar-calculator-main.js initializing...'); 714 774 console.log('[INIT] document.readyState:', document.readyState); 715 // Apply configuration from PHP if available 775 776 // Apply configuration from PHP if available (don't wait, just use defaults if not ready) 716 777 if (window.KSRAD_CalcConfig) { 717 778 console.log('[INIT] KSRAD_CalcConfig found:', window.KSRAD_CalcConfig); 718 779 CURRENCY_SYMBOL = window.KSRAD_CalcConfig.currencySymbol || CURRENCY_SYMBOL; 719 720 // Also expose globally for consistency with other scripts721 780 window.CURRENCY_SYMBOL = CURRENCY_SYMBOL; 722 781 } else { 723 console.warn('[INIT] KSRAD_CalcConfig not found ');782 console.warn('[INIT] KSRAD_CalcConfig not found - using defaults'); 724 783 } 725 784 -
keiste-solar-report/trunk/includes/class-ksrad-calculator.php
r3415762 r3446582 3 3 * Solar Calculator class for Keiste Solar Report 4 4 * 5 <<<<<<< HEAD 6 ======= 7 * This code is just the placeholder code. 8 >>>>>>> fed100d (added UK no solar. grant % defaults to zero now. the math is still off though.) 5 9 * Handles solar panel calculations and renders the calculator frontend. 6 10 * -
keiste-solar-report/trunk/includes/plugin-init.php
r3420871 r3446582 217 217 'googleSolarApiKey' => ksrad_get_option('google_solar_api_key', ''), 218 218 'reportKey' => ksrad_get_option('report_key', ''), 219 'defaultElectricityRate' => ksrad_get_option('default_electricity_rate', '0. 17'),220 'defaultExportRate' => ksrad_get_option('default_export_rate', ' 10'),221 'defaultFeedInTariff' => ksrad_get_option('default_feed_in_tariff', '0. 15'),219 'defaultElectricityRate' => ksrad_get_option('default_electricity_rate', '0.36'), 220 'defaultExportRate' => ksrad_get_option('default_export_rate', '5'), 221 'defaultFeedInTariff' => ksrad_get_option('default_feed_in_tariff', '0.20'), 222 222 'defaultLoanApr' => ksrad_get_option('default_loan_apr', '5'), 223 223 'loanTerm' => ksrad_get_option('loan_term', '7'), 224 224 'annualPriceIncrease' => ksrad_get_option('annual_price_increase', '5'), 225 'currency' => ksrad_get_option('currency', ' $'),226 'country' => ksrad_get_option('country', ' United States'),227 'systemCostRatio' => ksrad_get_option('system_cost_ratio', ' 650'),225 'currency' => ksrad_get_option('currency', '€'), 226 'country' => ksrad_get_option('country', 'Republic of Ireland'), 227 'systemCostRatio' => ksrad_get_option('system_cost_ratio', '1600'), 228 228 'grantRateDomestic' => ksrad_get_option('grant_rate_domestic', '30'), 229 229 'grantCapDomestic' => ksrad_get_option('grant_cap_domestic', '7500'), … … 311 311 'report_key' => '', 312 312 'logo_url' => '', 313 'default_electricity_rate' => '0. 17',314 'default_export_rate' => ' 10',315 'default_feed_in_tariff' => '0. 14',313 'default_electricity_rate' => '0.34', 314 'default_export_rate' => '5', 315 'default_feed_in_tariff' => '0.20', 316 316 'default_loan_apr' => '5', 317 317 'loan_term' => '7', 318 318 'annual_price_increase' => '5', 319 'currency' => ' $',320 'country' => ' United States',321 'system_cost_ratio' => ' 650',322 'cost_domestic' => ' 650',323 'cost_small' => ' 600',324 'cost_medium' => ' 500',325 'cost_large' => ' 425',319 'currency' => '€', 320 'country' => 'Republic of Ireland', 321 'system_cost_ratio' => '1800', 322 'cost_domestic' => '1800', 323 'cost_small' => '1600', 324 'cost_medium' => '1200', 325 'cost_large' => '1000', 326 326 'grant_rate_domestic' => '30', 327 327 'grant_cap_domestic' => '7500', -
keiste-solar-report/trunk/keiste-solar-report.php
r3420878 r3446582 5 5 * Plugin URI: https://keiste.com/keiste-solar-report 6 6 * Description: Comprehensive solar panel analysis tool with ROI calculations, Google Solar API integration, interactive charts, and PDF report generation. 7 * Version: 1.0.2 47 * Version: 1.0.25 8 8 * Author: Dara Burke, Keiste 9 9 * Author URI: https://keiste.com … … 34 34 // Define plugin constants (only once) with ksrad_ namespace 35 35 if (!defined('KSRAD_VERSION')) { 36 define('KSRAD_VERSION', '1.0.2 4');36 define('KSRAD_VERSION', '1.0.25'); 37 37 } 38 38 if (!defined('KSRAD_PLUGIN_DIR')) { … … 325 325 <div class="container"> 326 326 327 <div class="text-center mt-4">327 <div class="text-center"> 328 328 <?php 329 329 $ksrad_logo_url = ksrad_get_option('logo_url', ''); … … 333 333 } 334 334 ?> 335 <a href="<?php echo esc_url(home_url('/ ')); ?>">335 <a href="<?php echo esc_url(home_url('/keiste-solar-report/')); ?>"> 336 336 <img src="<?php echo esc_url($ksrad_logo_url); ?>" alt="Company Logo" 337 337 class="img-fluid logo-image" style="max-width: 130px; width: 100%;"> … … 359 359 ?> 360 360 <h1>Solar Report<sup style="color: red;font-size: 16px;vertical-align: middle;top: -14px;"> <?php echo esc_html($ksrad_country_code); ?></sup></h1> 361 <div style="text-align: center; margin: 30px 0;"> 362 <a href="<?php echo esc_url(remove_query_arg(['lat', 'lng', 'business_name'])); ?>" 363 class="btn btn-secondary" 364 style="display: inline-block; padding: 8px 16px; background: #6c757d; color: white; text-decoration: none; border-radius: 8px; font-size: 14px; transition: background 0.3s;" 365 onmouseover="this.style.background='#5a6268';" 366 onmouseout="this.style.background='#6c757d';"> 367 🔄 Start Again 368 </a> 369 </div> 361 370 </div> 362 371 363 372 364 <!-- Initial Page (when NOT an AJAX request) --> 365 <?php if (!$ksrad_isAjaxRequest): ?> 366 <div id="ajaxHeader" class="alert alert-info" role="alert" 373 <!-- Initial Page Header --> 374 <div id="ajaxHeader" class="alert alert-info" role="alert" 367 375 style="text-align: center; background: #FDFDFB; border: 2px solid #E8E8E6; border-radius: 12px; padding: 2rem; margin: 2rem auto; max-width: 600px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);"> 368 376 <h3 style="color: #2A2A28; margin-bottom: 1rem; font-size: 1.3em; font-weight: 600;">🔍 How Much Can You Save With Solar? … … 451 459 452 460 </div> 453 454 <?php endif; ?>455 461 456 462 <?php if (empty(ksrad_get_option('google_solar_api_key', ''))): ?> … … 704 710 <div class="results-section" id="results"> 705 711 <h4 class="text-center">Your Return on Investment (ROI)</h4> 712 <span class="text-center">enter your electricity bill (above)</span> 706 713 <!-- END .section.site-overview --> 707 714 <div class="row mt-4"> … … 713 720 <div class="resultsCol" style="border-left: unset;"> 714 721 <span class="highlight" id="netIncome">0</span> 715 <div class="ms-2 underWrite">MONTHLY INC/EXP</div>722 <div class="ms-2 underWrite">MONTHLY PROFIT/LOSS</div> 716 723 </div> 717 724 </div> … … 775 782 776 783 <?php if (!apply_filters('ksrad_is_premium', false)): ?> 777 <p class="mt-3 align-center" ><a href="https://keiste.com/how-is-our-math/" style="color: #5A5A58;font-size: 0.9rem;" >How is our math?</a></p>784 <p class="mt-3 align-center" style="visibility: hidden;"><a href="https://keiste.com/how-is-our-math/" style="color: #5A5A58;font-size: 0.9rem;" >How is our math?</a></p> 778 785 <?php endif; ?> 779 786 … … 846 853 // Display grant help with correct percent and currency formatting 847 854 $ksrad_currency_symbol = ksrad_get_option('currency', '€'); 848 $ksrad_grant_rate = floatval(ksrad_get_option(' seai_grant_rate', '30')); // default 30%849 $ksrad_grant_cap = floatval(ksrad_get_option(' seai_grant_cap', '162000')); // sensible numeric default855 $ksrad_grant_rate = floatval(ksrad_get_option('grant_rate_domestic', '0')); // default 30% 856 $ksrad_grant_cap = floatval(ksrad_get_option('grant_cap_domestic', '0')); // sensible numeric default 850 857 ?> 851 <div class="input-help-right"><?php echo esc_html($ksrad_grant_rate); ?>% Grant (max <?php echo esc_html($ksrad_currency_symbol); ?><?php echo number_format($ksrad_grant_cap, 0); ?>)</div> 858 <div class="input-help-right"> 859 <span class="grant-description"><?php echo esc_html($ksrad_grant_rate); ?>% Grant (max <?php echo esc_html($ksrad_currency_symbol); ?><?php echo number_format($ksrad_grant_cap, 0); ?>)</span> 860 </div> 852 861 </div> 853 862 </div> … … 927 936 // Currency symbol and getPanelCount - expose globally for external scripts 928 937 window.CURRENCY_SYMBOL = '<?php echo esc_js(ksrad_get_option('currency', '€')); ?>'; 929 938 // if it's the UK, the remove include grant setting 939 if (window.CURRENCY_SYMBOL == '£') { 940 document.getElementById("inclGrant").disabled = true; 941 } 930 942 window.getPanelCount = function getPanelCount() { 931 943 const range = document.querySelector('input[type="range"]#panelCount'); … … 1133 1145 <?php endif; ?> 1134 1146 1147 </div><!-- End .middle-column --> 1148 1135 1149 <?php endif; ?> 1136 1150 </div><!-- End .newContainer --> … … 1151 1165 window.KSRAD_CalcConfig = Object.assign({}, window.KSRAD_CalcConfig || {}, { 1152 1166 currencySymbol: '<?php echo esc_js(ksrad_get_option('currency', '€')); ?>', 1153 defaultExportRate: <?php echo esc_js(floatval(ksrad_get_option('default_export_rate', ' 10')) / 100); ?>,1167 defaultExportRate: <?php echo esc_js(floatval(ksrad_get_option('default_export_rate', '5')) / 100); ?>, 1154 1168 // Grant settings by building type 1155 1169 grantSettings: { … … 1179 1193 <h6 style="color: #2a2a28; text-align: center;font-family: 'Brush Script MT', cursive;margin-top: 2rem;"><a href="https://keiste.com" target="_blank" rel="noopener noreferrer" class="bad-script-regular">Get Your Keiste Solar Report</a></h6> 1180 1194 <?php endif; ?> 1181 1182 < /div><!-- #keiste-solar-report-wrapper -->1195 </div> 1196 <!-- #keiste-solar-report-wrapper --> 1183 1197 <?php 1184 1198 // Return the buffered content to shortcode handler -
keiste-solar-report/trunk/readme.txt
r3420878 r3446582 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1.0.2 47 Stable tag: 1.0.25 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html
Note: See TracChangeset
for help on using the changeset viewer.