Максимальная интеграция. HTML-поле для менеджера + прямые HTTP-запросы из 1С:
авто-смена статусов после оплаты, синхронизация склада ликвидных остатков,
опциональные вебхуки. Всё в одном модуле.
Что добавляется сверх UI
Статус заказа меняется автоматически (paid → in_production)
Склад ликвидных остатков синхронизируется с 1С
Регламентное задание для периодической синхронизации
Получение данных расчёта программно (без UI)
Подписка на вебхуки (order.completed, remnant.added)
Требования
Толстый клиент (не работает в тонком/вебе)
Разрешение «Использование внешних программ и интернет-ресурсов»
Доступ к raskroy.app:443 с сервера 1С
API-ключ с уровнем pro или enterprise
Полный модуль «РаскройПанелей»
Вставьте весь код в один общий модуль. Флаги: Клиент (управляемое) + Сервер (для HTTP-функций).
РаскройПанелей — полный модуль (~150 строк)
// ═══════════════════════════════════════════════════════════════
// РаскройПанелей — Толстый клиент, UI + API
// Флаги модуля: Клиент (УФ) + Сервер
// ═══════════════════════════════════════════════════════════════// ── Настройки ────────────────────────────────────────────────────
BASE_URL = "https://raskroy.app";
API_TOKEN = "rsk_ВАШ_КЛЮЧ";
// ════════════════════════ КЛИЕНТСКАЯ ЧАСТЬ ══════════════════════// Открыть расчёт в HTML-поле (вызывается с формы)
// Режим: "sandwich" (сэндвич-панели, по умолчанию) или "windowsill" (подоконники)&НаКлиентеПроцедураОткрытьРасчёт(ПолеHTML, НомерСчёта, Контрагент, Детали, Стратегия = "optimal", Режим = "sandwich") ЭкспортДеталиСтрока = "";
Для КаждогоДИзДеталиЦиклДеталиСтрока = ДеталиСтрока + ?(ДеталиСтрока="","",",")
+ Д.ИД+":"+Строка(Д.Ширина)+":"+Строка(Д.Высота)+":"+Строка(Д.Количество);
КонецЦикла;
URL = BASE_URL + "/?source=1c&invoice="
+ КодироватьСтроку(НомерСчёта, СпособКодированияСтроки.URLВАдресеСтроки)
+ "&client=" + КодироватьСтроку(Контрагент, СпособКодированияСтроки.URLВАдресеСтроки)
+ "&strategy=" + Стратегия + "&mode=" + Режим
+ "&token=" + API_TOKEN
+ "&parts=" + ДеталиСтрока;
ПолеHTML.Перейти(URL);
КонецПроцедуры// Пример вызова из формы счёта:
// ОткрытьРасчёт(Элементы.HTML, Объект.Номер, Объект.Контрагент.Наименование,
// ДеталиСэндвича, "optimal", "sandwich"); // сэндвич
// ОткрытьРасчёт(Элементы.HTML, Объект.Номер, Объект.Контрагент.Наименование,
// ДеталиПодоконников, "standard", "windowsill"); // подоконники// Получить ответ (вызывается из ПриПолученииСообщенияОтВебСтраницы)&НаКлиентеПроцедураОбработатьОтветКлиент(Форма, JSONСтрока) ЭкспортЧтение = НовыйЧтениеJSON;
Чтение.УстановитьСтроку(JSONСтрока);
Данные = ПрочитатьJSON(Чтение);
ЕслиДанные.type <> "raskroy.fillInvoice"ТогдаВозврат; КонецЕсли;
// Заполнить строку табличной части — ключевое слово зависит от режима
// Данные.mode = "sandwich" | "windowsill" (получаем от веб-интерфейса)ТабЧасть = Форма.Объект.Товары;
КлючНоменклатуры = ?(Данные.mode = "windowsill", "подоконник", "сэндвич");
Стр = Неопределено;
Для КаждогоСИзТабЧастьЦиклЕслиСтрНайти(НРег(С.Номенклатура.Наименование),КлючНоменклатуры)>0ТогдаСтр=С; Прервать; КонецЕсли;
КонецЦикла;
ЕслиСтр=НеопределеноТогдаСтр=ТабЧасть.Добавить(); КонецЕсли;
Стр.Количество = Данные.sheets_used;
Стр.Комментарий = "Раскрой: "+Данные.sheets_used+" л. КПД "+Данные.efficiency_pct+"%";
Сообщить("✓ Заполнено: "+Данные.sheets_used+" листов");
// Обновить статус на сервере (если счёт уже оплачен — сразу в производство)ОбновитьСтатус(Строка(Форма.Объект.Ссылка), "issued");
КонецПроцедуры// ════════════════════════ СЕРВЕРНАЯ ЧАСТЬ ═══════════════════════// Обновить статус заказа через API&НаСервереПроцедураОбновитьСтатус(ЗаказID, Статус, Контрагент = "", Примечание = "") ЭкспортПопыткаСоединение = НовыйHTTPСоединение("raskroy.app",,,,,, НовыйЗащищённоеСоединениеOpenSSL);
Запрос = НовыйHTTPЗапрос("/api/v1/orders/"+ЗаказID+"/status");
Запрос.Заголовки.Вставить("Content-Type", "application/json");
Запрос.Заголовки.Вставить("X-API-Key", API_TOKEN);
Тело = НовыйСтруктура("status,client_name,production_note",
Статус, Контрагент, Примечание);
Запрос.УстановитьТелоИзСтроки(_ВJSON(Тело));
Соединение.ВызватьHTTP(Запрос, "PATCH");
ИсключениеЖурналРегистрации.Записать("РаскройПанелей",, "Ошибка обновления статуса: "+ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры// Получить данные заказа (invoice-формат, без SVG)&НаСервереФункцияПолучитьДанныеЗаказа(ЗаказID) ЭкспортПопыткаСоединение = НовыйHTTPСоединение("raskroy.app",,,,,, НовыйЗащищённоеСоединениеOpenSSL);
Запрос = НовыйHTTPЗапрос("/api/v1/orders/"+ЗаказID+"/invoice");
Запрос.Заголовки.Вставить("X-API-Key", API_TOKEN);
Ответ = Соединение.Получить(Запрос);
ЕслиОтвет.КодСостояния = 200ТогдаВозврат_ИзJSON(Ответ.ПолучитьТелоКакСтроку());
КонецЕсли;
ИсключениеЖурналРегистрации.Записать("РаскройПанелей",, ОписаниеОшибки());
КонецПопытки;
ВозвратНеопределено;
КонецФункции// Синхронизировать склад остатков 1С → сервис// ОстаткиСписок — Массив структур {ИД1С, Ширина, Высота}&НаСервереПроцедураСинхронизироватьСклад(ОстаткиСписок) ЭкспортРемнантыMassив = НовыйМассив;
Для КаждогоОстИзОстаткиСписокЦиклРем = НовыйСтруктура;
Рем.Вставить("w", Ост.Ширина);
Рем.Вставить("h", Ост.Высота);
Рем.Вставить("external_meta", НовыйСтруктура("1c_ref", Ост.ИД1С));
РемнантыMassив.Добавить(Рем);
КонецЦикла;
Тело = НовыйСтруктура("remnants", РемнантыMassив);
ПопыткаСоединение = НовыйHTTPСоединение("raskroy.app",,,,,, НовыйЗащищённоеСоединениеOpenSSL);
Запрос = НовыйHTTPЗапрос("/api/v1/remnants/bulk");
Запрос.Заголовки.Вставить("Content-Type", "application/json");
Запрос.Заголовки.Вставить("X-API-Key", API_TOKEN);
Запрос.УстановитьТелоИзСтроки(_ВJSON(Тело));
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Д = _ИзJSON(Ответ.ПолучитьТелоКакСтроку());
ЖурналРегистрации.Записать("РаскройПанелей",, "Синхронизировано остатков: "+Д.processed);
ИсключениеЖурналРегистрации.Записать("РаскройПанелей",, "Ошибка синхронизации: "+ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры// ── Вспомогательные ──────────────────────────────────────────────&НаСервереФункция_ВJSON(Объект)
ЗаписьJSON = НовыйЗаписьJSON; ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Объект); ВозвратЗаписьJSON.Закрыть();
КонецФункции&НаСервереФункция_ИзJSON(Строка)
Ч = НовыйЧтениеJSON; Ч.УстановитьСтроку(Строка); ВозвратПрочитатьJSON(Ч);
КонецФункции