Novemcore Logo
ovemcore
Services
Software
Wir können Software!
Mit unseren eigenen Lösungen setzen wir neue Maßstäbe und sind Partner für führende Software-Produkte.
Software
PULSE
PULSE
SAVE
SAVE
Agicap
Agicap
Moss
Moss
TreasuryView
TreasuryView
ValueWorks
ValueWorks
Referenzen
Ressourcen
Webinare & EventsPodcastBlog
Über uns
Über UnsKarriere
Kontaktieren
SAVE Einsparrechner
Jetzt kontaktieren

1) Unternehmensprofil

Für die Standardversion reichen vier Eingaben.

pro Jahr
EUR
20,0 %
%
pro Jahr
aktiv im Zeitraum
Erweiterte Annahmen anpassenKostenverteilung und Einsparquoten je Kostenblock bearbeiten
+
Summe Kostenanteile = 100,0 %
Kostenblock Anteil Kurzfr. reduzierbar Kurzfr. Einsparquote Langfr. reduzierbar Langfr. Einsparquote

2) Ihr Einsparpotenzial

Die Ergebnisse werden direkt aus der Excel-Logik berechnet und in Tsd. bzw. Mio. EUR verdichtet.

Kurzfristig pro Jahr
56.003 EUR
280.016 EUR über 5 Jahre
Langfristig pro Jahr
246.330 EUR
1.231.648 EUR über 5 Jahre
Rechnungen je Lieferant
46,7
Multiplikator: 1,10
Hohe Rechnungsdichte je Lieferant erhöht das modellierte Potenzial leicht.

3) Breakdown nach Kostenblöcken

Die Tabelle zeigt Kostenbasis, Einsparquote und Einsparpotenzial pro Block für kurz- und langfristige Perspektive.

Kostenblock Kurzfr. Kostenbasis Kurzfr. Potenzial Langfr. Kostenbasis Langfr. Potenzial

4) Ergebnis per E-Mail anfordern

Erhalten Sie Ihre detaillierte Potenzialanalyse und Kostenübersicht direkt per E-Mail.

<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;600;800&display=swap" rel="stylesheet">
<style>
 :root {
   --bg: #f4fbf7;
   --surface: #ffffff;
   --surface-2: #eff8f1;
   --text: #143128;
   --muted: #5e756a;
   --line: #d8e7dd;
   --brand: #0f8b57;
   --brand-dark: #0b6a42;
   --brand-soft: #dff4e7;
   --warning: #fff4d6;
   --warning-text: #8a6313;
   --danger: #fde9e7;
   --danger-text: #8c332c;
   --shadow: 0 14px 40px rgba(15, 60, 39, 0.08);
   --radius: 20px;
 }
 * {
   box-sizing: border-box;
 }
 body {
   margin: 0;
   font-family: 'Plus Jakarta Sans', Inter, system-ui, sans-serif;
   background: radial-gradient(circle at top right, rgba(15, 139, 87, 0.08), transparent 26%), linear-gradient(180deg, #f9fdfb 0%, var(--bg) 100%);
   color: var(--text);
   line-height: 1.45;
 }
 .wrap {
   max-width: 1400px; /* Increased to give the second column more space */
   margin: 0 auto;
   padding: 32px 20px 80px;
 }
 .card {
   background: var(--surface);
   border: 1px solid rgba(15, 60, 39, 0.08);
   border-radius: var(--radius);
   box-shadow: var(--shadow);
 }
 .grid {
   display: grid;
   grid-template-columns: 380px 1fr; /* Slimmed sidebar slightly to give table more room */
   gap: 32px;
   align-items: start;
 }
 .panel {
   padding: 22px;
   position: sticky;
   top: 18px;
   align-self: start;
 }
 .section-title {
   font-size: 20px;
   margin: 0 0 6px;
   letter-spacing: -0.02em;
 }
 .section-copy {
   margin: 0 0 18px;
   color: var(--muted);
   font-size: 14px;
 }
 .input-group {
   margin-bottom: 16px;
 }
 .label-row {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 12px;
   margin-bottom: 8px;
   font-weight: 600;
   font-size: 14px;
 }
 .hint {
   color: var(--muted);
   font-size: 12px;
   font-weight: 500;
 }
 .num-wrap {
   position: relative;
 }
 .num-wrap input[type='number'],
 .num-wrap input[type='text'],
 .num-wrap input[type='email'],
 select {
   width: 100%;
   border-radius: 14px;
   border: 1px solid var(--line);
   background: #fff;
   padding: 14px 16px;
   color: var(--text);
   font-size: 16px;
   outline: none;
   transition: 0.2s border-color, 0.2s box-shadow;
 }
 .num-wrap input:focus,
 select:focus {
   border-color: rgba(15, 139, 87, 0.55);
   box-shadow: 0 0 0 4px rgba(15, 139, 87, 0.1);
 }
 .prefix,
 .suffix {
   position: absolute;
   top: 50%;
   transform: translateY(-50%);
   font-size: 14px;
   color: var(--muted);
   pointer-events: none;
 }
 .prefix {
   left: 14px;
 }
 .suffix {
   right: 14px;
 }
 .has-prefix input {
   padding-left: 34px;
 }
 .has-suffix input {
   padding-right: 58px;
 }
 input[type='range'] {
   width: 100%;
   accent-color: var(--brand);
   margin: 10px 0 0;
 }
 .toggle {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 14px;
   background: var(--surface-2);
   border: 1px solid var(--line);
   border-radius: 16px;
   padding: 14px 16px;
   cursor: pointer;
   margin-top: 8px;
 }
 .toggle strong {
   display: block;
   font-size: 14px;
 }
 .toggle span {
   color: var(--muted);
   font-size: 12px;
 }
 .toggle-icon {
   width: 30px;
   height: 30px;
   border-radius: 999px;
   background: #fff;
   border: 1px solid var(--line);
   display: grid;
   place-items: center;
   font-weight: 700;
   color: var(--brand-dark);
   flex: 0 0 auto;
 }
 .primary-btn,
 .secondary-btn {
   width: 100%;
   border: 0;
   border-radius: 14px;
   padding: 14px 16px;
   font-size: 15px;
   font-weight: 700;
   cursor: pointer;
   transition: transform 0.15s ease, opacity 0.15s ease;
 }
 .primary-btn {
   background: linear-gradient(135deg, var(--brand) 0%, var(--brand-dark) 100%);
   color: #fff;
   margin-top: 16px;
 }
 .secondary-btn {
   background: #fff;
   border: 1px solid var(--line);
   color: var(--text);
   margin-top: 10px;
 }
 .primary-btn:hover,
 .secondary-btn:hover {
   transform: translateY(-1px);
 }
 .results {
   display: flex;
   flex-direction: column;
   gap: 22px;
   min-width: 0;
 }
 .summary-card {
   padding: 22px;
 }
 .summary-grid {
   display: grid;
   grid-template-columns: repeat(3, minmax(0, 1fr));
   gap: 14px;
   margin-top: 18px;
 }
 .kpi {
   border: 1px solid var(--line);
   border-radius: 18px;
   padding: 18px;
   background: linear-gradient(180deg, #fff 0%, #f8fcf9 100%);
 }
 .kpi .label {
   font-size: 12px;
   letter-spacing: 0.06em;
   text-transform: uppercase;
   color: var(--muted);
   margin-bottom: 8px;
   font-weight: 700;
 }
 .kpi .value {
   font-size: clamp(26px, 2.8vw, 38px);
   font-weight: 800;
   line-height: 1;
   letter-spacing: -0.03em;
 }
 .kpi .sub {
   margin-top: 8px;
   color: var(--muted);
   font-size: 13px;
 }
 .band {
   display: inline-flex;
   align-items: center;
   gap: 8px;
   border-radius: 999px;
   padding: 7px 12px;
   font-size: 12px;
   font-weight: 700;
   background: var(--warning);
   color: var(--warning-text);
   margin-top: 14px;
 }
 .ok-band {
   background: var(--brand-soft);
   color: var(--brand-dark);
 }
 .danger-band {
   background: var(--danger);
   color: var(--danger-text);
 }
 .summary-text {
   white-space: pre-line;
   color: var(--text);
   font-size: 15px;
   margin-top: 14px;
 }
 table {
   width: 100%;
   border-collapse: collapse;
 }
 .table-card {
   padding: 8px 0 0;
   overflow: hidden;
 }
 .table-header {
   padding: 22px 22px 0;
 }
 thead th {
   font-size: 12px;
   text-transform: uppercase;
   letter-spacing: 0.06em;
   color: var(--muted);
   text-align: left;
   background: #f8fbf9;
   border-bottom: 1px solid var(--line);
   padding: 14px 12px;
   position: sticky;
   top: 0;
   z-index: 1;
 }
 tbody td {
   padding: 14px 12px;
   border-bottom: 1px solid #edf3ef;
   vertical-align: top;
   font-size: 14px;
 }
 tbody tr:hover {
   background: #fbfefc;
 }
 
 /* Scrollbar class for all tables */
 .table-scroll {
   overflow-x: auto;
   -webkit-overflow-scrolling: touch;
   width: 100%;
 }
 
 .muted {
   color: var(--muted);
 }
 .advanced {
   display: none;
   margin-top: 16px;
 }
 .advanced-card {
   padding: 22px;
 }
 .advanced.open {
   display: block;
 }
 .advanced table input {
   width: 65px;
   padding: 8px 4px;
   border-radius: 8px;
   border: 1px solid var(--line);
   font-size: 13px;
   text-align: center;
 }
 .advanced table th,
 .advanced table td {
   padding: 10px 8px;
   border-bottom: 1px solid #edf3ef;
   font-size: 13px;
 }
 .advanced table thead th {
   position: static;
 }
 .advanced table {
     width: 100%;
     min-width: 750px; /* Forces scrollbar on small screens */
 }
 .advanced .name-col {
   min-width: 250px;
   font-weight: 600;
 }
 .lead-form {
   padding: 22px;
 }
 .form-grid {
   display: grid;
   grid-template-columns: repeat(2, minmax(0, 1fr));
   gap: 14px;
 }
 .full {
   grid-column: 1 / -1;
 }
 .checkbox {
   display: flex;
   gap: 10px;
   align-items: flex-start;
   font-size: 13px;
   color: var(--muted);
   margin-top: 8px;
 }
 .checkbox input {
   margin-top: 4px;
 }
 .status-box {
   margin-top: 14px;
   padding: 12px 14px;
   border-radius: 12px;
   display: none;
   font-size: 14px;
   font-weight: 600;
 }
 .status-box.show {
   display: block;
 }
 .status-success {
   background: var(--brand-soft);
   color: var(--brand-dark);
 }
 .status-error {
   background: var(--danger);
   color: var(--danger-text);
 }
 @media (max-width: 1080px) {
   .grid {
     grid-template-columns: 1fr;
   }
   .panel {
     position: static;
   }
   .summary-grid {
     grid-template-columns: 1fr;
   }
 }
 @media (max-width: 720px) {
   .form-grid {
     grid-template-columns: 1fr;
   }
   .wrap {
     padding-inline: 14px;
   }
   .panel,
   .summary-card,
   .lead-form,
   .advanced-card {
     padding: 18px;
   }
 }
</style>

<div class="wrap">
 <section class="grid">
   <aside class="card panel">
     <h2 class="section-title">1) Unternehmensprofil</h2>
     <p class="section-copy">Für die Standardversion reichen vier Eingaben.</p>
     
     <div class="input-group">
       <div class="label-row"><label for="revenue">Umsatz</label><span class="hint">pro Jahr</span></div>
       <div class="num-wrap has-suffix"><input id="revenue" min="0" step="10000" type="number" value="8000000" /><span class="suffix">EUR</span></div>
     </div>
     
     <div class="input-group">
       <div class="label-row">
         <label for="margin">Gewinnmarge</label><span class="hint"><span id="marginLabel">20,0 %</span></span>
       </div>
       <div class="num-wrap has-suffix"><input id="marginDisplay" max="100" min="0" step="0.1" type="number" value="20" /><span class="suffix">%</span></div>
       <input id="margin" max="60" min="0" step="0.5" type="range" value="20" />
     </div>
     
     <div class="input-group">
       <div class="label-row"><label for="invoiceCount">Anzahl Rechnungen</label><span class="hint">pro Jahr</span></div>
       <div class="num-wrap"><input id="invoiceCount" min="0" step="1" type="number" value="7000" /></div>
     </div>
     
     <div class="input-group">
       <div class="label-row"><label for="supplierCount">Anzahl Lieferanten</label><span class="hint">aktiv im Zeitraum</span></div>
       <div class="num-wrap"><input id="supplierCount" min="1" step="1" type="number" value="150" /></div>
     </div>
     
     <button class="primary-btn" id="recalculateBtn">Berechnung aktualisieren</button>
     <button class="secondary-btn" id="resetBtn">Standardwerte wiederherstellen</button>
   </aside>

   <div class="results">
     
     <section class="card advanced-card">
        <div class="toggle" id="toggleAdvanced" style="margin-top: 0;">
         <div><strong>Erweiterte Annahmen anpassen</strong><span>Kostenverteilung und Einsparquoten je Kostenblock bearbeiten</span></div>
         <div class="toggle-icon" id="toggleIcon">+</div>
       </div>
       <div class="advanced" id="advancedPanel">
         <div class="band ok-band" id="shareStatus">Summe Kostenanteile = 100,0 %</div>
         
         <div class="table-scroll" style="margin-top: 12px; border: 1px solid var(--line); border-radius: 12px;">
           <table aria-label="Erweiterte Annahmen">
             <thead>
               <tr>
                 <th class="name-col">Kostenblock</th>
                 <th>Anteil</th>
                 <th>Kurzfr. reduzierbar</th>
                 <th>Kurzfr. Einsparquote</th>
                 <th>Langfr. reduzierbar</th>
                 <th>Langfr. Einsparquote</th>
               </tr>
             </thead>
             <tbody id="assumptionTableBody"></tbody>
           </table>
         </div>

       </div>
     </section>

     <section class="card summary-card">
       <h2 class="section-title">2) Ihr Einsparpotenzial</h2>
       <p class="section-copy">Die Ergebnisse werden direkt aus der Excel-Logik berechnet und in Tsd. bzw. Mio. EUR verdichtet.</p>
       <div class="summary-grid">
         <div class="kpi">
           <div class="label">Kurzfristig pro Jahr</div>
           <div class="value" id="shortAnnual">56.003 EUR</div>
           <div class="sub" id="shortFiveYears">280.016 EUR über 5 Jahre</div>
         </div>
         <div class="kpi">
           <div class="label">Langfristig pro Jahr</div>
           <div class="value" id="longAnnual">246.330 EUR</div>
           <div class="sub" id="longFiveYears">1.231.648 EUR über 5 Jahre</div>
         </div>
         <div class="kpi">
           <div class="label">Rechnungen je Lieferant</div>
           <div class="value" id="invoiceSupplierRatio">46,7</div>
           <div class="sub" id="factorText">Multiplikator: 1,10</div>
         </div>
       </div>
       <div class="band ok-band" id="ratioBand">Hohe Rechnungsdichte je Lieferant erhöht das modellierte Potenzial leicht.</div>
       <div class="summary-text" id="summaryText"></div>
     </section>

     <section class="card table-card">
       <div class="table-header">
         <h2 class="section-title">3) Breakdown nach Kostenblöcken</h2>
         <p class="section-copy">Die Tabelle zeigt Kostenbasis, Einsparquote und Einsparpotenzial pro Block für kurz- und langfristige Perspektive.</p>
       </div>
       <div class="table-scroll" style="max-height: 500px; border-top: 1px solid var(--line);">
         <table aria-label="Einsparpotenzial nach Kostenblöcken">
           <thead>
             <tr>
               <th>Kostenblock</th>
               <th>Kurzfr. Kostenbasis</th>
               <th>Kurzfr. Potenzial</th>
               <th>Langfr. Kostenbasis</th>
               <th>Langfr. Potenzial</th>
             </tr>
           </thead>
           <tbody id="resultRows"></tbody>
         </table>
       </div>
     </section>

     <section class="card lead-form">
       <h2 class="section-title">4) Ergebnis per E-Mail anfordern</h2>
       <p class="section-copy">Erhalten Sie Ihre detaillierte Potenzialanalyse und Kostenübersicht direkt per E-Mail.</p>
       <form id="leadForm">
         <div class="form-grid">
           <div>
             <div class="label-row"><label for="leadName">Name</label></div>
             <div class="num-wrap"><input id="leadName" placeholder="Max Mustermann" required="" type="text" /></div>
           </div>
           <div>
             <div class="label-row"><label for="leadEmail">E-Mail</label></div>
             <div class="num-wrap"><input id="leadEmail" placeholder="max.mustermann@unternehmen.de" required="" type="email" /></div>
           </div>
           <div>
             <div class="label-row"><label for="leadCompany">Unternehmen</label></div>
             <div class="num-wrap"><input id="leadCompany" placeholder="Beispiel GmbH" type="text" /></div>
           </div>
           <div>
             <div class="label-row"><label for="leadRole">Funktion</label></div>
             <div class="num-wrap"><input id="leadRole" placeholder="CFO / Procurement / Operations" type="text" /></div>
           </div>
           <div class="full">
             <div class="label-row"><label for="leadNote">Optionale Notiz</label></div>
             <div class="num-wrap"><input id="leadNote" placeholder="z. B. gewünschter Rückruf oder interessierende Kategorie" type="text" /></div>
           </div>
         </div>
         <label class="checkbox">
           <input id="consent" required="" type="checkbox" />
           <span>Ich möchte mein Ergebnis per E-Mail erhalten und stimme der Verarbeitung meiner Angaben zur Bearbeitung meiner Anfrage zu.</span>
         </label>
         <button class="primary-btn" type="submit">Ergebnis anfordern</button>
         <div class="status-box" id="formStatus"></div>
       </form>
     </section>
   </div>
 </section>
</div>

<script>
 const DEFAULT_MODEL = [
   { name: 'Wareneinsatz / Material / Direct Spend (COGS)', share: 0.2, shortReducible: 0.05, longReducible: 0.3, shortSavingRate: 0.08, longSavingRate: 0.12 },
   { name: 'Personalkosten', share: 0.35, shortReducible: 0.0, longReducible: 0.08, shortSavingRate: 0.0, longSavingRate: 0.15 },
   { name: 'Fremdleistungen operativ (Subunternehmer, externe Bearbeitung, ausgelagerte Leistung)', share: 0.03, shortReducible: 0.1, longReducible: 0.25, shortSavingRate: 0.1, longSavingRate: 0.12 },
   { name: 'Sales & Marketing (Werbung, Vertriebskosten, Provisionen, Agenturen)', share: 0.03, shortReducible: 0.25, longReducible: 0.4, shortSavingRate: 0.15, longSavingRate: 0.18 },
   { name: 'Raumkosten & Facilities (Miete/Pacht, Betriebskosten, Reinigung, Sicherheit)', share: 0.09, shortReducible: 0.05, longReducible: 0.2, shortSavingRate: 0.08, longSavingRate: 0.15 },
   { name: 'Logistik, Fuhrpark & Reisen', share: 0.02, shortReducible: 0.1, longReducible: 0.25, shortSavingRate: 0.1, longSavingRate: 0.12 },
   { name: 'IT & Telekom (Software/Cloud/IT-Services)', share: 0.03, shortReducible: 0.15, longReducible: 0.35, shortSavingRate: 0.15, longSavingRate: 0.2 },
   { name: 'Beratung & Professional Services (Rechts-/Steuer- /Unternehmensberatung, Recruiting, Freelancer)', share: 0.05, shortReducible: 0.25, longReducible: 0.5, shortSavingRate: 0.2, longSavingRate: 0.22 },
   { name: 'Energie & Entsorgung', share: 0.1, shortReducible: 0.15, longReducible: 0.4, shortSavingRate: 0.12, longSavingRate: 0.2 },
   { name: 'Instandhaltung & Reparaturen', share: 0.01, shortReducible: 0.05, longReducible: 0.25, shortSavingRate: 0.05, longSavingRate: 0.1 },
   { name: 'Versicherungen, Beiträge, Gebühren', share: 0.01, shortReducible: 0.1, longReducible: 0.35, shortSavingRate: 0.07, longSavingRate: 0.08 },
   { name: 'Finanzierungskosten', share: 0.04, shortReducible: 0.05, longReducible: 0.25, shortSavingRate: 0.05, longSavingRate: 0.1 },
   { name: 'Abschreibungen und Kosten für Anlagegüter', share: 0.04, shortReducible: 0.0, longReducible: 0.05, shortSavingRate: 0.0, longSavingRate: 0.05 },
 ];
const CALCULATOR_CONFIG = {
 calculatorName: 'SAVE Quick Savings Estimator',
 flowEndpoint: 'https://cloud.activepieces.com/api/v1/webhooks/5IKPbZcDN6iUNEvP2HlD2',
 emailType: 'SAVE_RESULT_V1',
 attachmentName: 'SAVE_Ergebnisuebersicht.pdf',
 source: 'novemcore-webflow-embed',
 version: 'v1.0.0'
};
 let model = JSON.parse(JSON.stringify(DEFAULT_MODEL));
 const els = { revenue: document.getElementById('revenue'), margin: document.getElementById('margin'), marginDisplay: document.getElementById('marginDisplay'), marginLabel: document.getElementById('marginLabel'), invoiceCount: document.getElementById('invoiceCount'), supplierCount: document.getElementById('supplierCount'), shortAnnual: document.getElementById('shortAnnual'), shortFiveYears: document.getElementById('shortFiveYears'), longAnnual: document.getElementById('longAnnual'), longFiveYears: document.getElementById('longFiveYears'), invoiceSupplierRatio: document.getElementById('invoiceSupplierRatio'), factorText: document.getElementById('factorText'), summaryText: document.getElementById('summaryText'), resultRows: document.getElementById('resultRows'), assumptionTableBody: document.getElementById('assumptionTableBody'), shareStatus: document.getElementById('shareStatus'), ratioBand: document.getElementById('ratioBand'), advancedPanel: document.getElementById('advancedPanel'), toggleAdvanced: document.getElementById('toggleAdvanced'), toggleIcon: document.getElementById('toggleIcon'), recalculateBtn: document.getElementById('recalculateBtn'), resetBtn: document.getElementById('resetBtn'), leadForm: document.getElementById('leadForm'), formStatus: document.getElementById('formStatus') };
 const state = { lastResult: null };
 
 function formatEUR(value, compact = false) {
   if (!isFinite(value)) return '-';
   if (compact) {
     return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR', notation: 'compact', maximumFractionDigits: 1 }).format(value);
   }
   return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR', maximumFractionDigits: 0 }).format(value);
 }
 
 function formatPercent(value, digits = 1) {
   return new Intl.NumberFormat('de-DE', { style: 'percent', minimumFractionDigits: digits, maximumFractionDigits: digits }).format(value);
 }
 
 function formatNumber(value, digits = 1) {
   return new Intl.NumberFormat('de-DE', { minimumFractionDigits: digits, maximumFractionDigits: digits }).format(value);
 }
 
 function escapeHtml(str) {
   return String(str).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&#039;');
 }
 
 function getInputs() {
   const revenue = Math.max(0, Number(els.revenue.value || 0));
   const marginPct = Number(els.marginDisplay.value || els.margin.value || 0);
   const margin = Math.min(1, Math.max(0, marginPct / 100));
   const invoiceCount = Math.max(0, Number(els.invoiceCount.value || 0));
   const supplierCount = Math.max(1, Number(els.supplierCount.value || 1));
   return { revenue, margin, invoiceCount, supplierCount };
 }
 
 function getAdjustmentFactor(invoiceCount, supplierCount) {
   const ratio = supplierCount > 0 ? invoiceCount / supplierCount : 0;
   if (ratio < 3) return { ratio, factor: 0.9, label: 'Niedrige Rechnungsdichte je Lieferant reduziert das modellierte Potenzial leicht.' };
   if (ratio > 8) return { ratio, factor: 1.1, label: 'Hohe Rechnungsdichte je Lieferant erhöht das modellierte Potenzial leicht.' };
   return { ratio, factor: 1.0, label: 'Mittlere Rechnungsdichte je Lieferant wirkt neutral im Modell.' };
 }
 
 function calculate() {
   const inputs = getInputs();
   const operatingCostBase = inputs.revenue * (1 - inputs.margin);
   const adjustment = getAdjustmentFactor(inputs.invoiceCount, inputs.supplierCount);
   const breakdown = model.map((row) => {
     const shortUsedShare = row.share * row.shortReducible;
     const longUsedShare = row.share * row.longReducible;
     const shortBase = shortUsedShare * operatingCostBase;
     const longBase = longUsedShare * operatingCostBase;
     const shortPotential = row.shortSavingRate * shortBase * adjustment.factor;
     const longPotential = row.longSavingRate * longBase * adjustment.factor;
     return { name: row.name, share: row.share, shortReducible: row.shortReducible, shortSavingRate: row.shortSavingRate, shortBase, shortPotential, longReducible: row.longReducible, longSavingRate: row.longSavingRate, longBase, longPotential };
   });
   const totalShort = breakdown.reduce((sum, row) => sum + row.shortPotential, 0);
   const totalLong = breakdown.reduce((sum, row) => sum + row.longPotential, 0);
   const result = { inputs, adjustment, operatingCostBase, totalShort, totalLong, totalShortFiveYears: totalShort * 5, totalLongFiveYears: totalLong * 5, breakdown, modelMeta: { shortAverageSavingRate: breakdown.reduce((s, r) => s + r.shortSavingRate, 0) / breakdown.length, longAverageSavingRate: breakdown.reduce((s, r) => s + r.longSavingRate, 0) / breakdown.length, totalCostShare: model.reduce((s, r) => s + r.share, 0) } };
   state.lastResult = result;
   renderResult(result);
   return result;
 }
 
 function renderResult(result) {
   els.shortAnnual.textContent = formatEUR(result.totalShort);
   els.shortFiveYears.textContent = `${formatEUR(result.totalShortFiveYears)} über 5 Jahre`;
   els.longAnnual.textContent = formatEUR(result.totalLong);
   els.longFiveYears.textContent = `${formatEUR(result.totalLongFiveYears)} über 5 Jahre`;
   els.invoiceSupplierRatio.textContent = formatNumber(result.adjustment.ratio, 1);
   els.factorText.textContent = `Multiplikator: ${formatNumber(result.adjustment.factor, 2)}`;
   els.summaryText.textContent = `Kurzfristig lassen sich mit SAVE und gezielten Maßnahmen ca. ${formatNumber(result.totalShort / 1000, 0)} Tsd. EUR pro Jahr einsparen. ` + `Dies entspricht über fünf Jahre rund ${formatNumber((result.totalShort / 1000) * 5, 0)} Tsd. EUR.\n\n` + `Langfristig besteht durch weitere Optimierung, Automatisierung und strukturelle Maßnahmen ein Potenzial von ca. ` + `${formatNumber(result.totalLong / 1000000, 2)} Mio. EUR pro Jahr bzw. ${formatNumber((result.totalLong / 1000000) * 5, 2)} Mio. EUR über fünf Jahre.`;
   const ratioClass = result.adjustment.factor < 1 ? 'band' : result.adjustment.factor > 1 ? 'band ok-band' : 'band';
   els.ratioBand.className = ratioClass;
   els.ratioBand.textContent = result.adjustment.label;
   els.resultRows.innerHTML = result.breakdown.map((row) => ` <tr><td><strong>${escapeHtml(row.name)}</strong><div class="muted">Kostenanteil: ${formatPercent(row.share, 1)}</div></td><td>${formatEUR(row.shortBase)}</td><td><strong>${formatEUR(row.shortPotential)}</strong><div class="muted">${formatPercent(row.shortSavingRate, 1)} Einsparquote</div></td><td>${formatEUR(row.longBase)}</td><td><strong>${formatEUR(row.longPotential)}</strong><div class="muted">${formatPercent(row.longSavingRate, 1)} Einsparquote</div></td></tr> `).join('') + ` <tr><td><strong>Summe</strong></td><td>${formatEUR(result.breakdown.reduce((s, r) => s + r.shortBase, 0))}</td><td><strong>${formatEUR(result.totalShort)}</strong></td><td>${formatEUR(result.breakdown.reduce((s, r) => s + r.longBase, 0))}</td><td><strong>${formatEUR(result.totalLong)}</strong></td></tr> `;
   const shareTotal = result.modelMeta.totalCostShare;
   if (Math.abs(shareTotal - 1) < 0.00001) {
     els.shareStatus.className = 'band ok-band';
     els.shareStatus.textContent = `Summe Kostenanteile = ${formatPercent(shareTotal, 1)}`;
   } else {
     els.shareStatus.className = 'band danger-band';
     els.shareStatus.textContent = `Achtung: Summe Kostenanteile = ${formatPercent(shareTotal, 1)} statt 100,0 %`;
   }
 }
 
 function renderAssumptions() {
   els.assumptionTableBody.innerHTML = model.map((row, index) => ` <tr><td class="name-col">${escapeHtml(row.name)}</td><td><input data-index="${index}" data-field="share" type="number" min="0" max="1" step="0.01" value="${row.share}" /></td><td><input data-index="${index}" data-field="shortReducible" type="number" min="0" max="1" step="0.01" value="${row.shortReducible}" /></td><td><input data-index="${index}" data-field="shortSavingRate" type="number" min="0" max="1" step="0.01" value="${row.shortSavingRate}" /></td><td><input data-index="${index}" data-field="longReducible" type="number" min="0" max="1" step="0.01" value="${row.longReducible}" /></td><td><input data-index="${index}" data-field="longSavingRate" type="number" min="0" max="1" step="0.01" value="${row.longSavingRate}" /></td></tr> `).join('');
 }
 
 function syncMarginFromRange() {
   els.marginDisplay.value = Number(els.margin.value).toFixed(1).replace(/\.0$/, '');
   els.marginLabel.textContent = `${formatNumber(Number(els.margin.value), 1)} %`;
   calculate();
 }
 
 function syncMarginFromInput() {
   let value = Number(els.marginDisplay.value || 0);
   if (!isFinite(value)) value = 0;
   value = Math.max(0, Math.min(60, value));
   els.marginDisplay.value = value;
   els.margin.value = value;
   els.marginLabel.textContent = `${formatNumber(value, 1)} %`;
   calculate();
 }
 
 function resetCalculator() {
   model = JSON.parse(JSON.stringify(DEFAULT_MODEL));
   els.revenue.value = 8000000;
   els.margin.value = 20;
   els.marginDisplay.value = 20;
   els.invoiceCount.value = 7000;
   els.supplierCount.value = 150;
   renderAssumptions();
   syncMarginFromRange();
 }
 
 function updateModelFromTable(event) {
   const target = event.target;
   if (!(target instanceof HTMLInputElement)) return;
   const idx = Number(target.dataset.index);
   const field = target.dataset.field;
   if (!Number.isInteger(idx) || !field || !model[idx]) return;
   let value = Number(target.value);
   if (!isFinite(value)) value = 0;
   value = Math.max(0, value);
   model[idx][field] = value;
   calculate();
 }
 
 function showStatus(message, kind = 'success') {
   els.formStatus.className = `status-box show ${kind === 'success' ? 'status-success' : 'status-error'}`;
   els.formStatus.textContent = message;
 }
 
 async function submitLead(event) {
   event.preventDefault();
   const result = state.lastResult || calculate();
   if (!document.getElementById('consent').checked) {
     showStatus('Bitte bestätigen Sie die Einwilligung, bevor das Ergebnis versendet wird.', 'error');
     return;
   }
   const payload = { calculator_name: CALCULATOR_CONFIG.calculatorName, calculator_version: CALCULATOR_CONFIG.version, source: CALCULATOR_CONFIG.source, submitted_at: new Date().toISOString(), lead: { name: document.getElementById('leadName').value.trim(), email: document.getElementById('leadEmail').value.trim(), company: document.getElementById('leadCompany').value.trim(), role: document.getElementById('leadRole').value.trim(), note: document.getElementById('leadNote').value.trim() }, email_meta: { email_type: CALCULATOR_CONFIG.emailType, attachment_name: CALCULATOR_CONFIG.attachmentName }, calculator_inputs: { revenue_eur: result.inputs.revenue, gross_margin_pct: result.inputs.margin, invoice_count_pa: result.inputs.invoiceCount, supplier_count: result.inputs.supplierCount }, calculator_results: { operating_cost_base_eur: result.operatingCostBase, invoice_supplier_ratio: result.adjustment.ratio, adjustment_factor: result.adjustment.factor, short_term_annual_eur: result.totalShort, short_term_five_year_eur: result.totalShortFiveYears, long_term_annual_eur: result.totalLong, long_term_five_year_eur: result.totalLongFiveYears }, assumptions: model, breakdown: result.breakdown };
   if (!CALCULATOR_CONFIG.flowEndpoint) {
     console.log('Demo payload for Power Automate', payload);
     showStatus('Demo-Modus: Keine Flow-URL hinterlegt. Die fertige Payload wurde in der Browser-Konsole ausgegeben.', 'error');
     return;
   }
   try {
     const response = await fetch(CALCULATOR_CONFIG.flowEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });
     if (!response.ok) {
       throw new Error(`HTTP ${response.status}`);
     }
     showStatus('Vielen Dank. Ihr Ergebnis wurde erfolgreich angefordert.');
     els.leadForm.reset();
   } catch (error) {
     console.error(error);
     showStatus('Der Versand konnte gerade nicht abgeschlossen werden. Bitte prüfen Sie die Flow-URL oder die Schnittstelle.', 'error');
   }
 }
 
 els.margin.addEventListener('input', syncMarginFromRange);
 els.marginDisplay.addEventListener('input', syncMarginFromInput);
 ['revenue', 'invoiceCount', 'supplierCount'].forEach((id) => {
   document.getElementById(id).addEventListener('input', calculate);
 });
 els.assumptionTableBody.addEventListener('input', updateModelFromTable);
 els.recalculateBtn.addEventListener('click', calculate);
 els.resetBtn.addEventListener('click', resetCalculator);
 els.toggleAdvanced.addEventListener('click', () => {
   const isOpen = els.advancedPanel.classList.toggle('open');
   els.toggleIcon.textContent = isOpen ? '–' : '+';
 });
 els.leadForm.addEventListener('submit', submitLead);
 renderAssumptions();
 syncMarginFromRange();
</script>

‍

Wir erklären Ihnen unsere SAVE Software

Jetz Kontaktieren
white arrow up iconwhite arrow up icon
Erfahren Sie zuerst, von Trends, Lösungen und kostenfreien Anlaysen, um Ihr Unternehmen noch effizienter zu machen.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Worum geht es?

Mit diesem Rechner erhalten Sie eine erste indikative Einschätzung, welches Einsparpotenzial in Ihren indirekten Kosten und Eingangsrechnungen liegen kann. Die Berechnung basiert auf wenigen strukturellen Kennzahlen und typischen Erfahrungswerten aus vergleichbaren Unternehmen.

Die Eingabe dauert 2 Minuten.

Was Sie erhalten

  • Eine indikative jährliche Einsparschätzung
  • Eine indikative einschätzung des mittelfristigen Einsparpotenzials per E-Mail
  • Eine Einordnung nach typischen Kostenblöcken per E-Mail
  • Eine strukturierte Ergebnis-Zusammenfassung per E-Mail
  • Eine erste Priorisierung möglicher Hebel per E-Mail

Die Ergebnisse dienen als Orientierung basierend auf unsereren Projekterfahrungen.

Wie wir rechnen

Die Schätzung basiert auf Benchmarks, typischen Kostenstrukturen sowie realisierten Projekten im Bereich indirekter Kosten. Dabei berücksichtigen wir unter anderem wiederkehrende Muster wie Preisabweichungen, stille Preiserhöhungen, Dubletten, Lieferantenstreuung und strukturelle Ineffizienzen.

Die Berechnung ist bewusst indikativ. Das tatsächliche Einsparpotenzial hängt von Ihrem konkreten Kostenmix sowie der Datenqualität ab. Unsere Software SAVE ist genau hierfür gemacht: Ihr Einsparpotenzial idenfizieren und heben.

Der nächste Schritt

Wir zeigen Ihnen in einem kurzen Austausch, wie eine Detailanalyse mit unserer Software SAVE auf Basis echter Rechnungs- und Positionsdaten aussieht – und wie daraus ein belastbarer Business Case entsteht.

Das könnte Sie interessieren:

No items found.

In schnellen Schritten konkrete Ergebnisse

No items found.
Jetzt kontaktieren
white arrow up iconwhite arrow up icon
Mehr Services

Unsere neusten Insights

No items found.
Mehr Insights
SAVE Einsparrechner
Erhalten Sie eine erste Einsparschätzung des Einsparpotenzials für Ihr Unternehmen, welches Sie durch unserer SAVE Software realisieren.
Ihr Einsparpotenzial
Termin vereinbarenMehr erfahren