// Fictional training recipes and prices. No customer or Solnce catalog data. const suppliers=[ ['fresh','Демо: овощи и молочные продукты'],['protein','Демо: мясо и рыба'], ['bakery','Демо: пекарня'],['grocery','Демо: бакалея'],['pack','Демо: упаковка'] ].map(([key,name])=>({id:`demo-v1-supplier-${key}`,name,active:true,category:'Учебный поставщик',contact:'',phone:'',email:'',address:'',deliveryDays:'По договорённости',minOrder:0,note:'Вымышленный поставщик для знакомства с приложением.'})); // key, product name, purchase unit price, supplier, unit const products=[ ['baguette','Багет',240,'bakery'],['tomato','Томаты',260,'fresh'],['basil','Базилик',1500,'fresh'], ['oil','Масло оливковое',1100,'grocery'],['rye','Хлеб ржаной',220,'bakery'], ['salmon','Лосось слабосолёный',2400,'protein'],['cream','Сыр сливочный',850,'fresh'], ['cucumber','Огурцы',220,'fresh'],['dill','Укроп',700,'fresh'],['toast','Хлеб тостовый',240,'bakery'], ['chicken','Филе курицы готовое',850,'protein'],['lettuce','Салат листовой',700,'fresh'], ['mozzarella','Моцарелла мини',950,'fresh'],['cherry','Томаты черри',450,'fresh'], ['tartlet','Тарталетки готовые',750,'bakery'],['mushroom','Шампиньоны',340,'fresh'], ['cooking-cream','Сливки',500,'fresh'],['gouda','Сыр гауда',900,'fresh'],['onion','Лук репчатый',80,'fresh'], ['tortilla','Тортилья',450,'bakery'],['turkey','Ветчина из индейки',1000,'protein'],['pepper','Перец сладкий',380,'fresh'], ['brie','Сыр бри',1600,'fresh'],['blue','Сыр с голубой плесенью',1700,'fresh'],['grape','Виноград',420,'fresh'], ['walnut','Орех грецкий очищенный',1000,'grocery'],['honey','Мёд',800,'grocery'],['cracker','Крекер',500,'bakery'], ['salami','Салями',1400,'protein'],['beef','Ростбиф готовый',2000,'protein'],['pickle','Корнишоны',400,'grocery'], ['olive','Маслины без косточек',650,'grocery'],['mustard','Горчица',350,'grocery'],['carrot','Морковь',90,'fresh'], ['hummus','Хумус готовый',600,'grocery'],['biscuit','Крошка бисквитная',500,'bakery'], ['strawberry','Клубника',750,'fresh'],['blueberry','Голубика',1300,'fresh'],['sugar','Пудра сахарная',160,'grocery'], ['box','Коробка для кейтеринга',65,'pack','шт.'],['skewer','Шпажка бамбуковая',2,'pack','шт.'], ['cup','Стаканчик десертный',9,'pack','шт.'],['sauce-cup','Соусник',7,'pack','шт.'] ].map(([key,name,cost,supplier,unit='кг'])=>({key,id:`demo-v1-stock-${key}`,name,cost,unit,supplierId:`demo-v1-supplier-${supplier}`})); const byKey=new Map(products.map(p=>[p.key,p])); // Product quantities are gross/net in grams; packaging is in pieces. const recipes=[ {id:'bruschetta-tomato',name:'Брускетты с томатами и базиликом',price:2200,pieces:24, rows:[['baguette',480,480],['tomato',330,300],['basil',26,24],['oil',36,36]], composition:['24 брускетты с томатами, базиликом и оливковым маслом'],allergens:['Глютен'], steps:['Нарезать багет на 24 одинаковых ломтика и подсушить.','Подготовить томаты и базилик, смешать с маслом.','Распределить начинку по ломтикам, уложить в коробку.']}, {id:'salmon-cream',name:'Канапе с лососем и сливочным сыром',price:3200,pieces:16, rows:[['rye',240,240],['salmon',240,240],['cream',160,160],['cucumber',84,72],['dill',10,8]], composition:['16 канапе на ржаном хлебе с лососем, сливочным сыром и огурцом'],allergens:['Рыба','Молоко','Глютен'], steps:['Вырезать из ржаного хлеба 16 основ.','Нанести сливочный сыр, добавить ломтики огурца и лосося.','Украсить укропом и уложить в коробку.']}, {id:'chicken-sandwich',name:'Мини-сэндвичи с курицей',price:2400,pieces:12, rows:[['toast',360,360],['chicken',240,240],['cream',120,120],['tomato',92,84],['lettuce',45,36]], composition:['12 мини-сэндвичей с готовым куриным филе, томатами, салатом и сливочным сыром'],allergens:['Глютен','Молоко'], steps:['Нарезать готовое куриное филе, подготовить овощи и салат.','Собрать сэндвичи из тостового хлеба, сыра, курицы и овощей.','Нарезать на 12 одинаковых мини-сэндвичей и упаковать.']}, {id:'caprese',name:'Канапе «Капрезе»',price:2100,pieces:20, rows:[['mozzarella',360,360],['cherry',308,280],['basil',22,20],['oil',40,40],['skewer',20,20]], composition:['20 шпажек с моцареллой, черри и базиликом'],allergens:['Молоко'], steps:['Подготовить черри и базилик, обсушить моцареллу.','Собрать 20 шпажек, распределив ингредиенты поровну.','Добавить оливковое масло, уложить в коробку.']}, {id:'mushroom-tartlet',name:'Тарталетки с грибами и сыром',price:2300,pieces:20, rows:[['tartlet',200,200],['mushroom',440,300],['cooking-cream',100,100],['gouda',120,120],['onion',88,60],['oil',20,20]], composition:['20 тарталеток с шампиньонами, сливками и сыром'],allergens:['Глютен','Молоко'], steps:['Подготовить и обжарить лук с грибами на масле; в расчёте учтены потери массы.','Добавить сливки и распределить начинку по 20 тарталеткам.','Добавить сыр, запечь до расплавления и упаковать после охлаждения.']}, {id:'turkey-wrap',name:'Роллы из тортильи с индейкой',price:2700,pieces:25, rows:[['tortilla',320,320],['turkey',320,320],['cream',180,180],['lettuce',75,60],['pepper',150,120]], composition:['25 мини-роллов с ветчиной из индейки, сливочным сыром, перцем и салатом'],allergens:['Глютен','Молоко'], steps:['Подготовить салат и перец, нарезать ветчину.','Нанести сыр на тортильи, распределить начинку и свернуть плотные рулеты.','Нарезать на 25 порций и уложить срезом вверх.']}, {id:'cheese-fruit',name:'Сырный бокс с виноградом и орехами',price:2900,pieces:0, rows:[['brie',200,200],['gouda',180,180],['blue',120,120],['grape',176,160],['walnut',50,50],['honey',40,40],['cracker',50,50],['sauce-cup',1,1]], composition:['Бри, гауда и сыр с голубой плесенью','Виноград, грецкий орех, мёд и крекер'],allergens:['Молоко','Орехи','Глютен'], steps:['Нарезать сыры порционными кусочками.','Подготовить виноград, переложить мёд в соусник.','Разложить сыры, виноград, орехи и крекер отдельными секциями.']}, {id:'meat-assortment',name:'Мясное ассорти с корнишонами',price:3200,pieces:0, rows:[['salami',180,180],['beef',220,220],['turkey',150,150],['pickle',90,80],['olive',45,40],['mustard',30,30],['sauce-cup',1,1]], composition:['Салями, готовый ростбиф и ветчина из индейки','Корнишоны, маслины и горчица'],allergens:['Горчица'], steps:['Нарезать готовые мясные продукты тонкими ломтиками.','Обсушить корнишоны и маслины, переложить горчицу в соусник.','Разложить ассорти секциями, добавить гарниры.']}, {id:'vegetables-hummus',name:'Овощной бокс с хумусом',price:2100,pieces:0, rows:[['carrot',300,250],['cucumber',275,250],['pepper',250,200],['cherry',165,150],['hummus',150,150],['sauce-cup',1,1]], composition:['Морковь, огурцы, сладкий перец и черри','Хумус в отдельном соуснике'],allergens:['Кунжут в составе хумуса'], steps:['Вымыть и подготовить овощи; очистить морковь и перец.','Нарезать овощи палочками, черри оставить целыми.','Переложить хумус в соусник и разложить овощи вокруг него.']}, {id:'berry-dessert',name:'Ягодные мини-десерты',price:2800,pieces:16, rows:[['biscuit',160,160],['cream',320,320],['cooking-cream',160,160],['strawberry',176,160],['blueberry',84,80],['sugar',80,80],['cup',16,16]], composition:['16 десертов со сливочным кремом, бисквитом, клубникой и голубикой'],allergens:['Молоко','Глютен','Яйцо в составе бисквита'], steps:['Подготовить ягоды, разделить готовый бисквит на крошку.','Смешать сливочный сыр, сливки и сахарную пудру в крем.','Собрать 16 стаканчиков слоями: бисквит, крем, ягоды.']} ]; const round=n=>Math.round(n*1000)/1000; const totals=new Map(); export const boxes=recipes.map((r,index)=>{ const rows=[...r.rows,['box',1,1]].map(([key,gross,net])=>{const p=byKey.get(key),scale=p.unit==='кг'?1000:1;const row={productId:p.id,name:p.name,unit:p.unit,gross:round(gross/scale),net:round(net/scale),unitCost:p.cost};totals.set(key,round((totals.get(key)||0)+row.gross));return row}); const outputGrams=Math.round(rows.filter(p=>p.unit==='кг').reduce((s,p)=>s+p.net*1000,0)); return {id:`demo-v1-${r.id}`,name:r.name,price:r.price,category:0,catalogSection:'Демонстрационные боксы',pieces:r.pieces,weight:`${outputGrams} г`,photo:`demo/images/${r.id}.png`,composition:r.composition,ingredients:rows.map(p=>[p.name,p.gross,p.unit]),demo:true,ttk:{number:`ДЕМО-${String(index+1).padStart(2,'0')}`,basis:'На 1 готовый бокс',outputGrams,pieces:r.pieces,rows,steps:r.steps,allergens:r.allergens,ingredientCost:Math.round(rows.reduce((s,p)=>s+p.gross*p.unitCost,0)*100)/100,note:'Учебные нормы и цены для знакомства с приложением.'}}; }); export const stock=products.map((p,index)=>({id:p.id,name:p.name,unit:p.unit,cost:p.cost,qty:(p.unit==='шт.'?Math.floor:round)((totals.get(p.key)||0)*[0,0.45,2,0.7][index%4]),min:p.unit==='кг'?0.1:2,supplierId:p.supplierId,lastPurchaseDate:'',lastPurchasePrice:0})); export {suppliers}; export const demo={version:1,batch:'trial-demo-v1',boxes,stock,suppliers,scenario:{lines:[{id:'demo-v1-bruschetta-tomato',qty:2},{id:'demo-v1-salmon-cream',qty:1},{id:'demo-v1-caprese',qty:1}]}};