Package Information
Documentation
n8n-nodes-onec — 1C Kodyaz İnteqrasiya Node-u
n8n üçün xüsusi 1C (1C:Enterprise) inteqrasiya node paketi — n8n-nodes-onec. 1C bazası ilə işləmək üçün bütün alətləri təmin edir: kəşf, oxu, izləmə və toplu emal.
📋 Mündəricat
- Ümumi Baxış
- Quraşdırma
- Credential Konfiqurasiyası
- Node Əməliyyatları
- Parametrlər Cədvəli
- 1C-də Nələr Edilməlidir
- 1C API Spesifikasiya
- İnkişaf
- Əlaqə
- Lisenziya
🔭 Ümumi Baxış
Bu paket n8n ilə 1C:Enterprise serveri arasında körpü qurur. 1C Kodyaz vahid node-u bütün trigger və action əməliyyatlarını özündə birləşdirir — 9 əməliyyat təmin edir:
- Metadata Kəşfi — 1C bazasındakı bütün obyektləri avtomatik aşkarlayır
- Məlumat Oxu — Səhifələmə və tarix filtri ilə istənilən obyekti oxuyur
- Sayma — Sürətli element sayı (data yüklənmir)
- JSON Strukturunu Öyrən — Obyektin sahə adlarını və nümunə dəyərlərini göstərir
- Yarat / Yenilə — POST ilə 1C-də soraqça elementi yaradır/yeniləyir, sənəd yaradır
- Xüsusi Sorğu — İstənilən endpoint-ə fərdi GET sorğusu
- Sənəd İzləmə — Yeni sənədləri polling ilə aşkarlayır (Schedule Trigger ilə)
- Metadata İzləmə — Obyekt tiplərində dəyişiklikləri aşkarlayır (Schedule Trigger ilə)
- Toplu Oxu — Birdən çox obyekti ardıcıl oxuyub vahid nəticədə birləşdirir
Server:
http://SIZIN_SERVER/SIZIN_BAZA/hs/api
Auth: HTTP Basic Authentication (istifadəçi adı mütləq, şifrə boş qala bilər)
📦 Quraşdırma
n8n Community Nodes (tövsiyə olunur)
n8n UI-da Settings → Community Nodes → Install → n8n-nodes-onec yazıb yükləyin.
Lokal Development
npm install n8n-nodes-onec
# və ya development üçün:
npx @n8n/node-cli new --source n8n-nodes-onec
Docker
docker run -d \
-v ~/.n8n:/home/node/.n8n \
-e N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true \
n8nio/n8n
Sonra n8n UI-da Settings → Community Nodes → n8n-nodes-onec quraşdırın.
🔑 Credential Konfiqurasiyası
1C API Credential
n8n UI-da Credentials → 1C API yaradın:
| Sahə | Təsvir | Nümunə |
|---|---|---|
| Base URL | 1C HTTP Servisin tam URL ünvanı | http://SERVER/BAZA/hs/api |
| User | 1C istifadəçi adı (mütləq) | Administrator |
| Password | 1C şifrəsi | şifrəniz |
⚠️ Təhlükəsizlik: 1C serverində mütləq şifrə təyin edin. Boş şifrə yalnız lokal/test mühitləri üçündür. Production mühitdə güclü şifrə istifadəsi tövsiyə olunur.
Test düyməsi /GetMetadata endpointini çağıraraq credential-i yoxlayır.
🔐 Təhlükəsizlik Tövsiyəsi: Minimum İmkanlı 1C İstifadəçiləri
Bu node-un istifadə etdiyi 1C credential-ı, 1C tərəfdə həmin istifadəçiyə təyin olunmuş bütün rol və icazələrlə işləyir — node özü əlavə məhdudiyyət tətbiq etmir.
Tövsiyə olunan praktika:
- Hər workflow və ya operator üçün ayrıca, məqsədə uyğun 1C istifadəçisi yaradın. Məsələn, kontragent borclarını izləyən workflow üçün yalnız müvafiq reyestrə oxuma icazəsi olan istifadəçi yetərlidir.
- Administrator və ya geniş hüquqlu hesablardan inteqrasiya üçün istifadə etməyin. Bu cür hesab sızarsa və ya workflow səhvən başqa obyektə sorğu göndərsə, məhdudiyyət yalnız 1C-nin rol sistemi tərəfindən qoyulur.
- 1C-də rol yaratarkən, yalnız
getEntities/getCount/getEntitySchemaüçün oxuma,createOrUpdateüçün isə əlavə olaraq yazma icazəsi verin — heç vaxt defolt olaraq tam icazə verməyin. - İcazəsi olmayan obyektə sorğu zamanı 1C 500 status kodu ilə cavab verir (səbəb 1C-nin daxili icazə xətasıdır). n8n-də bu, ümumi
"Request failed with status code 500"mesajı kimi görünür — bu, node-un xətası deyil, gözlənilən rədd cavabıdır.
Production-da boş şifrə istifadə etməyin. Şifrəni boş qoymaq yalnız lokal sınaq mühitləri üçün nəzərdə tutulub.
🔧 Node Əməliyyatları
Node "1C Kodyaz" vahid node kimi bütün əməliyyatları özündə birləşdirir — həm action (oxu, yaz, kəşf), həm də trigger/watch (izləmə) funksiyaları. Data & Storage / Transform / Development kateqoriyalarında yerləşir. Watch əməliyyatları n8n-in Schedule Trigger node-u ilə birlikdə işləyir.
1. Metadata Əldə Et (getMetadata)
Bazadakı bütün aktiv obyektləri kəşf edir. Hər hansı digər əməliyyatdan əvvəl çağırın.
Endpoint: GET /GetMetadata
Cavab: [{tip, ad, sinonim}] massivi
2. Məlumatları Oxu (getEntities)
Seçilmiş obyektin məlumatlarını səhifələmə və tarix filtrləri ilə oxuyur.
Endpoint: GET /{tip}/{ad}?page=N&pageSize=M
Parametrlər: entityPath, returnAll, page, pageSize, start, end
3. Sayını Öyrən (getCount)
Seçilmiş obyektin yalnız ümumi element sayını qaytarır.
Endpoint: GET /{tip}/{ad}?count=TRUE
Cavab: {total: N}
4. JSON Strukturunu Öyrən (getEntitySchema)
Seçilmiş 1C obyektindən ilk qeydi oxuyaraq onun JSON sahə adlarını, tiplərini və nümunə dəyərlərini qaytarır. POST body hazırlamazdan əvvəl obyektin strukturunu öyrənmək üçün istifadə olunur.
Endpoint: GET /{tip}/{ad}?pageSize=N (N=1-5)
Parametrlər: entityPath, schemaSampleSize
Cavab: { _entity, _schema: { fieldName: { type, example } }, _sampleRecords }
5. Yarat / Yenilə (createOrUpdate)
POST sorğusu ilə 1C-də yeni soraqça elementi yaradır və ya mövcud elementi yeniləyir, yeni sənəd yaradır. JSON body strukturu üçün əvvəlcə JSON Strukturunu Öyrən əməliyyatını istifadə edin.
Endpoint: POST /{tip}/{ad} (1C-də PostDataPOST handler-i)
Parametrlər: entityPath, jsonBody
Cavab: { _entity, _operation, _result }
POST body nümunəsi — Soraqça yaratma:
{"Наименование": "Yeni Müştəri", "Код": "001"}
POST body nümunəsi — Sənəd yaratma:
{
"Дата": "2026-06-17T15:30:00",
"Контрагент": "Əhməd MMC",
"Mallar": [
{ "Номенклатура": "Alma", "Количество": 10, "Цена": 2.5 }
]
}
6. Xüsusi Sorğu — Raw Request (rawRequest)
İstənilən 1C API endpointinə fərdi GET sorğusu göndərir.
Endpoint: İstənilən URL (manual daxil edilir)
Parametrlər: rawUrl, rawQueryParams (key=value cütləri)
7. Yeni Sənədləri İzlə (watchDocuments)
Schedule Trigger ilə birlikdə istifadə olunur. Hər yoxlamada son yoxlama tarixindən sonra yaranan yeni qeydləri aşkarlayır.
Parametrlər: entityPath, watchPageSize, lookbackMinutes, silentOnError
8. Metadata Dəyişikliklərini İzlə (watchMetadata)
Schedule Trigger ilə birlikdə istifadə olunur. Metadata-da yeni və ya silinmiş obyekt tiplərini aşkarlayır.
Parametrlər: silentOnError
9. Çoxlu Obyekt Oxu — Batch (batchRead)
Birdən çox 1C obyektini ardıcıl oxuyur, hər obyektə etiket əlavə edir və nəticələri vahid çıxışda birləşdirir.
Parametrlər: entities[], continueOnError
📊 Parametrlər Cədvəli
Əməliyyat (operation)
| Dəyər | Ad | Təsvir |
|---|---|---|
getMetadata |
Metadata Əldə Et | Bütün obyekt tiplərini kəşf et |
getEntities |
Məlumatları Oxu | Obyekt məlumatlarını səhifəli oxu |
getCount |
Sayını Öyrən | Yalnız ümumi element sayı |
getEntitySchema |
JSON Strukturunu Öyrən | Obyektin sahə strukturunu göstər |
createOrUpdate |
Yarat / Yenilə | POST ilə yeni qeyd yarat və ya yenilə |
rawRequest |
Xüsusi Sorğu (Raw Request) | Fərdi GET sorğusu |
watchDocuments |
Yeni Sənədləri İzlə | Polling ilə yeni sənəd aşkarla |
watchMetadata |
Metadata Dəyişikliklərini İzlə | Yeni/silinmiş obyektləri izlə |
batchRead |
Çoxlu Obyekt Oxu (Batch) | Çoxlu obyekti toplu oxu |
Obyekt (entityPath) — Resource Locator
| Rejim | Təsvir |
|---|---|
| Siyahıdan Seç | GetMetadata nəticələrindən axtarışlı dropdown (5 dəq TTL keş) |
| Manual Daxil Et | /Tip/Ad formatında birbaşa daxil etmə |
getEntities Parametrləri
| Parametr | Tip | Default | Təsvir |
|---|---|---|---|
returnAll |
boolean | false | Bütün səhifələri avtomatik gəz (max 10,000 səhifə) |
page |
number (≥1) | 1 | Manual səhifə seçimi |
pageSize |
number (1-200) | 20 | Səhifə başına element sayı |
start |
dateTime | (boş) | Başlanğıc tarix filteri (ISO format) |
end |
dateTime | (boş) | Bitmə tarixi filteri (ISO format) |
🖥 1C-də Nələr Edilməlidir
Bu bölmə 1C:Enterprise serverində Universal REST API HTTP Servisinin necə qurulacağını addım-addım izah edir.
Addım 1: HTTP Servisin Yaradılması
- 1C Konfiqurator-u açın
- Ümumi → HTTP Servisləri bölməsinə keçin
- Yeni HTTP Servis əlavə edin:
- Ad:
UniversalApi - Sinonim:
Universal 1C API - Kök URL:
hs/api
- Ad:
Addım 2: Şablonların (URL Templates) Əlavə Olunması
HTTP Servisin içində üç şablon yaradın:
| Şablon | Metod | Handler Funksiyası |
|---|---|---|
/GetMetadata |
GET | GetMetadataGET |
/{tip}/{ad} |
GET | GetDataGET |
/PostData |
POST | PostDataPOST |
Addım 3: Handler Funksiyalarının Tam Kodu
Aşağıdakı 3 funksiyanı HTTP Servisin moduluna əlavə edin:
3.1 GetMetadataGET — Kəşf endpointi
Функция GetMetadataGET(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
МассивМетаданных = Новый Массив;
// 1. Soraqçalar (Справочники)
Для Каждого Справочник Из Метаданные.Справочники Цикл
СтруктураО = Новый Структура;
СтруктураО.Вставить("tip", "Справочник");
СтруктураО.Вставить("ad", Справочник.Имя);
СтруктураО.Вставить("sinonim", Справочник.Синоним);
МассивМетаданных.Добавить(СтруктураО);
КонецЦикла;
// 2. Sənədlər (Документы)
Для Каждого Документ Из Метаданные.Документы Цикл
СтруктураО = Новый Структура;
СтруктураО.Вставить("tip", "Документ");
СтруктураО.Вставить("ad", Документ.Имя);
СтруктураО.Вставить("sinonim", Документ.Синоним);
МассивМетаданных.Добавить(СтруктураО);
КонецЦикла;
// 3. Məlumat Reyestrləri (РегистрыСведений)
Для Каждого РегистрСведения Из Метаданные.РегистрыСведений Цикл
СтруктураО = Новый Структура;
СтруктураО.Вставить("tip", "РегистрСведений");
СтруктураО.Вставить("ad", РегистрСведения.Имя);
СтруктураО.Вставить("sinonim", РегистрСведения.Синоним);
МассивМетаданных.Добавить(СтруктураО);
КонецЦикла;
// 4. Yığım Reyestrləri (РегистрыНакопления)
Для Каждого РегистрНакопления Из Метаданные.РегистрыНакопления Цикл
СтруктураО = Новый Структура;
СтруктураО.Вставить("tip", "РегистрНакопления");
СтруктураО.Вставить("ad", РегистрНакопления.Имя);
СтруктураО.Вставить("sinonim", РегистрНакопления.Синоним);
МассивМетаданных.Добавить(СтруктураО);
КонецЦикла;
// 5. JSON formatına çevirmə
Попытка
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивМетаданных);
СтрокаJSON = ЗаписьJSON.Закрыть();
Ответ.Заголовки.Вставить("Content-type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8);
Исключение
Ответ.КодСостояния = 400;
Ответ.УстановитьТелоИзСтроки("Xəta: " + ОписаниеОшибки(), КодировкаТекста.UTF8);
КонецПопытки;
Возврат Ответ;
КонецФункции
3.2 GetDataGET — Data oxuma endpointi (TAM KOD)
Функция GetDataGET(Запрос)
// ============================================================
// UNIVERSAL 1C HTTP SERVICE — GET Handler (Tam Düzgün Versiya)
// Soraqça + Sənəd + Məlumat Reyestri + Yığım Reyestri
// ============================================================
// 1. URL-dən obyektin növünü və adını oxuyuruq
ТипОбъекта = Запрос.ПараметрыURL.Получить("tip");
ИмяОбъекта = Запрос.ПараметрыURL.Получить("ad");
// Parametrlərin böyük/kiçik hərflərindən asılı olmaması üçün default dəyərlər
ParamPage = 1;
РазмерСтраницы = 20;
ParamStart = Неопределено;
ParamEnd = Неопределено;
ParamTop = Неопределено;
ParamCount = "FALSE";
Для Каждого КлючИЗначение Из Запрос.ПараметрыЗапроса Цикл
КлючВрег = Врег(КлючИЗначение.Ключ);
Если КлючВрег = "PAGE" Тогда
ParamPage = Макс(1, Число(КлючИЗначение.Значение));
ИначеЕсли КлючВрег = "PAGESIZE" Тогда
РазмерСтраницы = Мин(Макс(1, Число(КлючИЗначение.Значение)), 200);
ИначеЕсли КлючВрег = "START" Тогда
ParamStart = КлючИЗначение.Значение;
ИначеЕсли КлючВрег = "END" Тогда
ParamEnd = КлючИЗначение.Значение;
ИначеЕсли КлючВрег = "TOP" Тогда
ParamTop = Число(КлючИЗначение.Значение);
ИначеЕсли КлючВрег = "COUNT" Тогда
ParamCount = Врег(Строка(КлючИЗначение.Значение));
КонецЕсли;
КонецЦикла;
Если ЗначениеЗаполнено(ParamTop) Тогда
ParamPage = 1;
РазмерСтраницы = Мин(ParamTop, 200);
КонецЕсли;
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-type", "application/json; charset=utf-8");
// Giriş sahələrinin validasiyası
Если Не ЗначениеЗаполнено(ТипОбъекта) Или Не ЗначениеЗаполнено(ИмяОбъекта) Тогда
Ответ.КодСостояния = 400;
Ответ.УстановитьТелоИзСтроки("{""error"": ""'tip' ve 'ad' parametrleri mutleqdir""}", КодировкаТекста.UTF8);
Возврат Ответ;
КонецЕсли;
ВрегТип = Врег(ТипОбъекта);
МДОбъект = Неопределено;
Попытка
Если ВрегТип = "СПРАВОЧНИК" Тогда МДОбъект = Метаданные.Справочники[ИмяОбъекта];
ИначеЕсли ВрегТип = "ДОКУМЕНТ" Тогда МДОбъект = Метаданные.Документы[ИмяОбъекта];
ИначеЕсли ВрегТип = "РЕГИСТРСВЕДЕНИЙ" Тогда МДОбъект = Метаданные.РегистрыСведений[ИмяОбъекта];
ИначеЕсли ВрегТип = "РЕГИСТРНАКОПЛЕНИЯ" Тогда МДОбъект = Метаданные.РегистрыНакопления[ИмяОбъекта];
КонецЕсли;
Исключение
МДОбъект = Неопределено;
КонецПопытки;
Если МДОбъект = Неопределено Тогда
Ответ.КодСостояния = 400;
Ответ.УстановитьТелоИзСтроки("{""error"": ""Obyekt tapilmadi: " + ТипОбъекта + "." + ИмяОбъекта + """}", КодировкаТекста.UTF8);
Возврат Ответ;
КонецЕсли;
Попытка
// 2. Dinamik olaraq sahələrin metaməlumatdan yığılması
МассивПолей = Новый Массив;
СтрокаСортировки = "";
Если ВрегТип = "СПРАВОЧНИК" Тогда
МассивПолей.Добавить("Т.Ссылка КАК Ссылка");
МассивПолей.Добавить("Т.Код КАК Код");
МассивПолей.Добавить("Т.Наименование КАК Наименование");
Попытка
Если МДОбъект.Иерархический Тогда
МассивПолей.Добавить("Т.Родитель КАК Родитель");
МассивПолей.Добавить("Т.ЭтоГруппа КАК ЭтоГруппа");
КонецЕсли;
Исключение
КонецПопытки;
МассивПолей.Добавить("Т.ПометкаУдаления КАК ПометкаУдаления");
МассивПолей.Добавить("Т.Предопределенный КАК Предопределенный");
СтрокаСортировки = " УПОРЯДОЧИТЬ ПО Т.Ссылка";
ИначеЕсли ВрегТип = "ДОКУМЕНТ" Тогда
МассивПолей.Добавить("Т.Ссылка КАК Ссылка");
МассивПолей.Добавить("Т.Дата КАК Дата");
МассивПолей.Добавить("Т.Номер КАК Номер");
МассивПолей.Добавить("Т.ПометкаУдаления КАК ПометкаУдаления");
МассивПолей.Добавить("Т.Проведен КАК Проведен");
СтрокаСортировки = " УПОРЯДОЧИТЬ ПО Т.Дата УБЫВ, Т.Ссылка УБЫВ";
ИначеЕсли ВрегТип = "РЕГИСТРСВЕДЕНИЙ" Тогда
Попытка
Если МДОбъект.Периодический <> Метаданные.Свойства.ПериодичностьРегистраСведений.Непериодический Тогда
МассивПолей.Добавить("Т.Период КАК Период");
СтрокаСортировки = " УПОРЯДОЧИТЬ ПО Т.Период УБЫВ";
КонецЕсли;
Исключение
КонецПопытки;
Для Каждого Измерение Из МДОбъект.Измерения Цикл МассивПолей.Добавить("Т." + Измерение.Имя + " КАК " + Измерение.Имя); КонецЦикла;
Для Каждого Ресурс Из МДОбъект.Ресурсы Цикл МассивПолей.Добавить("Т." + Ресурс.Имя + " КАК " + Ресурс.Имя); КонецЦикла;
Если ПустаяСтрока(СтрокаСортировки) И МДОбъект.Измерения.Количество() > 0 Тогда
СтрокаСортировки = " УПОРЯДОЧИТЬ ПО Т." + МДОбъект.Измерения[0].Имя;
КонецЕсли;
ИначеЕсли ВрегТип = "РЕГИСТРНАКОПЛЕНИЯ" Тогда
МассивПолей.Добавить("Т.Период КАК Период");
МассивПолей.Добавить("Т.Регистратор КАК Регистратор");
МассивПолей.Добавить("Т.НомерСтроки КАК НомерСтроки");
МассивПолей.Добавить("Т.ВидДвижения КАК ВидДвижения");
Для Каждого Измерение Из МДОбъект.Измерения Цикл МассивПолей.Добавить("Т." + Измерение.Имя + " КАК " + Измерение.Имя); КонецЦикла;
Для Каждого Ресурс Из МДОбъект.Ресурсы Цикл МассивПолей.Добавить("Т." + Ресурс.Имя + " КАК " + Ресурс.Имя); КонецЦикла;
СтрокаСортировки = " УПОРЯДОЧИТЬ ПО Т.Период УБЫВ, Т.Регистратор, Т.НомерСтроки";
КонецЕсли;
// Ümumi dinamik rekvizitlərin əlavə olunması
Для Каждого Реквизит Из МДОбъект.Реквизиты Цикл
ИмяРек = Реквизит.Имя;
Если ВрегТип = "СПРАВОЧНИК" И (Врег(ИмяРек) = "КОД" Или Врег(ИмяРек) = "НАИМЕНОВАНИЕ" Или Врег(ИмяРек) = "РОДИТЕЛЬ" Или Врег(ИмяРек) = "ЭТОГРУППА") Тогда Продолжить; КонецЕсли;
Если ВрегТип = "ДОКУМЕНТ" И (Врег(ИмяРек) = "ДАТА" Или Врег(ИмяРек) = "НОМЕР") Тогда Продолжить; КонецЕсли;
МассивПолей.Добавить("Т." + ИмяРек + " КАК " + ИмяРек);
КонецЦикла;
СтрокаПолей = СтрСоединить(МассивПолей, ", ");
// Şərtlər bloku (ГДЕ)
Условия = Новый Массив;
ПараметрыДат = Новый Структура;
Если ВрегТип = "ДОКУМЕНТ" Или ВрегТип = "РЕГИСТРНАКОПЛЕНИЯ" Или (ВрегТип = "РЕГИСТРСВЕДЕНИЙ" И МассивПолей.Найти("Т.Период КАК Период") <> Неопределено) Тогда
ИмяПоляВремени = ?(ВрегТип = "ДОКУМЕНТ", "Дата", "Период");
Если ЗначениеЗаполнено(ParamStart) Тогда
Условия.Добавить("Т." + ИмяПоляВремени + " >= &StartDate");
ПараметрыДат.Вставить("StartDate", XMLЗначение(Тип("Дата"), ParamStart));
КонецЕсли;
Если ЗначениеЗаполнено(ParamEnd) Тогда
Условия.Добавить("Т." + ИмяПоляВремени + " <= &EndDate");
ПараметрыДат.Вставить("EndDate", XMLЗначение(Тип("Дата"), ParamEnd));
КонецЕсли;
КонецЕсли;
СтрокаУсловий = ?(Условия.Количество() > 0, " ГДЕ " + СтрСоединить(Условия, " И "), "");
// 3. ÜMUMİ SAYIN TAPILMASI (COUNT)
ЗапросСчет = Новый Запрос;
ЗапросСчет.Текст = "ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Всего ИЗ " + ТипОбъекта + "." + ИмяОбъекта + " КАК Т" + СтрокаУсловий;
Для Каждого Пара Из ПараметрыДат Цикл
ЗапросСчет.УстановитьПараметр(Пара.Ключ, Пара.Значение);
КонецЦикла;
ВсегоЗаписей = 0;
ВыборкаСчет = ЗапросСчет.Выполнить().Выбрать();
Если ВыборкаСчет.Следующий() Тогда ВсегоЗаписей = ВыборкаСчет.Всего; КонецЕсли;
Если ParamCount = "TRUE" Тогда
ЗаписьJSON = Новый ЗаписьJSON; ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Новый Структура("total", ВсегоЗаписей));
Ответ.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть(), КодировкаТекста.UTF8);
Возврат Ответ;
КонецЕсли;
// 4. MULTI-VERSION PAGINATION ENGINE
Смещение = (ParamPage - 1) * РазмерСтраницы;
ЗапросБД = Новый Запрос;
Для Каждого Пара Из ПараметрыДат Цикл ЗапросБД.УстановитьПараметр(Пара.Ключ, Пара.Значение); КонецЦикла;
Если (ВрегТип = "СПРАВОЧНИК" Или ВрегТип = "ДОКУМЕНТ") И Смещение > 0 Тогда
ЗапросОфсет = Новый Запрос;
ЗапросОфсет.Текст = "ВЫБРАТЬ ПЕРВЫЕ " + Формат(Смещение, "ЧГ=0") + " Т.Ссылка КАК Ссылка ИЗ " + ТипОбъекта + "." + ИмяОбъекта + " КАК Т" + СтрокаУсловий + СтрокаСортировки;
Для Каждого Пара Из ПараметрыДат Цикл ЗапросОфсет.УстановитьПараметр(Пара.Ключ, Пара.Значение); КонецЦикла;
МассивПредыдущих = ЗапросОфсет.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
СтрокаУсловийОснова = ?(СтрокаУсловий = "", " ГДЕ Т.Ссылка НЕ В (&МассивПредыдущих)", СтрокаУсловий + " И Т.Ссылка НЕ В (&МассивПредыдущих)");
ТекстЗапроса = "ВЫБРАТЬ ПЕРВЫЕ " + Формат(РазмерСтраницы, "ЧГ=0") + " " + СтрокаПолей + " ИЗ " + ТипОбъекта + "." + ИмяОбъекта + " КАК Т" + СтрокаУсловийОснова + СтрокаСортировки;
ЗапросБД.Текст = ТекстЗапроса;
ЗапросБД.УстановитьПараметр("МассивПредыдущих", МассивПредыдущих);
ИначеЕсли (ВрегТип = "РЕГИСТРСВЕДЕНИЙ" Или ВрегТип = "РЕГИСТРНАКОПЛЕНИЯ") Тогда
MaksLimitРек = Смещение + РазмерСтраницы;
ТекстЗапроса = "ВЫБРАТЬ ПЕРВЫЕ " + Формат(MaksLimitРек, "ЧГ=0") + " " + СтрокаПолей + " ИЗ " + ТипОбъекта + "." + ИмяОбъекта + " КАК Т" + СтрокаУсловий + СтрокаСортировки;
ЗапросБД.Текст = ТекстЗапроса;
Иначе
ТекстЗапроса = "ВЫБРАТЬ ПЕРВЫЕ " + Формат(РазмерСтраницы, "ЧГ=0") + " " + СтрокаПолей + " ИЗ " + ТипОбъекта + "." + ИмяОбъекта + " КАК Т" + СтрокаУсловий + СтрокаСортировки;
ЗапросБД.Текст = ТекстЗапроса;
КонецЕсли;
РезультатЗапроса = ЗапросБД.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Колонки = РезультатЗапроса.Колонки;
СсылкаСуществует = (Колонки.Найти("Ссылка") <> Неопределено);
МассивРезультата = Новый Массив;
ТекущийИндекс = 0;
// 5. Məlumatın struktura yığılması
Пока Выборка.Следующий() Цикл
Если (ВрегТип = "РЕГИСТРСВЕДЕНИЙ" Или ВрегТип = "РЕГИСТРНАКОПЛЕНИЯ") И ТекущийИндекс < Смещение Тогда
ТекущийИндекс = ТекущийИндекс + 1;
Продолжить;
КонецЕсли;
СтруктураЭлемента = Новый Структура;
Для Каждого Колонка Из Колонки Цикл
ИмяПоля = Колонка.Имя;
ЗначениеПоля = Выборка[ИмяПоля];
ТипЗначения = ТипЗнч(ЗначениеПоля);
Если ЗначениеПоля = Null Или ЗначениеПоля = Неопределено Тогда
СтруктураЭлемента.Вставить(ИмяПоля, Неопределено);
Продолжить;
КонецЕсли;
Если ТипЗначения = Тип("Строка") Или ТипЗначения = Тип("Число") Или ТипЗначения = Тип("Булево") Или ТипЗначения = Тип("Дата") Тогда
СтруктураЭлемента.Вставить(ИмяПоля, ЗначениеПоля);
Продолжить;
КонецЕсли;
Попытка
МетаИнформация = Метаданные.НайтиПоТипу(ТипЗначения);
Если МетаИнформация <> Неопределено Или Метаданные.Перечисления.Содержит(МетаИнформация) Тогда
СтруктураЭлемента.Вставить(ИмяПоля, Строка(ЗначениеПоля));
Иначе
СтруктураЭлемента.Вставить(ИмяПоля, ?(ЗначениеЗаполнено(ЗначениеПоля), Строка(ЗначениеПоля), ""));
КонецЕсли;
Исключение
СтруктураЭлемента.Вставить(ИмяПоля, Строка(ЗначениеПоля));
КонецПопытки;
КонецЦикла;
// Cədvəl hissələri (ТЧ)
Если СсылкаСуществует Тогда
Попытка
МетаОбъект = Метаданные.НайтиПоТипу(ТипЗнч(Выборка.Ссылка));
Если МетаОбъект <> Неопределено Тогда
Для Каждого ТЧ Из МетаОбъект.ТабличныеЧасти Цикл
ИмяТЧ = ТЧ.Имя;
МассивТЧ = Новый Массив;
ТаблицаТЧ = Выборка.Ссылка[ИмяТЧ].Выгрузить();
Для Каждого СтрокаТЧ Из ТаблицаТЧ Цикл
СтруктураСтрокиТЧ = Новый Структура;
Для Каждого КолонкаТЧ Из ТаблицаТЧ.Колонки Цикл
ИмяКолонкиТЧ = КолонкаТЧ.Имя;
ЗначениеТЧ = СтрокаТЧ[ИмяКолонкиТЧ];
Если ЗначениеТЧ = Null Или ЗначениеТЧ = Неопределено Тогда
СтруктураСтрокиТЧ.Вставить(ИмяКолонкиТЧ, Неопределено);
ИначеЕсли ТипЗнч(ЗначениеТЧ) = Тип("Строка") Или ТипЗнч(ЗначениеТЧ) = Тип("Число") Или ТипЗнч(ЗначениеТЧ) = Тип("Булево") Или ТипЗнч(ЗначениеТЧ) = Тип("Дата") Тогда
СтруктураСтрокиТЧ.Вставить(ИмяКолонкиТЧ, ЗначениеТЧ);
Иначе
СтруктураСтрокиТЧ.Вставить(ИмяКолонкиТЧ, Строка(ЗначениеТЧ));
КонецЕсли;
КонецЦикла;
МассивТЧ.Добавить(СтруктураСтрокиТЧ);
КонецЦикла;
СтруктураЭлемента.Вставить(ИмяТЧ, МассивТЧ);
КонецЦикла;
КонецЕсли;
Исключение
КонецПопытки;
КонецЕсли;
МассивРезультата.Добавить(СтруктураЭлемента);
ТекущийИндекс = ТекущийИндекс + 1;
КонецЦикла;
// 6. CAVABIN FORMATLAŞDIRILMASI (META + DATA)
ВсегоСтраниц = Макс(1, Цел((ВсегоЗаписей + РазмерСтраницы - 1) / РазмерСтраницы));
Мета = Новый Структура;
Мета.Вставить("total", ВсегоЗаписей);
Мета.Вставить("page", ParamPage);
Мета.Вставить("pageSize", РазмерСтраницы);
Мета.Вставить("totalPages", ВсегоСтраниц);
Мета.Вставить("count", МассивРезультата.Количество());
ОтветСтруктура = Новый Структура;
ОтветСтруктура.Вставить("meta", Мета);
ОтветСтруктура.Вставить("data", МассивРезультата);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ОтветСтруктура);
СтрокаJSON = ЗаписьJSON.Закрыть();
Ответ.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8);
Исключение
Ответ.КодСостояния = 500;
Ответ.УстановитьТелоИзСтроки("{""error"": """ + ОписаниеОшибки() + """}", КодировкаТекста.UTF8);
КонецПопытки;
Возврат Ответ;
КонецФункции
3.3 PostDataPOST — Məlumat yaratma/yeniləmə endpointi (POST)
Bu funksiya n8n-dən gələn POST sorğusunu emal edir. Soraq kitabçalarında (Справочник) adla axtarış edib tapar, tapmasa yaradar, tapsa yeniləyər. Sənədlər (Документ) üçün yeni sənəd yaradıb təsdiqləyər, əlaqəli soraq kitabçalarını avtomatik axtarar/yaradar, cədvəl hissələrini (ТЧ) emal edər.
POST body nümunəsi (Справочник):
{
"Наименование": "Yeni Kontragent",
"Код": "00001"
}
POST body nümunəsi (Документ — Alış Sənədi):
{
"Дата": "2026-06-17T15:30:00",
"Контрагент": "Əhməd MMC",
"Mallar": [
{ "Номенклатура": "Alma", "Количество": 10, "Цена": 2.5 },
{ "Номенклатура": "Armud", "Количество": 5, "Цена": 3.0 }
]
}
Tam BSL kodu:
Функция PostDataPOST(Запрос)
// 1. URL-dən obyektin növünü və adını oxuyuruq
ТипОбъекта = Запрос.ПараметрыURL.Получить("tip");
ИмяОбъекта = Запрос.ПараметрыURL.Получить("ad");
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-type", "application/json; charset=utf-8");
Попытка
// 2. n8n-dən gələn POST bədənini (JSON) oxuyuruq
СтрокаJSON = Запрос.ПолучитьТелоКакСтроку("UTF-8");
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
Данные = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
МассивРезультатов = Новый Массив;
// Əgər n8n-dən tək obyekt gəlibsə, onu massivə salırıq
Если ТипЗнч(Данные) = Тип("Структура") Тогда
МассивДанных = Новый Массив;
МассивДанных.Добавить(Данные);
Иначе
МассивДанных = Данные;
КонецЕсли;
// =========================================================
// MƏNTİQ 1: SORAQ KİTABÇALARI (СПРАВОЧНИК) ÜÇÜN
// =========================================================
Если Врег(ТипОбъекта) = "СПРАВОЧНИК" Тогда
Менеджер = Справочники[ИмяОбъекта];
Для Каждого ЭлементДанных Из МассивДанных Цикл
Если ЭлементДанных.Свойство("Наименование") Тогда
ИмяЭлемента = ЭлементДанных.Наименование;
СсылкаНаОбъект = Менеджер.НайтиПоНаименованию(ИмяЭлемента, Истина);
Если СсылкаНаОбъект.Пустая() Тогда
НовыйОбъект = Менеджер.СоздатьЭлемент();
НовыйОбъект.Наименование = ИмяЭлемента;
ЗаполнитьЗначенияСвойств(НовыйОбъект, ЭлементДанных);
НовыйОбъект.Записать();
МассивРезультатов.Добавить(ИмяЭлемента + " - Uğurla yaradıldı");
Иначе
Объект = СсылкаНаОбъект.ПолучитьОбъект();
ЗаполнитьЗначенияСвойств(Объект, ЭлементДанных);
Объект.Записать();
МассивРезультатов.Добавить(ИмяЭлемента + " - Uğurla yeniləndi");
КонецЕсли;
Иначе
МассивРезультатов.Добавить("Xəta: JSON daxilində 'Наименование' xassəsi tapılmadı");
КонецЕсли;
КонецЦикла;
// =========================================================
// MƏNTİQ 2: SƏNƏDLƏR (ДОКУМЕНТ) ÜÇÜN
// =========================================================
ИначеЕсли Врег(ТипОбъекта) = "ДОКУМЕНТ" Тогда
Менеджер = Документы[ИмяОбъекта];
Для Каждого ЭлементДанных Из МассивДанных Цикл
НовыйДок = Менеджер.СоздатьДокумент();
// Tarix məntiqi
Если ЭлементДанных.Свойство("Дата") И ЗначениеЗаполнено(ЭлементДанных.Дата) Тогда
Попытка
Если ТипЗнч(ЭлементДанных.Дата) = Тип("Дата") Тогда
НовыйДок.Дата = ЭлементДанных.Дата;
Иначе
СтрДата = СтрЗаменить(ЭлементДанных.Дата, "T", "");
СтрДата = СтрЗаменить(СтрДата, "-", "");
СтрДата = СтрЗаменить(СтрДата, ":", "");
НовыйДок.Дата = Дата(СтрДата);
КонецЕсли;
Исключение
НовыйДок.Дата = ТекущаяДата();
КонецПопытки;
ЭлементДанных.Удалить("Дата");
Иначе
НовыйДок.Дата = ТекущаяДата();
КонецЕсли;
ЗаполнитьЗначенияСвойств(НовыйДок, ЭлементДанных);
// Avtomatik soraqça axtar/yarat
Для Каждого Реквизит Из НовыйДок.Метаданные().Реквизиты Цикл
ИмяРеквизита = Реквизит.Имя;
Если ЭлементДанных.Свойство(ИмяРеквизита) И ТипЗнч(ЭлементДанных[ИмяРеквизита]) = Тип("Строка") И ЗначениеЗаполнено(ЭлементДанных[ИмяРеквизита]) Тогда
Для Каждого ТекущийТип Из Реквизит.Тип.Типы() Цикл
МетаИнформация = Метаданные.НайтиПоТипу(ТекущийТип);
Если МетаИнформация <> Неопределено И Метаданные.Справочники.Содержит(МетаИнформация) Тогда
ИмяСправочника = МетаИнформация.Имя;
СсылкаНаЭлемент = Справочники[ИмяСправочника].НайтиПоНаименованию(ЭлементДанных[ИмяРеквизита], Истина);
Если СсылкаНаЭлемент.Пустая() Тогда
НовСправ = Справочники[ИмяСправочника].СоздатьЭлемент();
НовСправ.Наименование = ЭлементДанных[ИмяРеквизита];
НовСправ.Записать();
НовыйДок[ИмяРеквизита] = НовСправ.Ссылка;
Иначе
НовыйДок[ИмяРеквизита] = СсылкаНаЭлемент;
КонецЕсли;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
// Cədvəl hissələri (ТЧ)
Для Каждого ТЧ Из НовыйДок.Метаданные().ТабличныеЧасти Цикл
ИмяТЧ = ТЧ.Имя;
Если ЭлементДанных.Свойство(ИмяТЧ) И ТипЗнч(ЭлементДанных[ИмяТЧ]) = Тип("Массив") Тогда
Для Каждого СтрокаJSON Из ЭлементДанных[ИмяТЧ] Цикл
НоваяСтрока = НовыйДок[ИмяТЧ].Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаJSON);
Для Каждого Колонка Из ТЧ.Реквизиты Цикл
ИмяКолонки = Колонка.Имя;
Если СтрокаJSON.Свойство(ИмяКолонки) И ТипЗнч(СтрокаJSON[ИмяКолонки]) = Тип("Строка") И ЗначениеЗаполнено(СтрокаJSON[ИмяКолонки]) Тогда
Для Каждого ТекущийТип Из Колонка.Тип.Типы() Цикл
МетаИнформация = Метаданные.НайтиПоТипу(ТекущийТип);
Если МетаИнформация <> Неопределено И Метаданные.Справочники.Содержит(МетаИнформация) Тогда
ИмяСправТЧ = МетаИнформация.Имя;
СсылкаТЧ = Справочники[ИмяСправТЧ].НайтиПоНаименованию(СтрокаJSON[ИмяКолонки], Истина);
Если СсылкаТЧ.Пустая() Тогда
НовЭлТЧ = Справочники[ИмяСправТЧ].СоздатьЭлемент();
НовЭлТЧ.Наименование = СтрокаJSON[ИмяКолонки];
НовЭлТЧ.Записать();
НоваяСтрока[ИмяКолонки] = НовЭлТЧ.Ссылка;
Иначе
НоваяСтрока[ИмяКолонки] = СсылкаТЧ;
КонецЕсли;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЦикла;
НовыйДок.Записать(РежимЗаписиДокумента.Проведение);
МассивРезультатов.Добавить("Sənəd nömrə " + НовыйДок.Номер + " uğurla yaradıldı və təsdiqləndi.");
КонецЦикла;
Иначе
Ответ.КодСостояния = 400;
МассивРезультатов.Добавить("Bu POST metodu hələlik yalnız 'Справочник' və 'Документ' növü üçün aktivdir.");
КонецЕсли;
// Nəticələri JSON olaraq qaytarırıq
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивРезультатов);
Ответ.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть(), КодировкаТекста.UTF8);
Исключение
Ответ.КодСостояния = 400;
Ответ.УстановитьТелоИзСтроки("{""error"": """ + СтрЗаменить(ОписаниеОшибки(), """", "\""") + """}", КодировкаТекста.UTF8);
КонецПопытки;
Возврат Ответ;
КонецФункции
Addım 4: Veb Serverdə Paylaşma
- 1C-də Administration → Veb serverdə paylaş bölməsinə keçin
- HTTP Servisi seçin və Publish düyməsini basın
- Ünvanı yoxlayın:
http://<server_ip>/<baza_adı>/hs/api
Test:
curl -u <user>:<password> "http://<server>/<base>/hs/api/GetMetadata"
Əhəmiyyətli Qeydlər
| Məsələ | Təsvir |
|---|---|
| Case-insensitive | Query parametrləri Врег() ilə yoxlanır — PAGE, Page, page eynidir |
| TOP parametri | Köhnə OData üsulu ilə uyğunluq üçün dəstəklənir — avtomatik page=1, pageSize=TOP |
| Cədvəl hissələri | Sənədlərin cədvəl hissələri (ТЧ) avtomatik $expand edilir |
| Dinamik sahələr | Bütün rekvizitlər metaməlumatdan avtomatik oxunur |
| Xətalar | 400 = obyekt tapılmadı, 500 = daxili 1C xətası |
| 4 tip dəstəyi | Справочник, Документ, РегистрСведений, РегистрНакопления |
| Pagination | Soraqça/Sənəd üçün offset (Ссылка НЕ В), Reyestrlər üçün ПЕРВЫЕ N |
| Periodik | Periodik reyestrlər avtomatik Период sahəsi ilə gəlir |
📐 1C API Spesifikasiya
Universal Dinamik Kəşf və Data API (v1.2.0)
API iki mərhələli dinamik yanaşma təklif edir:
Mərhələ 1: Kəşf
GET /GetMetadata
Bütün mövcud 1C obyektlərini siyahı şəklində qaytarır:
| Obyekt Tipi | Təsvir |
|---|---|
Справочник |
Statik məlumatlar: Kontragent, Nomenklatura, Anbarlar... |
Документ |
Hərəkət sənədləri: Alış, Satış, Ödəniş... |
РегистрСведений |
Dövri məlumatlar: Qiymətlər, xassələr... |
РегистрНакопления |
Anbar qalıqları, dövriyyələr... |
Cavab formatı:
[
{ "tip": "Справочник", "ad": "Kontragent", "sinonim": "Kontragent" },
{ "tip": "Документ", "ad": "AlışSənədi", "sinonim": "Alış sənədi" }
]
Mərhələ 2: Data İstehlakı
GET /{tip}/{ad}?page=1&pageSize=20&start=2024-01-01&end=2024-12-31
| Parametr | Tip | Default | Max | Təsvir |
|---|---|---|---|---|
page |
Integer | 1 | — | Cari səhifə |
pageSize |
Integer | 20 | 200 | Səhifə ölçüsü |
count |
Boolean | FALSE | — | TRUE = yalnız say |
start |
ISO Date | — | — | Başlanğıc tarix |
end |
ISO Date | — | — | Bitmə tarixi |
Cavab formatı:
{
"meta": { "total": 7, "page": 1, "pageSize": 2, "totalPages": 4, "count": 2 },
"data": [
{ "Ссылка": "Əhməd", "Код": "000000002", "Наименование": "Əhməd" }
]
}
🛠 İnkişaf
Tələblər
- Node.js ≥ 18
- npm ≥ 9
Qurma və Test
npm install
npm run build # TypeScript kompilyasiya
npm run dev # n8n + hot reload (http://localhost:5678)
npm run lint # ESLint yoxlaması
npm run lint:fix # Avtomatik düzəliş
npm run test # Vitest testləri
npm run release # Versiya bump + publish
Fayl Strukturu
n8n-nodes-starter/
├── credentials/
│ └── OneCApi.credentials.ts # 1C Basic Auth credential
├── nodes/
│ └── OneC/
│ ├── OneCKodyaz.node.ts # Vahid node sinfi (9 əməliyyat + trigger/watch)
│ ├── OneCKodyaz.node.json # Codex metadata
│ ├── listSearch/
│ │ ├── getEntityTypes.ts # Obyekt axtarış dropdown (5 dəq TTL keş)
│ │ └── getEntityFields.ts # POST üçün sahə adları təklifi
│ └── shared/
│ ├── transport.ts # HTTP sorğu helper (retry + URL normallaşdırma)
│ └── types.ts # TypeScript interfeysləri
├── test/
│ ├── extractEntityPath.test.ts # Unit testlər (6 test)
│ └── transport.test.ts # Retry məntiqi testləri (9 test)
├── icons/
│ ├── onec.svg
│ └── onec.dark.svg
├── README.md
└── package.json
📞 Əlaqə
- Vebsayt: www.kodyaz.az
- Email: info@kodyaz.az
- Telefon: +994 10 101 31 41
- npm: npmjs.com/package/n8n-nodes-onec
📄 Lisenziya
Bütün hüquqlar qorunur © 2026 KodYaz. Bu proqram təminatı KodYaz-ın əqli mülkiyyətidir.