/*   BREAK-EVEN AUDITOR & ANALYZER */ const GEMINI_API_KEY = PropertiesService.getScriptProperties().getProperty(‘GEMINI_API_KEY’); const SHEET_NAME = ‘Break-Even Analysis’; if (!GEMINI_API_KEY) {   throw new Error(‘GEMINI_API_KEY is missing! Add it in Project properties > Script properties.’); } function doGet() {   return HtmlService.createHtmlOutput(`                                                  
         

📊 Break-Even Calculator Pro

                   
           
           
           
           
           
           
           
           
           
         
                   
         
         
       
                    `).setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL); } function saveAndAnalyze(data) {   try {     if (!data || typeof data !== ‘object’) {       return { success: false, error: ‘No valid data received’ };     }     const fixed = Number(data.fixed) || 0;     const varCost = Number(data.varCost) || 0;     const price = Number(data.price) || 0;     const target = Number(data.target) || 0;     const weeklySales = Number(data.weeklySales) || 0;     const growthRate = Number(data.growthRate) || 0;     const cashOnHand = Number(data.cashOnHand) || 0;     const personalDraw = Number(data.personalDraw) || 0;     const planWeeks = Number(data.planWeeks) || 12;     const contrib = price – varCost;     if (contrib <= 0) return { success: false, error: 'Price must be > Variable Cost’ };         const contribPct = (contrib / price) * 100;     const beUnits = Math.ceil(fixed / contrib);     const beRevenue = beUnits * price;     const targetUnits = Math.ceil((fixed + target) / contrib);     const projProfit = (weeklySales * contrib) – fixed;     let safetyMargin = 0;     if (weeklySales > 0) {       safetyMargin = ((weeklySales – beUnits) / weeklySales) * 100;     }     let endingCash = cashOnHand;     let currentSales = weeklySales;     const weeklyDraw = personalDraw / 4.33;     for (let i = 1; i <= planWeeks; i++) {       endingCash += (currentSales * contrib) - fixed - weeklyDraw;       currentSales *= (1 + growthRate / 100);     }     function formatCurrency(value) { return '$' + Math.round(value).toLocaleString(); }     const prompt = `Analyze this business model in under 600 words:     METRICS:     - Fixed: ${formatCurrency(fixed)}/wk | Variable: ${formatCurrency(varCost)}/unit | Price: ${formatCurrency(price)}/unit     - Break-even: ${beUnits} units/wk (${formatCurrency(beRevenue)}/wk)     - Current sales: ${weeklySales} units/wk | Growth: ${growthRate}%/wk | Profit: ${formatCurrency(projProfit)}/wk     - Safety margin: ${safetyMargin.toFixed(1)}% | Cash: ${formatCurrency(cashOnHand)} → ${formatCurrency(endingCash)} (${planWeeks} weeks)     - Personal draw: ${formatCurrency(personalDraw)}/mo     PROVIDE:     1. VIABILITY: One sentence assessment     2. TOP RISK: What could break this business + impact     3. SENSITIVITY: New break-even if costs +15% or sales -20% (give exact units)     4. CASH: When does cash turn negative? Recommended reserve?     5. ACTION: One thing to do THIS WEEK with expected $ impact     Be quantitative. Use bullets.`;     // FIXED MODEL NAME - This resolves the 404 error     const model = 'gemini-2.5-flash';     const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${GEMINI_API_KEY}`;         const payload = {       contents: [{ parts: [{ text: prompt }] }],       generationConfig: { temperature: 0.4 }     };     const response = UrlFetchApp.fetch(url, {       method: 'post',       contentType: 'application/json',       payload: JSON.stringify(payload),       muteHttpExceptions: true     });     const responseCode = response.getResponseCode();     if (responseCode !== 200) {       return { success: false, error: `Gemini API error ${responseCode}` };     }     const json = JSON.parse(response.getContentText());     let analysisText = 'AI Unavailable';         if (json.candidates && json.candidates.length > 0) {       if (json.candidates[0].content && json.candidates[0].content.parts) {          analysisText = json.candidates[0].content.parts[0].text;       }     }     const ss = SpreadsheetApp.getActiveSpreadsheet();     let sheet = ss.getSheetByName(SHEET_NAME);         if (!sheet) {       sheet = ss.insertSheet(SHEET_NAME);       const headers = [         ‘Timestamp’, ‘Fixed Costs’, ‘Var Cost’, ‘Price’, ‘Target Profit’,         ‘BE Units’, ‘Target Units’, ‘Contrib %’, ‘Weekly Sales’, ‘Growth %’,         ‘Safety %’, ‘Proj Profit’, ‘Starting Cash’, ‘Ending Cash’, ‘Personal Draw’, ‘AI Analysis’       ];       sheet.appendRow(headers);       sheet.setFrozenRows(1);       sheet.getRange(1, 1, 1, headers.length).setFontWeight(‘bold’)            .setBackground(‘#667eea’).setFontColor(‘#ffffff’).setHorizontalAlignment(‘center’);     }     sheet.appendRow([       new Date(), fixed, varCost, price, target, beUnits, targetUnits,       contribPct.toFixed(2) + ‘%’, weeklySales, growthRate + ‘%’,       safetyMargin.toFixed(2) + ‘%’, projProfit, cashOnHand, endingCash,       personalDraw, analysisText     ]);     const lastRow = sheet.getLastRow();     sheet.getRange(lastRow, 2, 1, 1).setNumberFormat(‘$#,##0’);     sheet.getRange(lastRow, 3, 1, 1).setNumberFormat(‘$#,##0.00’);     sheet.getRange(lastRow, 4, 1, 1).setNumberFormat(‘$#,##0.00’);     sheet.getRange(lastRow, 12, 1, 3).setNumberFormat(‘$#,##0’);     sheet.autoResizeColumns(1, 16);     return {       success: true,       analysis: analysisText,       message: SHEET_NAME + ‘ (Row ‘ + lastRow + ‘)’,       metrics: { beUnits: beUnits, beRevenue: formatCurrency(beRevenue), projProfit: formatCurrency(projProfit), safetyMargin: safetyMargin.toFixed(1) }     };   } catch (error) {     return { success: false, error: ‘Server error: ‘ + error.toString() };   } }