caterium-app/supabase/migrations/20260918010000_trial_demo_catalog.sql

85 lines
36 KiB
PL/PgSQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Generated by ops/demo/build-trial-demo.mjs. Fictional training catalog only.
begin;
create or replace function public.caterium_trial_demo_seed_v1()
returns jsonb language sql immutable security definer set search_path=public,pg_temp
as $fn$ select $demo${"version":1,"batch":"trial-demo-v1","boxes":[{"id":"demo-v1-bruschetta-tomato","name":"Брускетты с томатами и базиликом","price":2200,"category":0,"catalogSection":"Демонстрационные боксы","pieces":24,"weight":"840 г","photo":"demo/images/bruschetta-tomato.png","composition":["24 брускетты с томатами, базиликом и оливковым маслом"],"ingredients":[["Багет",0.48,"кг"],["Томаты",0.33,"кг"],["Базилик",0.026,"кг"],["Масло оливковое",0.036,"кг"],["Коробка для кейтеринга",1,"шт."]],"demo":true,"ttk":{"number":"ДЕМО-01","basis":"На 1 готовый бокс","outputGrams":840,"pieces":24,"rows":[{"productId":"demo-v1-stock-baguette","name":"Багет","unit":"кг","gross":0.48,"net":0.48,"unitCost":240},{"productId":"demo-v1-stock-tomato","name":"Томаты","unit":"кг","gross":0.33,"net":0.3,"unitCost":260},{"productId":"demo-v1-stock-basil","name":"Базилик","unit":"кг","gross":0.026,"net":0.024,"unitCost":1500},{"productId":"demo-v1-stock-oil","name":"Масло оливковое","unit":"кг","gross":0.036,"net":0.036,"unitCost":1100},{"productId":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","gross":1,"net":1,"unitCost":65}],"steps":["Нарезать багет на 24 одинаковых ломтика и подсушить.","Подготовить томаты и базилик, смешать с маслом.","Распределить начинку по ломтикам, уложить в коробку."],"allergens":["Глютен"],"ingredientCost":344.6,"note":"Учебные нормы и цены для знакомства с приложением."}},{"id":"demo-v1-salmon-cream","name":"Канапе с лососем и сливочным сыром","price":3200,"category":0,"catalogSection":"Демонстрационные боксы","pieces":16,"weight":"720 г","photo":"demo/images/salmon-cream.png","composition":["16 канапе на ржаном хлебе с лососем, сливочным сыром и огурцом"],"ingredients":[["Хлеб ржаной",0.24,"кг"],["Лосось слабосолёный",0.24,"кг"],["Сыр сливочный",0.16,"кг"],["Огурцы",0.084,"кг"],["Укроп",0.01,"кг"],["Коробка для кейтеринга",1,"шт."]],"demo":true,"ttk":{"number":"ДЕМО-02","basis":"На 1 готовый бокс","outputGrams":720,"pieces":16,"rows":[{"productId":"demo-v1-stock-rye","name":"Хлеб ржаной","unit":"кг","gross":0.24,"net":0.24,"unitCost":220},{"productId":"demo-v1-stock-salmon","name":"Лосось слабосолёный","unit":"кг","gross":0.24,"net":0.24,"unitCost":2400},{"productId":"demo-v1-stock-cream","name":"Сыр сливочный","unit":"кг","gross":0.16,"net":0.16,"unitCost":850},{"productId":"demo-v1-stock-cucumber","name":"Огурцы","unit":"кг","gross":0.084,"net":0.072,"unitCost":220},{"productId":"demo-v1-stock-dill","name":"Укроп","unit":"кг","gross":0.01,"net":0.008,"unitCost":700},{"productId":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","gross":1,"net":1,"unitCost":65}],"steps":["Вырезать из ржаного хлеба 16 основ.","Нанести сливочный сыр, добавить ломтики огурца и лосося.","Украсить укропом и уложить в коробку."],"allergens":["Рыба","Молоко","Глютен"],"ingredientCost":855.28,"note":"Учебные нормы и цены для знакомства с приложением."}},{"id":"demo-v1-chicken-sandwich","name":"Мини-сэндвичи с курицей","price":2400,"category":0,"catalogSection":"Демонстрационные боксы","pieces":12,"weight":"840 г","photo":"demo/images/chicken-sandwich.png","composition":["12 мини-сэндвичей с готовым куриным филе, томатами, салатом и сливочным сыром"],"ingredients":[["Хлеб тостовый",0.36,"кг"],["Филе курицы готовое",0.24,"кг"],["Сыр сливочный",0.12,"кг"],["Томаты",0.092,"кг"],["Салат листовой",0.045,"кг"],["Коробка для кейтеринга",1,"шт."]],"demo":true,"ttk":{"number":"ДЕМО-03","basis":"На 1 готовый бокс","outputGrams":840,"pieces":12,"rows":[{"productId":"demo-v1-stock-toast","name":"Хлеб тостовый","unit":"кг","gross":0.36,"net":0.36,"unitCost":240},{"productId":"demo-v1-stock-chicken","name":"Филе курицы готовое","unit":"кг","gross":0.24,"net":0.24,"unitCost":850},{"productId":"demo-v1-stock-cream","name":"Сыр сливочный","unit":"кг","gross":0.12,"net":0.12,"unitCost":850},{"productId":"demo-v1-stock-tomato","name":"Томаты","unit":"кг","gross":0.092,"net":0.084,"unitCost":260},{"productId":"demo-v1-stock-lettuce","name":"Салат листовой","unit":"кг","gross":0.045,"net":0.036,"unitCost":700},{"productId":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","gross":1,"net":1,"unitCost":65}],"steps":["Нарезать готовое куриное филе, подготовить овощи и салат.","Собрать сэндвичи из тостового хлеба, сыра, курицы и овощей.","Нарезать на 12 одинаковых мини-сэндвичей и упаковать."],"allergens":["Глютен","Молоко"],"ingredientCost":512.82,"note":"Учебные нормы и цены для знакомства с приложением."}},{"id":"demo-v1-caprese","name":"Канапе «Капрезе»","price":2100,"category":0,"catalogSection":"Демонстрационные боксы","pieces":20,"weight":"700 г","photo":"demo/images/caprese.png","composition":["20 шпажек с моцареллой, черри и базиликом"],"ingredients":[["Моцарелла мини",0.36,"кг"],["Томаты черри",0.308,"кг"],["Базилик",0.022,"кг"],["Масло оливковое",0.04,"кг"],["Шпажка бамбуковая",20,"шт."],["Коробка для кейтеринга",1,"шт."]],"demo":true,"ttk":{"number":"ДЕМО-04","basis":"На 1 готовый бокс","outputGrams":700,"pieces":20,"rows":[{"productId":"demo-v1-stock-mozzarella","name":"Моцарелла мини","unit":"кг","gross":0.36,"net":0.36,"unitCost":950},{"productId":"demo-v1-stock-cherry","name":"Томаты черри","unit":"кг","gross":0.308,"net":0.28,"unitCost":450},{"productId":"demo-v1-stock-basil","name":"Базилик","unit":"кг","gross":0.022,"net":0.02,"unitCost":1500},{"productId":"demo-v1-stock-oil","name":"Масло оливковое","unit":"кг","gross":0.04,"net":0.04,"unitCost":1100},{"productId":"demo-v1-stock-skewer","name":"Шпажка бамбуковая","unit":"шт.","gross":20,"net":20,"unitCost":2},{"productId":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","gross":1,"net":1,"unitCost":65}],"steps":["Подготовить черри и базилик, обсушить моцареллу.","Собрать 20 шпажек, распределив ингредиенты поровну.","Добавить оливковое масло, уложить в коробку."],"allergens":["Молоко"],"ingredientCost":662.6,"note":"Учебные нормы и цены для знакомства с приложением."}},{"id":"demo-v1-mushroom-tartlet","name":"Тарталетки с грибами и сыром","price":2300,"category":0,"catalogSection":"Демонстрационные боксы","pieces":20,"weight":"800 г","photo":"demo/images/mushroom-tartlet.png","composition":["20 тарталеток с шампиньонами, сливками и сыром"],"ingredients":[["Тарталетки готовые",0.2,"кг"],["Шампиньоны",0.44,"кг"],["Сливки",0.1,"кг"],["Сыр гауда",0.12,"кг"],["Лук репчатый",0.088,"кг"],["Масло оливковое",0.02,"кг"],["Коробка для кейтеринга",1,"шт."]],"demo":true,"ttk":{"number":"ДЕМО-05","basis":"На 1 готовый бокс","outputGrams":800,"pieces":20,"rows":[{"productId":"demo-v1-stock-tartlet","name":"Тарталетки готовые","unit":"кг","gross":0.2,"net":0.2,"unitCost":750},{"productId":"demo-v1-stock-mushroom","name":"Шампиньоны","unit":"кг","gross":0.44,"net":0.3,"unitCost":340},{"productId":"demo-v1-stock-cooking-cream","name":"Сливки","unit":"кг","gross":0.1,"net":0.1,"unitCost":500},{"productId":"demo-v1-stock-gouda","name":"Сыр гауда","unit":"кг","gross":0.12,"net":0.12,"unitCost":900},{"productId":"demo-v1-stock-onion","name":"Лук репчатый","unit":"кг","gross":0.088,"net":0.06,"unitCost":80},{"productId":"demo-v1-stock-oil","name":"Масло оливковое","unit":"кг","gross":0.02,"net":0.02,"unitCost":1100},{"productId":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","gross":1,"net":1,"unitCost":65}],"steps":["Подготовить и обжарить лук с грибами на масле; в расчёте учтены потери массы.","Добавить сливки и распределить начинку по 20 тарталеткам.","Добавить сыр, запечь до расплавления и упаковать после охлаждения."],"allergens":["Глютен","Молоко"],"ingredientCost":551.64,"note":"Учебные нормы и цены для знакомства с приложением."}},{"id":"demo-v1-turkey-wrap","name":"Роллы из тортильи с индейкой","price":2700,"category":0,"catalogSection":"Демонстрационные боксы","pieces":25,"weight":"1000 г","photo":"demo/images/turkey-wrap.png","composition":["25 мини-роллов с ветчиной из индейки, сливочным сыром, перцем и салатом"],"ingredients":[["Тортилья",0.32,"кг"],["Ветчина из индейки",0.32,"кг"],["Сыр сливочный",0.18,"кг"],["Салат листовой",0.075,"кг"],["Перец сладкий",0.15,"кг"],["Коробка для кейтеринга",1,"шт."]],"demo":true,"ttk":{"number":"ДЕМО-06","basis":"На 1 готовый бокс","outputGrams":1000,"pieces":25,"rows":[{"productId":"demo-v1-stock-tortilla","name":"Тортилья","unit":"кг","gross":0.32,"net":0.32,"unitCost":450},{"productId":"demo-v1-stock-turkey","name":"Ветчина из индейки","unit":"кг","gross":0.32,"net":0.32,"unitCost":1000},{"productId":"demo-v1-stock-cream","name":"Сыр сливочный","unit":"кг","gross":0.18,"net":0.18,"unitCost":850},{"productId":"demo-v1-stock-lettuce","name":"Салат листовой","unit":"кг","gross":0.075,"net":0.06,"unitCost":700},{"productId":"demo-v1-stock-pepper","name":"Перец сладкий","unit":"кг","gross":0.15,"net":0.12,"unitCost":380},{"productId":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","gross":1,"net":1,"unitCost":65}],"steps":["Подготовить салат и перец, нарезать ветчину.","Нанести сыр на тортильи, распределить начинку и свернуть плотные рулеты.","Нарезать на 25 порций и уложить срезом вверх."],"allergens":["Глютен","Молоко"],"ingredientCost":791.5,"note":"Учебные нормы и цены для знакомства с приложением."}},{"id":"demo-v1-cheese-fruit","name":"Сырный бокс с виноградом и орехами","price":2900,"category":0,"catalogSection":"Демонстрационные боксы","pieces":0,"weight":"800 г","photo":"demo/images/cheese-fruit.png","composition":["Бри, гауда и сыр с голубой плесенью","Виноград, грецкий орех, мёд и крекер"],"ingredients":[["Сыр бри",0.2,"кг"],["Сыр гауда",0.18,"кг"],["Сыр с голубой плесенью",0.12,"кг"],["Виноград",0.176,"кг"],["Орех грецкий очищенный",0.05,"кг"],["Мёд",0.04,"кг"],["Крекер",0.05,"кг"],["Соусник",1,"шт."],["Коробка для кейтеринга",1,"шт."]],"demo":true,"ttk":{"number":"ДЕМО-07","basis":"На 1 готовый бокс","outputGrams":800,"pieces":0,"rows":[{"productId":"demo-v1-stock-brie","name":"Сыр бри","unit":"кг","gross":0.2,"net":0.2,"unitCost":1600},{"productId":"demo-v1-stock-gouda","name":"Сыр гауда","unit":"кг","gross":0.18,"net":0.18,"unitCost":900},{"productId":"demo-v1-stock-blue","name":"Сыр с голубой плесенью","unit":"кг","gross":0.12,"net":0.12,"unitCost":1700},{"productId":"demo-v1-stock-grape","name":"Виноград","unit":"кг","gross":0.176,"net":0.16,"unitCost":420},{"productId":"demo-v1-stock-walnut","name":"Орех грецкий очищенный","unit":"кг","gross":0.05,"net":0.05,"unitCost":1000},{"productId":"demo-v1-stock-honey","name":"Мёд","unit":"кг","gross":0.04,"net":0.04,"unitCost":800},{"productId":"demo-v1-stock-cracker","name":"Крекер","unit":"кг","gross":0.05,"net":0.05,"unitCost":500},{"productId":"demo-v1-stock-sauce-cup","name":"Соусник","unit":"шт.","gross":1,"net":1,"unitCost":7},{"productId":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","gross":1,"net":1,"unitCost":65}],"steps":["Нарезать сыры порционными кусочками.","Подготовить виноград, переложить мёд в соусник.","Разложить сыры, виноград, орехи и крекер отдельными секциями."],"allergens":["Молоко","Орехи","Глютен"],"ingredientCost":938.92,"note":"Учебные нормы и цены для знакомства с приложением."}},{"id":"demo-v1-meat-assortment","name":"Мясное ассорти с корнишонами","price":3200,"category":0,"catalogSection":"Демонстрационные боксы","pieces":0,"weight":"700 г","photo":"demo/images/meat-assortment.png","composition":["Салями, готовый ростбиф и ветчина из индейки","Корнишоны, маслины и горчица"],"ingredients":[["Салями",0.18,"кг"],["Ростбиф готовый",0.22,"кг"],["Ветчина из индейки",0.15,"кг"],["Корнишоны",0.09,"кг"],["Маслины без косточек",0.045,"кг"],["Горчица",0.03,"кг"],["Соусник",1,"шт."],["Коробка для кейтеринга",1,"шт."]],"demo":true,"ttk":{"number":"ДЕМО-08","basis":"На 1 готовый бокс","outputGrams":700,"pieces":0,"rows":[{"productId":"demo-v1-stock-salami","name":"Салями","unit":"кг","gross":0.18,"net":0.18,"unitCost":1400},{"productId":"demo-v1-stock-beef","name":"Ростбиф готовый","unit":"кг","gross":0.22,"net":0.22,"unitCost":2000},{"productId":"demo-v1-stock-turkey","name":"Ветчина из индейки","unit":"кг","gross":0.15,"net":0.15,"unitCost":1000},{"productId":"demo-v1-stock-pickle","name":"Корнишоны","unit":"кг","gross":0.09,"net":0.08,"unitCost":400},{"productId":"demo-v1-stock-olive","name":"Маслины без косточек","unit":"кг","gross":0.045,"net":0.04,"unitCost":650},{"productId":"demo-v1-stock-mustard","name":"Горчица","unit":"кг","gross":0.03,"net":0.03,"unitCost":350},{"productId":"demo-v1-stock-sauce-cup","name":"Соусник","unit":"шт.","gross":1,"net":1,"unitCost":7},{"productId":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","gross":1,"net":1,"unitCost":65}],"steps":["Нарезать готовые мясные продукты тонкими ломтиками.","Обсушить корнишоны и маслины, переложить горчицу в соусник.","Разложить ассорти секциями, добавить гарниры."],"allergens":["Горчица"],"ingredientCost":989.75,"note":"Учебные нормы и цены для знакомства с приложением."}},{"id":"demo-v1-vegetables-hummus","name":"Овощной бокс с хумусом","price":2100,"category":0,"catalogSection":"Демонстрационные боксы","pieces":0,"weight":"1000 г","photo":"demo/images/vegetables-hummus.png","composition":["Морковь, огурцы, сладкий перец и черри","Хумус в отдельном соуснике"],"ingredients":[["Морковь",0.3,"кг"],["Огурцы",0.275,"кг"],["Перец сладкий",0.25,"кг"],["Томаты черри",0.165,"кг"],["Хумус готовый",0.15,"кг"],["Соусник",1,"шт."],["Коробка для кейтеринга",1,"шт."]],"demo":true,"ttk":{"number":"ДЕМО-09","basis":"На 1 готовый бокс","outputGrams":1000,"pieces":0,"rows":[{"productId":"demo-v1-stock-carrot","name":"Морковь","unit":"кг","gross":0.3,"net":0.25,"unitCost":90},{"productId":"demo-v1-stock-cucumber","name":"Огурцы","unit":"кг","gross":0.275,"net":0.25,"unitCost":220},{"productId":"demo-v1-stock-pepper","name":"Перец сладкий","unit":"кг","gross":0.25,"net":0.2,"unitCost":380},{"productId":"demo-v1-stock-cherry","name":"Томаты черри","unit":"кг","gross":0.165,"net":0.15,"unitCost":450},{"productId":"demo-v1-stock-hummus","name":"Хумус готовый","unit":"кг","gross":0.15,"net":0.15,"unitCost":600},{"productId":"demo-v1-stock-sauce-cup","name":"Соусник","unit":"шт.","gross":1,"net":1,"unitCost":7},{"productId":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","gross":1,"net":1,"unitCost":65}],"steps":["Вымыть и подготовить овощи; очистить морковь и перец.","Нарезать овощи палочками, черри оставить целыми.","Переложить хумус в соусник и разложить овощи вокруг него."],"allergens":["Кунжут в составе хумуса"],"ingredientCost":418.75,"note":"Учебные нормы и цены для знакомства с приложением."}},{"id":"demo-v1-berry-dessert","name":"Ягодные мини-десерты","price":2800,"category":0,"catalogSection":"Демонстрационные боксы","pieces":16,"weight":"960 г","photo":"demo/images/berry-dessert.png","composition":["16 десертов со сливочным кремом, бисквитом, клубникой и голубикой"],"ingredients":[["Крошка бисквитная",0.16,"кг"],["Сыр сливочный",0.32,"кг"],["Сливки",0.16,"кг"],["Клубника",0.176,"кг"],["Голубика",0.084,"кг"],["Пудра сахарная",0.08,"кг"],["Стаканчик десертный",16,"шт."],["Коробка для кейтеринга",1,"шт."]],"demo":true,"ttk":{"number":"ДЕМО-10","basis":"На 1 готовый бокс","outputGrams":960,"pieces":16,"rows":[{"productId":"demo-v1-stock-biscuit","name":"Крошка бисквитная","unit":"кг","gross":0.16,"net":0.16,"unitCost":500},{"productId":"demo-v1-stock-cream","name":"Сыр сливочный","unit":"кг","gross":0.32,"net":0.32,"unitCost":850},{"productId":"demo-v1-stock-cooking-cream","name":"Сливки","unit":"кг","gross":0.16,"net":0.16,"unitCost":500},{"productId":"demo-v1-stock-strawberry","name":"Клубника","unit":"кг","gross":0.176,"net":0.16,"unitCost":750},{"productId":"demo-v1-stock-blueberry","name":"Голубика","unit":"кг","gross":0.084,"net":0.08,"unitCost":1300},{"productId":"demo-v1-stock-sugar","name":"Пудра сахарная","unit":"кг","gross":0.08,"net":0.08,"unitCost":160},{"productId":"demo-v1-stock-cup","name":"Стаканчик десертный","unit":"шт.","gross":16,"net":16,"unitCost":9},{"productId":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","gross":1,"net":1,"unitCost":65}],"steps":["Подготовить ягоды, разделить готовый бисквит на крошку.","Смешать сливочный сыр, сливки и сахарную пудру в крем.","Собрать 16 стаканчиков слоями: бисквит, крем, ягоды."],"allergens":["Молоко","Глютен","Яйцо в составе бисквита"],"ingredientCost":895,"note":"Учебные нормы и цены для знакомства с приложением."}}],"stock":[{"id":"demo-v1-stock-baguette","name":"Багет","unit":"кг","cost":240,"qty":0,"min":0.1,"supplierId":"demo-v1-supplier-bakery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-tomato","name":"Томаты","unit":"кг","cost":260,"qty":0.19,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-basil","name":"Базилик","unit":"кг","cost":1500,"qty":0.096,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-oil","name":"Масло оливковое","unit":"кг","cost":1100,"qty":0.067,"min":0.1,"supplierId":"demo-v1-supplier-grocery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-rye","name":"Хлеб ржаной","unit":"кг","cost":220,"qty":0,"min":0.1,"supplierId":"demo-v1-supplier-bakery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-salmon","name":"Лосось слабосолёный","unit":"кг","cost":2400,"qty":0.108,"min":0.1,"supplierId":"demo-v1-supplier-protein","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-cream","name":"Сыр сливочный","unit":"кг","cost":850,"qty":1.56,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-cucumber","name":"Огурцы","unit":"кг","cost":220,"qty":0.251,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-dill","name":"Укроп","unit":"кг","cost":700,"qty":0,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-toast","name":"Хлеб тостовый","unit":"кг","cost":240,"qty":0.162,"min":0.1,"supplierId":"demo-v1-supplier-bakery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-chicken","name":"Филе курицы готовое","unit":"кг","cost":850,"qty":0.48,"min":0.1,"supplierId":"demo-v1-supplier-protein","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-lettuce","name":"Салат листовой","unit":"кг","cost":700,"qty":0.084,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-mozzarella","name":"Моцарелла мини","unit":"кг","cost":950,"qty":0,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-cherry","name":"Томаты черри","unit":"кг","cost":450,"qty":0.213,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-tartlet","name":"Тарталетки готовые","unit":"кг","cost":750,"qty":0.4,"min":0.1,"supplierId":"demo-v1-supplier-bakery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-mushroom","name":"Шампиньоны","unit":"кг","cost":340,"qty":0.308,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-cooking-cream","name":"Сливки","unit":"кг","cost":500,"qty":0,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-gouda","name":"Сыр гауда","unit":"кг","cost":900,"qty":0.135,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-onion","name":"Лук репчатый","unit":"кг","cost":80,"qty":0.176,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-tortilla","name":"Тортилья","unit":"кг","cost":450,"qty":0.224,"min":0.1,"supplierId":"demo-v1-supplier-bakery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-turkey","name":"Ветчина из индейки","unit":"кг","cost":1000,"qty":0,"min":0.1,"supplierId":"demo-v1-supplier-protein","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-pepper","name":"Перец сладкий","unit":"кг","cost":380,"qty":0.18,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-brie","name":"Сыр бри","unit":"кг","cost":1600,"qty":0.4,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-blue","name":"Сыр с голубой плесенью","unit":"кг","cost":1700,"qty":0.084,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-grape","name":"Виноград","unit":"кг","cost":420,"qty":0,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-walnut","name":"Орех грецкий очищенный","unit":"кг","cost":1000,"qty":0.023,"min":0.1,"supplierId":"demo-v1-supplier-grocery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-honey","name":"Мёд","unit":"кг","cost":800,"qty":0.08,"min":0.1,"supplierId":"demo-v1-supplier-grocery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-cracker","name":"Крекер","unit":"кг","cost":500,"qty":0.035,"min":0.1,"supplierId":"demo-v1-supplier-bakery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-salami","name":"Салями","unit":"кг","cost":1400,"qty":0,"min":0.1,"supplierId":"demo-v1-supplier-protein","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-beef","name":"Ростбиф готовый","unit":"кг","cost":2000,"qty":0.099,"min":0.1,"supplierId":"demo-v1-supplier-protein","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-pickle","name":"Корнишоны","unit":"кг","cost":400,"qty":0.18,"min":0.1,"supplierId":"demo-v1-supplier-grocery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-olive","name":"Маслины без косточек","unit":"кг","cost":650,"qty":0.032,"min":0.1,"supplierId":"demo-v1-supplier-grocery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-mustard","name":"Горчица","unit":"кг","cost":350,"qty":0,"min":0.1,"supplierId":"demo-v1-supplier-grocery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-carrot","name":"Морковь","unit":"кг","cost":90,"qty":0.135,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-hummus","name":"Хумус готовый","unit":"кг","cost":600,"qty":0.3,"min":0.1,"supplierId":"demo-v1-supplier-grocery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-biscuit","name":"Крошка бисквитная","unit":"кг","cost":500,"qty":0.112,"min":0.1,"supplierId":"demo-v1-supplier-bakery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-strawberry","name":"Клубника","unit":"кг","cost":750,"qty":0,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-blueberry","name":"Голубика","unit":"кг","cost":1300,"qty":0.038,"min":0.1,"supplierId":"demo-v1-supplier-fresh","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-sugar","name":"Пудра сахарная","unit":"кг","cost":160,"qty":0.16,"min":0.1,"supplierId":"demo-v1-supplier-grocery","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-box","name":"Коробка для кейтеринга","unit":"шт.","cost":65,"qty":7,"min":2,"supplierId":"demo-v1-supplier-pack","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-skewer","name":"Шпажка бамбуковая","unit":"шт.","cost":2,"qty":0,"min":2,"supplierId":"demo-v1-supplier-pack","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-cup","name":"Стаканчик десертный","unit":"шт.","cost":9,"qty":7,"min":2,"supplierId":"demo-v1-supplier-pack","lastPurchaseDate":"","lastPurchasePrice":0},{"id":"demo-v1-stock-sauce-cup","name":"Соусник","unit":"шт.","cost":7,"qty":6,"min":2,"supplierId":"demo-v1-supplier-pack","lastPurchaseDate":"","lastPurchasePrice":0}],"suppliers":[{"id":"demo-v1-supplier-fresh","name":"Демо: овощи и молочные продукты","active":true,"category":"Учебный поставщик","contact":"","phone":"","email":"","address":"","deliveryDays":"По договорённости","minOrder":0,"note":"Вымышленный поставщик для знакомства с приложением."},{"id":"demo-v1-supplier-protein","name":"Демо: мясо и рыба","active":true,"category":"Учебный поставщик","contact":"","phone":"","email":"","address":"","deliveryDays":"По договорённости","minOrder":0,"note":"Вымышленный поставщик для знакомства с приложением."},{"id":"demo-v1-supplier-bakery","name":"Демо: пекарня","active":true,"category":"Учебный поставщик","contact":"","phone":"","email":"","address":"","deliveryDays":"По договорённости","minOrder":0,"note":"Вымышленный поставщик для знакомства с приложением."},{"id":"demo-v1-supplier-grocery","name":"Демо: бакалея","active":true,"category":"Учебный поставщик","contact":"","phone":"","email":"","address":"","deliveryDays":"По договорённости","minOrder":0,"note":"Вымышленный поставщик для знакомства с приложением."},{"id":"demo-v1-supplier-pack","name":"Демо: упаковка","active":true,"category":"Учебный поставщик","contact":"","phone":"","email":"","address":"","deliveryDays":"По договорённости","minOrder":0,"note":"Вымышленный поставщик для знакомства с приложением."}],"scenario":{"lines":[{"id":"demo-v1-bruschetta-tomato","qty":2},{"id":"demo-v1-salmon-cream","qty":1},{"id":"demo-v1-caprese","qty":1}]}}$demo$::jsonb $fn$;
revoke all on function public.caterium_trial_demo_seed_v1() from public,anon,authenticated;
create or replace function public.caterium_trial_demo_status(p_workspace uuid)
returns jsonb language plpgsql stable security definer set search_path=public,pg_temp
as $fn$
declare
v_storage jsonb; v_empty boolean:=true; v_key text; v_value jsonb;
v_allowed boolean; v_installed boolean;
begin
if auth.uid() is null or public.sun_member_role(p_workspace) is null then raise exception 'Access denied'; end if;
select coalesce(payload->'storage','{}'::jsonb) into v_storage from public.sun_app_state where workspace_id=p_workspace;
v_installed:=coalesce(v_storage#>>'{sunTrialDemoV1,v,version}','')='1';
foreach v_key in array array['sunBoxes','sunStock','sunSuppliers','sunStockMoves'] loop
v_value:=v_storage#>array[v_key,'v'];
if v_value is not null and v_value<>'[]'::jsonb then v_empty:=false; end if;
if v_storage ? v_key and (jsonb_typeof(v_storage->v_key)<>'object' or v_value is null) then v_empty:=false; end if;
end loop;
v_allowed:=public.sun_member_role(p_workspace)='admin'
and public.sun_subscription_access_mode(p_workspace)='full'
and (exists(select 1 from public.sun_workspace_subscriptions where workspace_id=p_workspace and status='trialing') or public.sun_is_platform_admin())
and public.sun_workspace_has_feature(p_workspace,'catalog_edit')
and public.sun_workspace_has_feature(p_workspace,'stock')
and public.sun_workspace_has_feature(p_workspace,'suppliers')
and not exists(select 1 from public.sun_workspace_members m join public.caterium_sidebar_brand_assignment a on a.user_id=m.user_id where m.workspace_id=p_workspace);
return jsonb_build_object('eligible',coalesce(v_allowed,false),'installed',v_installed,'empty',v_empty,'canInstall',coalesce(v_allowed,false) and v_empty and not v_installed);
end $fn$;
revoke all on function public.caterium_trial_demo_status(uuid) from public,anon;
grant execute on function public.caterium_trial_demo_status(uuid) to authenticated;
create or replace function public.caterium_install_trial_demo(p_workspace uuid)
returns jsonb language plpgsql security definer set search_path=public,pg_temp
as $fn$
declare
v_state public.sun_app_state%rowtype; v_status jsonb; v_seed jsonb; v_storage jsonb; v_moves jsonb; v_marker jsonb;
begin
if auth.uid() is null or public.sun_member_role(p_workspace) is distinct from 'admin' then raise exception 'Administrator membership required'; end if;
perform 1 from public.sun_workspaces where id=p_workspace for update;
v_status:=public.caterium_trial_demo_status(p_workspace);
if not (v_status->>'eligible')::boolean then raise exception 'Демонстрационная база доступна в пробной или собственной тестовой компании разработчика'; end if;
if (v_status->>'installed')::boolean then return v_status; end if;
if not (v_status->>'empty')::boolean then raise exception 'Каталог, склад или поставщики уже заполнены. Данные сохранены без изменений'; end if;
select * into v_state from public.sun_app_state where workspace_id=p_workspace for update;
if not found then raise exception 'Рабочая база не найдена'; end if;
v_seed:=public.caterium_trial_demo_seed_v1();
select coalesce(jsonb_agg(jsonb_build_object('id','demo-v1-opening-'||(p->>'id'),'productId',p->>'id','productName',p->>'name','unit',p->>'unit',
'type','set','qty',p->'qty','setTo',p->'qty','cost',p->'cost','date',current_date::text,'createdAt',now(),
'supplierId',p->>'supplierId','note','Учебный начальный остаток')),'[]'::jsonb) into v_moves
from jsonb_array_elements(v_seed->'stock') p where (p->>'qty')::numeric>0;
v_marker:=jsonb_build_object('version',1,'batch','trial-demo-v1','installedAt',now(),'scenario',v_seed->'scenario');
v_storage:=coalesce(v_state.payload->'storage','{}'::jsonb)||jsonb_build_object(
'sunBoxes',jsonb_build_object('t','j','v',v_seed->'boxes'),
'sunStock',jsonb_build_object('t','j','v',v_seed->'stock'),
'sunSuppliers',jsonb_build_object('t','j','v',v_seed->'suppliers'),
'sunStockMoves',jsonb_build_object('t','j','v',v_moves),
'sunTrialDemoV1',jsonb_build_object('t','j','v',v_marker));
perform public.sun_save_app_state_v17(p_workspace,jsonb_set(v_state.payload,'{storage}',v_storage),'trial-demo-v1',v_state.revision);
insert into public.sun_platform_audit_events(actor_user_id,action,target_workspace_id,details)
values(auth.uid(),'trial_demo.install',p_workspace,jsonb_build_object('version',1,'boxes',10));
return public.caterium_trial_demo_status(p_workspace);
end $fn$;
revoke all on function public.caterium_install_trial_demo(uuid) from public,anon;
grant execute on function public.caterium_install_trial_demo(uuid) to authenticated;
create or replace function public.caterium_seed_new_trial()
returns trigger language plpgsql security definer set search_path=public,pg_temp
as $fn$
begin
if coalesce((public.caterium_trial_demo_status(new.workspace_id)->>'canInstall')::boolean,false) then
perform public.caterium_install_trial_demo(new.workspace_id);
end if;
return new;
end $fn$;
revoke all on function public.caterium_seed_new_trial() from public,anon,authenticated;
drop trigger if exists caterium_seed_new_trial on public.caterium_trial_redemptions;
create trigger caterium_seed_new_trial after insert on public.caterium_trial_redemptions
for each row execute function public.caterium_seed_new_trial();
notify pgrst,'reload schema';
commit;