QR Menu Pro
QR Menu Pro Sheets Edition

Меню
нового
поколения

БД в Google Таблицах. QR на стол. Заказ без приложений.

Нужно для работы
Google аккаунт
Google Таблица (создадим)
Apps Script (настроим за 2 мин)
Блюд
24/7
Live
QR
Заказы

Шаг 1 из 3

Создайте Google Таблицу и Apps Script

Создать Google Таблицу

В таблице создайте 3 листа:

1 Лист: menu — для блюд
2 Лист: orders — для заказов
3 Лист: settings — для настроек

Откройте Apps Script (Расширения → Apps Script) и вставьте этот код:

const SS_ID = SpreadsheetApp.getActiveSpreadsheet().getId();
function doGet(e){return handle(e);}
function doPost(e){return handle(e);}
function handle(e){
 const p=e.parameter,b=e.postData?JSON.parse(e.postData.contents||'{}'):{};
 const act=p.action||b.action;
 const ss=SpreadsheetApp.openById(SS_ID);
 let res={};
 try{
  if(act==='getMenu'){res=getMenu(ss);}
  else if(act==='saveMenu'){res=saveMenuItem(ss,b);}
  else if(act==='deleteMenu'){res=deleteMenuItem(ss,b.id);}
  else if(act==='getOrders'){res=getOrders(ss,p.rid);}
  else if(act==='addOrder'){res=addOrder(ss,b);}
  else if(act==='updateOrder'){res=updateOrder(ss,b);}
  else if(act==='getSettings'){res=getSettings(ss);}
  else if(act==='saveSettings'){res=saveSettings(ss,b);}
 }catch(err){res={error:err.toString()};}
 return ContentService.createTextOutput(JSON.stringify(res)).setMimeType(ContentService.MimeType.JSON);
}
function getMenu(ss){
 const sh=ss.getSheetByName('menu');
 const rows=sh.getDataRange().getValues();
 if(rows.length<2)return{items:[]};
 const hdr=rows[0];const items=rows.slice(1).map(r=>{
  const o={};hdr.forEach((h,i)=>o[h]=r[i]);return o;
 }).filter(r=>r.id);
 return{items};
}
function saveMenuItem(ss,d){
 const sh=ss.getSheetByName('menu');
 let rows=sh.getDataRange().getValues();
 if(rows.length===0){sh.appendRow(['id','name','category','price','description','imageUrl','available','restaurantId','images']);rows=sh.getDataRange().getValues();}
 const hdr=rows[0];const hdrs=['id','name','category','price','description','imageUrl','available','restaurantId','images'];
 if(rows.length===1){sh.appendRow(hdrs.map(h=>d[h]??''));return{ok:true};}
 const idx=rows.findIndex((r,i)=>i>0&&r[hdr.indexOf('id')]===d.id);
 if(idx>0){sh.getRange(idx+1,1,1,hdr.length).setValues([hdr.map(h=>d[h]??'')]);}
 else{sh.appendRow(hdr.map(h=>d[h]??''));}
 return{ok:true};
}
function deleteMenuItem(ss,id){
 const sh=ss.getSheetByName('menu');
 const rows=sh.getDataRange().getValues();
 const hdr=rows[0];const col=hdr.indexOf('id');
 for(let i=rows.length-1;i>0;i--){if(rows[i][col]===id)sh.deleteRow(i+1);}
 return{ok:true};
}
function getOrders(ss,rid){
 const sh=ss.getSheetByName('orders');
 const rows=sh.getDataRange().getValues();
 if(rows.length<2)return{orders:[]};
 const hdr=rows[0];const orders=rows.slice(1).map(r=>{
  const o={};hdr.forEach((h,i)=>{try{o[h]=typeof r[i]==='string'&&r[i].startsWith('[')?JSON.parse(r[i]):r[i];}catch{o[h]=r[i];}});return o;
 }).filter(r=>r.id&&(!rid||r.restaurantId===rid));
 return{orders};
}
function addOrder(ss,d){
 const sh=ss.getSheetByName('orders');
 let rows=sh.getDataRange().getValues();
 const hdr=['id','restaurantId','tableNumber','items','total','status','timestamp'];
 if(rows.length===0){sh.appendRow(hdr);}
 sh.appendRow(hdr.map(h=>h==='items'?JSON.stringify(d[h]):d[h]??''));
 return{ok:true};
}
function updateOrder(ss,d){
 const sh=ss.getSheetByName('orders');
 const rows=sh.getDataRange().getValues();
 const hdr=rows[0];const col=hdr.indexOf('id');
 const idx=rows.findIndex((r,i)=>i>0&&r[col]===d.id);
 if(idx>0){const statusCol=hdr.indexOf('status');sh.getRange(idx+1,statusCol+1).setValue(d.status);}
 return{ok:true};
}
function getSettings(ss){
 const sh=ss.getSheetByName('settings');
 const rows=sh.getDataRange().getValues();
 const s={};rows.forEach(r=>{if(r[0])s[r[0]]=r[1];});return{settings:s};
}
function saveSettings(ss,d){
 const sh=ss.getSheetByName('settings');
 sh.clearContents();
 Object.entries(d.settings).forEach(([k,v])=>sh.appendRow([k,v]));
 return{ok:true};
}

Шаг 2 из 3

Разверните веб-приложение

В редакторе Apps Script:

1.Нажмите «Развернуть»«Новое развертывание»
2.Тип: Веб-приложение
3.Доступ: Все
4.Нажмите «Развернуть» и скопируйте URL

Шаг 3 из 3

Последний шаг — название заведения

Ресторан

Заказы

Авто-обновление каждые 15 сек

LIVE

Меню

Импорт меню

Загрузите CSV, JSON или вставьте данные

Перетащите CSV или нажмите

Колонки: name, category, price, description, imageUrl

Пример CSV

name,category,price,description
Борщ,Супы,1200,Традиционный со сметаной
Пицца Маргарита,Пиццы,2500,Томат + моцарелла
Кола,Напитки,500,330 мл

Статистика

Заказов сегодня
0
Выручка сегодня
0 ₸
Средний чек
0 ₸
Позиций в меню
0

Топ блюд

QR и Настройки

Ваш QR-код

QR
Ссылка на меню

Настройки заведения

Звук новых заказов
Уведомление при поступлении

Сервисный сбор

Показывается гостю при открытии меню перед просмотром блюд.

Включить сбор

Google Sheets

Опасная зона

Информация

Продолжая, вы принимаете условия обслуживания

Название

Заказ принят!

Повар уже видит ваш заказ. Ожидайте!