🌸 Bloom De Luxe

Введи PIN-код для входу

🌸 Bloom De Luxe

Налаштуйте підключення до Google Sheets

Виручка
Прибуток
Продажів
Реклама
Канали
Останні продажі
🌸

Ще немає продажів.
Додай перший!

📈 Бізнес-аналітика

Реклама та контент не впливають на валову маржу. Вони враховуються лише у чистому прибутку.

Загальна виручка
Валовий прибуток
Витрати на рекламу
Витрати на контент
Чистий прибуток
Валова маржа
Кількість продажів
Середній чек

Продажі за каналами

Топ-5 букетів за прибутком

Швидка оцінка

Новий продаж

Фінанси

Ціна продажу
+ Чайові
± Доставка
− Квіти + Упакування
Прибуток

Клієнт

Додати контент-букет

Витрати

Загальна вартість

Додатково

Останні записи
📸

Ще немає контент-витрат.

Додати витрати на рекламу

Останні витрати
📣

Ще немає записів реклами.

Підключення до Google Sheets
1

Відкрий свій Google Sheets трекер

Той файл BloomDeLuxe_Tracker.xlsx який завантажив раніше — імпортуй його в Google Drive і відкрий як Google Sheets.

2

Відкрий Apps Script

В Google Sheets: Extensions → Apps Script

3

Встав скрипт

Видали весь код і встав цей (скопіюй кнопкою нижче):

function doGet(e) { try { var p = e.parameter || {}; var ss = SpreadsheetApp.getActiveSpreadsheet(); if (p.type === 'sale') { var sheet = ss.getSheetByName('📦 Продажі'); if (!sheet.getRange(2, 18).getValue()) { sheet.getRange(2, 18).setValue('Оплата карткою (AUD)'); sheet.getRange(2, 18).setBackground('#1A1A2E'); sheet.getRange(2, 18).setFontColor('#FFFFFF'); sheet.getRange(2, 18).setFontWeight('bold'); sheet.getRange(2, 19).setValue('Оплата кешем (AUD)'); sheet.getRange(2, 19).setBackground('#1A1A2E'); sheet.getRange(2, 19).setFontColor('#FFFFFF'); sheet.getRange(2, 19).setFontWeight('bold'); sheet.getRange(2, 18, 1, 2).setHorizontalAlignment('center'); sheet.getRange(2, 18, 1, 2).setVerticalAlignment('middle'); sheet.getRange(2, 18, 1, 2).setWrap(true); sheet.setColumnWidth(18, 130); sheet.setColumnWidth(19, 130); } var nextRow = -1; for (var i = 3; i <= 102; i++) { if (!sheet.getRange(i, 3).getValue()) { nextRow = i; break; } } if (nextRow === -1) nextRow = sheet.getLastRow() + 1; sheet.getRange(nextRow, 1, 1, 19).setValues([[ nextRow - 2, p.date, p.name, p.composition, p.channel, Number(p.flowers) || 0, Number(p.packaging) || 0, Number(p.price) || 0, Number(p.delivery) || 0, Number(p.tips) || 0, Number(p.revenue) || 0, Number(p.profit) || 0, '', p.clientName || '', p.phone || '', p.email || '', p.notes || '', Number(p.paymentCard) || 0, Number(p.paymentCash) || 0 ]]); sheet.getRange(nextRow, 13).setFormula('=IFERROR(L' + nextRow + '/H' + nextRow + ',"")'); sheet.getRange(nextRow, 13).setNumberFormat('0.0%'); } if (p.type === 'ad') { var sheet = ss.getSheetByName('📣 Реклама'); var nextRow = -1; for (var i = 3; i <= 52; i++) { if (!sheet.getRange(i, 2).getValue()) { nextRow = i; break; } } if (nextRow === -1) nextRow = sheet.getLastRow() + 1; sheet.getRange(nextRow, 1, 1, 5).setValues([[ p.date || '', p.platform || '', p.adType || '', Number(p.amount) || 0, p.notes || '' ]]); } if (p.type === 'content') { var sheet = ss.getSheetByName('📸 Контент'); if (!sheet) { sheet = ss.insertSheet('📸 Контент'); var headers = [ '№', 'Дата', 'Назва букету', 'Тип контенту', 'Квіти (AUD)', 'Упакування (AUD)', 'Інші витрати (AUD)', 'Загальна вартість (AUD)', 'Статус', 'Посилання', 'Нотатки' ]; sheet.getRange(2, 1, 1, headers.length).setValues([headers]); sheet.getRange(2, 1, 1, headers.length) .setBackground('#1A1A2E') .setFontColor('#FFFFFF') .setFontWeight('bold') .setHorizontalAlignment('center') .setVerticalAlignment('middle') .setWrap(true); sheet.setFrozenRows(2); sheet.setColumnWidth(1, 55); sheet.setColumnWidth(2, 105); sheet.setColumnWidth(3, 190); sheet.setColumnWidth(4, 140); sheet.setColumnWidth(5, 115); sheet.setColumnWidth(6, 125); sheet.setColumnWidth(7, 125); sheet.setColumnWidth(8, 145); sheet.setColumnWidth(9, 130); sheet.setColumnWidth(10, 220); sheet.setColumnWidth(11, 260); } var nextRow = -1; for (var i = 3; i <= 102; i++) { if (!sheet.getRange(i, 3).getValue()) { nextRow = i; break; } } if (nextRow === -1) nextRow = sheet.getLastRow() + 1; sheet.getRange(nextRow, 1, 1, 11).setValues([[ nextRow - 2, p.date || '', p.name || '', p.contentType || '', Number(p.flowers) || 0, Number(p.packaging) || 0, Number(p.other) || 0, Number(p.total) || 0, p.status || '', p.link || '', p.notes || '' ]]); sheet.getRange(nextRow, 5, 1, 4).setNumberFormat('$0.00'); } // Create or refresh the read-only analytics output after any request. rebuildAnalyticsSheet_(ss); return ContentService .createTextOutput(JSON.stringify({status:'ok'})) .setMimeType(ContentService.MimeType.JSON); } catch(err) { return ContentService .createTextOutput(JSON.stringify({status:'error', msg: err.toString()})) .setMimeType(ContentService.MimeType.JSON); } } function rebuildAnalyticsSheet_(ss) { var name = '📈 Аналітика'; var sheet = ss.getSheetByName(name); if (!sheet) { sheet = ss.insertSheet(name); } // This sheet is generated analytics only. Source sheets are never cleared. sheet.clear(); sheet.getCharts().forEach(function(chart) { sheet.removeChart(chart); }); var dark = '#1A1A2E'; var dark2 = '#24243A'; var gold = '#C9A84C'; var ivory = '#F5F0E8'; var green = '#2D6A4F'; var red = '#C1121F'; var border = '#D8CFC0'; sheet.setHiddenGridlines(true); sheet.setFrozenRows(3); sheet.getRange('A1:N40').setBackground(dark).setFontColor('#FFFFFF'); sheet.getRange('A1:N2').merge() .setValue('🌸 BLOOM DE LUXE — БІЗНЕС-АНАЛІТИКА') .setBackground(dark) .setFontColor(gold) .setFontSize(20) .setFontWeight('bold') .setHorizontalAlignment('center') .setVerticalAlignment('middle'); sheet.getRange('A3:N3').merge() .setValue('Автоматично оновлюється з Продажів, Реклами та Контенту') .setFontColor('#E8D18A') .setFontStyle('italic') .setHorizontalAlignment('center'); var cards = [ ['A4:C4','A5:C6','💰 ЗАГАЛЬНА ВИРУЧКА',"=SUMIF('📦 Продажі'!A3:A1000,\">0\",'📦 Продажі'!K3:K1000)",'$#,##0.00','#1A1A2E'], ['D4:F4','D5:F6','🌸 ВАЛОВИЙ ПРИБУТОК',"=SUMIF('📦 Продажі'!A3:A1000,\">0\",'📦 Продажі'!L3:L1000)",'$#,##0.00',green], ['G4:I4','G5:I6','📣 ВИТРАТИ НА РЕКЛАМУ',"=IFERROR(SUM(FILTER('📣 Реклама'!D3:D1000,ISNUMBER('📣 Реклама'!A3:A1000))),0)",'$#,##0.00',red], ['J4:L4','J5:L6','📸 ВИТРАТИ НА КОНТЕНТ',"=SUMIF('📸 Контент'!A3:A1000,\">0\",'📸 Контент'!H3:H1000)",'$#,##0.00',red], ['A8:C8','A9:C10','💎 ЧИСТИЙ ПРИБУТОК','=D5-G5-J5','$#,##0.00',green], ['D8:F8','D9:F10','📈 ВАЛОВА МАРЖА','=IF(A5=0,"",D5/A5)','0.0%','#1A1A2E'], ['G8:I8','G9:I10','🛍 КІЛЬКІСТЬ ПРОДАЖІВ',"=COUNT('📦 Продажі'!A3:A1000)",'0','#1A1A2E'], ['J8:L8','J9:L10','🧾 СЕРЕДНІЙ ЧЕК','=IF(G9=0,"",A5/G9)','$#,##0.00','#1A1A2E'] ]; cards.forEach(function(c) { sheet.getRange(c[0]).merge() .setValue(c[2]) .setBackground(dark2) .setFontColor(gold) .setFontWeight('bold') .setHorizontalAlignment('center') .setVerticalAlignment('middle') .setBorder(true,true,false,true,false,false,gold,SpreadsheetApp.BorderStyle.SOLID); sheet.getRange(c[1]).merge(); var cell = sheet.getRange(c[1].split(':')[0]); cell.setFormula(c[3]); sheet.getRange(c[1]) .setBackground(ivory) .setFontColor(c[5]) .setFontSize(17) .setFontWeight('bold') .setHorizontalAlignment('center') .setVerticalAlignment('middle') .setNumberFormat(c[4]) .setBorder(false,true,true,true,false,false,gold,SpreadsheetApp.BorderStyle.SOLID); }); sheet.getRange('N4').setValue('Рік').setBackground(dark2).setFontColor(gold).setFontWeight('bold'); sheet.getRange('N5').setValue(new Date().getFullYear()).setBackground(dark2).setFontColor('#FFFFFF').setFontWeight('bold'); sheet.getRange('N4:N5').setHorizontalAlignment('center').setBorder(true,true,true,true,true,true,gold,SpreadsheetApp.BorderStyle.SOLID); sectionHeader_(sheet, 'A12:F12', '📍 ПРОДАЖІ ЗА КАНАЛАМИ', gold, dark); sectionHeader_(sheet, 'H12:N12', '🏆 ТОП-5 БУКЕТІВ ЗА ПРИБУТКОМ', gold, dark); sectionHeader_(sheet, 'A24:F24', '📅 ПОМІСЯЧНА ДИНАМІКА', gold, dark); sectionHeader_(sheet, 'H24:N24', '📊 СТРУКТУРА ВИТРАТ', gold, dark); sheet.getRange('A13:D13').setValues([['Канал','Кількість','Виручка (AUD)','% від виручки']]); tableHeader_(sheet, 'A13:D13', dark2, gold, border); var channels = ['Instagram','Website','Google','Ринок','Рекомендація','Інше','Tik Tok']; sheet.getRange(14,1,channels.length,1).setValues(channels.map(function(x){ return [x]; })); channels.forEach(function(_, idx) { var row = 14 + idx; sheet.getRange(row,2).setFormula("=COUNTIF('📦 Продажі'!E3:E1000,A" + row + ")"); sheet.getRange(row,3).setFormula("=SUMIF('📦 Продажі'!E3:E1000,A" + row + ",'📦 Продажі'!K3:K1000)"); sheet.getRange(row,4).setFormula("=IF($A$5=0,0,C" + row + "/$A$5)"); }); tableBody_(sheet, 'A14:D20', ivory, dark, border); sheet.getRange('C14:C20').setNumberFormat('$#,##0.00'); sheet.getRange('D14:D20').setNumberFormat('0.0%'); sheet.getRange('H13:L13').setValues([['#','Назва букету','Виручка','Прибуток','Маржа']]); tableHeader_(sheet, 'H13:L13', dark2, gold, border); for (var r = 14; r <= 18; r++) { var rank = r - 13; sheet.getRange(r,8).setValue(rank); sheet.getRange(r,11).setFormula("=LARGE(FILTER('📦 Продажі'!L3:L1000,ISNUMBER('📦 Продажі'!A3:A1000)),H" + r + ")"); sheet.getRange(r,9).setFormula("=INDEX('📦 Продажі'!C3:C1000,MATCH(K" + r + ",'📦 Продажі'!L3:L1000,0))"); sheet.getRange(r,10).setFormula("=INDEX('📦 Продажі'!K3:K1000,MATCH(K" + r + ",'📦 Продажі'!L3:L1000,0))"); sheet.getRange(r,12).setFormula("=IF(J" + r + "=0,\"\",K" + r + "/J" + r + ")"); } tableBody_(sheet, 'H14:L18', ivory, dark, border); sheet.getRange('J14:K18').setNumberFormat('$#,##0.00'); sheet.getRange('L14:L18').setNumberFormat('0.0%'); sheet.getRange('A25:F25').setValues([['Місяць','Виручка','Валовий прибуток','Реклама','Контент','Чистий прибуток']]); tableHeader_(sheet, 'A25:F25', dark2, gold, border); var months = ['Січень','Лютий','Березень','Квітень','Травень','Червень','Липень','Серпень','Вересень','Жовтень','Листопад','Грудень']; sheet.getRange(26,1,12,1).setValues(months.map(function(x){ return [x]; })); for (var m = 1; m <= 12; m++) { var row = 25 + m; var nextMonth = m === 12 ? 'DATE($N$5+1,1,1)' : 'DATE($N$5,' + (m + 1) + ',1)'; var startMonth = 'DATE($N$5,' + m + ',1)'; sheet.getRange(row,2).setFormula("=SUMIFS('📦 Продажі'!K3:K1000,'📦 Продажі'!B3:B1000,\">=\"&" + startMonth + ",'📦 Продажі'!B3:B1000,\"<\"&" + nextMonth + ")"); sheet.getRange(row,3).setFormula("=SUMIFS('📦 Продажі'!L3:L1000,'📦 Продажі'!B3:B1000,\">=\"&" + startMonth + ",'📦 Продажі'!B3:B1000,\"<\"&" + nextMonth + ")"); sheet.getRange(row,4).setFormula("=SUMIFS('📣 Реклама'!D3:D1000,'📣 Реклама'!A3:A1000,\">=\"&" + startMonth + ",'📣 Реклама'!A3:A1000,\"<\"&" + nextMonth + ")"); sheet.getRange(row,5).setFormula("=SUMIFS('📸 Контент'!H3:H1000,'📸 Контент'!B3:B1000,\">=\"&" + startMonth + ",'📸 Контент'!B3:B1000,\"<\"&" + nextMonth + ")"); sheet.getRange(row,6).setFormula('=C' + row + '-D' + row + '-E' + row); } tableBody_(sheet, 'A26:F37', ivory, dark, border); sheet.getRange('B26:F37').setNumberFormat('$#,##0.00'); sheet.getRange('H25:J25').setValues([['Категорія','Сума','% від витрат']]); tableHeader_(sheet, 'H25:J25', dark2, gold, border); sheet.getRange('H26:H28').setValues([['Реклама'],['Контент'],['Разом маркетинг']]); sheet.getRange('I26').setFormula('=G5'); sheet.getRange('I27').setFormula('=J5'); sheet.getRange('I28').setFormula('=I26+I27'); sheet.getRange('J26').setFormula('=IF(I28=0,0,I26/I28)'); sheet.getRange('J27').setFormula('=IF(I28=0,0,I27/I28)'); sheet.getRange('J28').setValue(1); tableBody_(sheet, 'H26:J28', ivory, dark, border); sheet.getRange('I26:I28').setNumberFormat('$#,##0.00'); sheet.getRange('J26:J28').setNumberFormat('0.0%'); sheet.getRange('H30:N30').merge().setValue('ШВИДКА ОЦІНКА БІЗНЕСУ') .setBackground(gold).setFontColor(dark).setFontWeight('bold').setHorizontalAlignment('center'); sheet.getRange('H31:N35').merge() .setFormula('="Валова маржа: "&TEXT(D9,"0.0%")&CHAR(10)&"Чистий прибуток: "&TEXT(A9,"$#,##0.00")&CHAR(10)&"Маркетингові витрати: "&TEXT(G5+J5,"$#,##0.00")&CHAR(10)&CHAR(10)&"Реклама та контент не впливають на валову маржу. Вони враховуються у чистому прибутку."') .setBackground(dark2).setFontColor('#E8D18A').setWrap(true).setVerticalAlignment('top'); var widths = [145,105,120,115,115,125,24,55,200,115,115,95,24,75]; widths.forEach(function(width, idx) { sheet.setColumnWidth(idx + 1, width); }); sheet.setRowHeights(5, 2, 28); sheet.setRowHeights(9, 2, 28); var monthlyChart = sheet.newChart() .setChartType(Charts.ChartType.LINE) .addRange(sheet.getRange('A25:F37')) .setPosition(39,1,0,0) .setOption('title','Фінансова динаміка за місяцями') .setOption('legend',{position:'bottom'}) .setOption('backgroundColor',ivory) .build(); sheet.insertChart(monthlyChart); var expenseChart = sheet.newChart() .setChartType(Charts.ChartType.PIE) .addRange(sheet.getRange('H25:I27')) .setPosition(39,8,0,0) .setOption('title','Маркетингові витрати') .setOption('legend',{position:'bottom'}) .setOption('backgroundColor',ivory) .build(); sheet.insertChart(expenseChart); } function sectionHeader_(sheet, range, text, bg, color) { sheet.getRange(range).merge() .setValue(text) .setBackground(bg) .setFontColor(color) .setFontWeight('bold') .setHorizontalAlignment('center'); } function tableHeader_(sheet, range, bg, color, border) { sheet.getRange(range) .setBackground(bg) .setFontColor(color) .setFontWeight('bold') .setHorizontalAlignment('center') .setWrap(true) .setBorder(true,true,true,true,true,true,border,SpreadsheetApp.BorderStyle.SOLID); } function tableBody_(sheet, range, bg, color, border) { sheet.getRange(range) .setBackground(bg) .setFontColor(color) .setBorder(true,true,true,true,true,true,border,SpreadsheetApp.BorderStyle.SOLID); }
4

Deploy → New deployment

Натисни Deploy → New deployment
Type: Web app
Execute as: Me
Who has access: Anyone
Натисни Deploy і скопіюй URL.

5

Встав URL нижче

Шерінг для команди

1. Відкрий Google Sheets
2. Натисни Share (кнопка вгорі праворуч)
3. Додай email людини → обери Editor
4. Поділись також посиланням на цю аппу