Files
site_aegisone/other/1C_UNF_INTEGRATION.md
T

431 lines
18 KiB
Markdown
Raw 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.
# Интеграция с 1С:УНФ 3.0 (1С-Фреш)
> Дата исследования: 04.06.2026
> Статус: ИССЛЕДОВАНИЕ (код не написан)
---
## 1. Краткое описание
Документ описывает доступные API для интеграции сервисного портала AegisOne с 1С:УНФ 3.0, работающей в облаке 1С-Фреш.
**Цель:** Синхронизация данных между 1С:УНФ и порталом — клиенты, заказы, контактные лица.
---
## 2. Доступные интерфейсы 1С-Фреш
| Интерфейс | Назначение | Чтение | Запись | Сложность |
|-----------|-----------|--------|--------|-----------|
| **OData** | Стандартный интерфейс платформы 1С | ✅ | ✅ | Средняя |
| **REST API** | Портал 1С:ITS Fresh-Integration | ✅ | ✅ | Средняя |
| **HTTP-сервис** | УниверсальнаяИнтеграция (UniversalIntegration) | ✅ | ✅ | Высокая |
| **Система взаимодействия** | Вебхуки (внешние → 1С) | ❌ | ✅ | Низкая |
### Главный вывод
**OData** — основной и самый доступный способ интеграции. Через OData доступны практи­чески все объекты 1С:УНФ 3.0: справочники, документы, регистры.
---
## 3. OData интерфейс
### 3.1 Формат URL
```
https://<server>/a/unf/<tenant>/odata/standard.odata/<Entity>
```
| Параметр | Описание | Пример |
|----------|----------|--------|
| `server` | Адрес сервера 1С-Фреш | `https://xxx.1cfresh.com` |
| `app` | Код приложения | `unf` (для УНФ) |
| `tenant` | Номер области данных | `34` |
| `Entity` | Имя объекта метаданных | `Catalog_Контрагенты` |
### 3.2 Аутентификация
```
Authorization: Basic <base64(login:password)>
```
Используется сервисный пользователь 1С-Фреш с правами доступа к OData.
### 3.3 Формат ответа
```
?$format=json — JSON
?$format=atom — Atom/XML (по умолчанию)
?$format=json;odata=nometadata — JSON без метаданных
```
---
## 4. Доступные сущности 1С:УНФ 3.0
### 4.1 Справочники (Catalogs)
| OData URL | Описание | Приоритет для нас |
|-----------|----------|-------------------|
| `Catalog_Контрагенты` | Покупатели, поставщики, прочие контрагенты | 🔴 Высокий → **Клиенты** |
| `Catalog_КонтактныеЛица` | Контактные лица контрагентов | 🔴 Высокий → **Контакты** |
| `Catalog_Номенклатура` | Услуги, товары, работы | 🟡 Средний → Каталог услуг |
| `Catalog_Договоры` | Договоры с контрагентами | 🟡 Средний → Привязка к клиенту |
| `Catalog_Проекты` | Проекты | 🟡 Средний → Связь с заказами |
| `Catalog_Организации` | Наши организации | 🟢 Низкий → Контекст |
| `Catalog_БанковскиеСчета` | Расчётные счета | 🟢 Низкий |
### 4.2 Документы (Documents)
| OData URL | Описание | Приоритет для нас |
|-----------|----------|-------------------|
| `Document_ЗаказКлиента` | Заказ покупателя | 🔴 Высокий → **Заказ/Лид** |
| `Document_РеализацияТоваровУслуг` | Реализация товаров и услуг | 🟡 Средний → История работ |
| `Document_АктВыполненныхРабот` | Акт выполненных работ | 🟡 Средний → Подтверждение |
| `Document_СчетНаОплату` | Счёт на оплату | 🟡 Средний → Финансы |
| `Document_ПоступлениеТоваров` | Поступление товаров | 🟢 Низкий → Закупки |
| `Document_СчетНаОплатуПоставщика` | Счёт от поставщика | 🟢 Низкий |
### 4.3 Регистры сведений
| OData URL | Описание |
|-----------|----------|
| `InformationRegister_ЦеныНоменклатурыДокументов` | Цены номенклатуры |
| `InformationRegister_КурсыВалют` | Курсы валют |
| `InformationRegister_НастройкиСистемыНалогообложения` | Учётная политика |
### 4.4 Табличные части
Доступны через суффикс имени:
```
Document_ЗаказКлиента_Товары — табличная часть «Товары»
Document_ЗаказКлиента_Услуги — табличная часть «Услуги»
Catalog_Контрагенты_КонтактнаяИнформация — контактная информация
```
---
## 5. Примеры запросов
### 5.1 Все контрагенты (покупатели)
```http
GET /odata/standard.odata/Catalog_Контрагенты?$format=json
&$select=Ref_Key,Description,ИНН,КПП,РегистрационныйНомер
&$filter=not (IsFolder)
&$orderby=Description
&$top=100
Authorization: Basic <auth>
```
### 5.2 Поиск контрагента по ИНН
```http
GET /odata/standard.odata/Catalog_Контрагенты?$format=json
&$select=Ref_Key,Description,ИНН,КПП
&$filter=(ИНН eq '2310031540')
Authorization: Basic <auth>
```
### 5.3 Поиск контрагента по наименованию
```http
GET /odata/standard.odata/Catalog_Контрагенты?$format=json
&$select=Ref_Key,Description,ИНН
&$filter=like(Description, 'Аегис%')
Authorization: Basic <auth>
```
### 5.4 Заказы конкретного клиента
```http
GET /odata/standard.odata/Document_ЗаказКлиента?$format=json
&$expand=Контрагент
&$select=Ref_Key,Number,Date,СуммаДокумента,Статус,Контрагент/Description
&$filter=Контрагент_Key eq guid'...'
&$orderby=Date desc
Authorization: Basic <auth>
```
### 5.5 Контактные лица контрагента
```http
GET /odata/standard.odata/Catalog_КонтактныеЛица?$format=json
&$select=Ref_Key,Description,Должность,Владелец_Key
&$filter=Владелец_Key eq guid'...'
Authorization: Basic <auth>
```
### 5.6 Номенклатура (услуги)
```http
GET /odata/standard.odata/Catalog_Номенклатура?$format=json
&$expand=ЕдиницаИзмерения
&$select=Ref_Key,Description,Артикул,ВидНоменклатуры
&$filter=not (IsFolder)
&$orderby=Description
Authorization: Basic <auth>
```
### 5.7 Создание нового контрагента (POST)
```http
POST /odata/standard.odata/Catalog_Контрагенты
Content-Type: application/json
Authorization: Basic <auth>
{
"Description": "ООО Ромашка",
"ИНН": "2310031540",
"КПП": "231001001",
"ЮридическоеФизическоеЛицо": "ЮридическоеЛицо"
}
```
### 5.8 Обновление контрагента (PATCH)
```http
PATCH /odata/standard.odata/Catalog_Контрагенты(guid'...')
Content-Type: application/json
Authorization: Basic <auth>
{
"Description": "ООО Ромашка (обновлено)"
}
```
---
## 6. Маппинг сущностей 1С:УНФ → Наш портал
### 6.1 Контрагенты → Клиенты
| Поле 1С:УНФ | Поле портала | Тип маппинга |
|-------------|-------------|--------------|
| `Ref_Key` | `onec_id` (UUID) | Прямой |
| `Description` | `company_name` | Прямой |
| `ИНН` | `inn` | Прямой (ключ дедупликации) |
| `КПП` | `kpp` | Прямой |
| `Телефон` | `phone` | Нормализация |
| `Email` | `email` | Прямой |
| `Адрес` | `address` | Прямой |
### 6.2 Заказ клиента → Лид/Заказ
| Поле 1С:УНФ | Поле портала | Тип маппинга |
|-------------|-------------|--------------|
| `Ref_Key` | `onec_order_id` (UUID) | Прямой |
| `Number` | `number` | Прямой |
| `Date` | `created_at` | Конвертация |
| `СуммаДокумента` | `amount` | Прямой |
| `Статус` | `status` | Маппинг статусов |
| `Контрагент_Key` | `customer_id` | FK (по onec_id) |
### 6.3 Статусы заказов
| Статус 1С:УНФ | Статус портала |
|---------------|---------------|
| В работе | `in_progress` |
| Закрыт | `completed` |
| Отменён | `cancelled` |
---
## 7. Стратегия интеграции
### Фаза 0: Настройка доступа (отдельная задача)
1. **Получить от пользователя:**
- URL базы в 1С-Фреш (типа `https://xxx.1cfresh.com/a/unf/`)
- Логин/пароль сервисного пользователя
- Номер области данных (tenant)
2. **Проверить доступность:**
- Выполнить тестовый запрос к `$metadata`
- Убедиться в наличии нужных сущностей
- Проверить права доступа
3. **Создать таблицу настроек:**
```sql
CREATE TABLE onec_settings (
id SERIAL PRIMARY KEY,
base_url VARCHAR(500) NOT NULL,
tenant VARCHAR(50) NOT NULL,
login VARCHAR(100) NOT NULL,
password_encrypted TEXT NOT NULL, -- fernet
last_sync_at TIMESTAMP,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT NOW()
);
```
### Фаза 1: Синхронизация контрагентов → клиенты
1. **Миграция:** Таблица `onec_sync_log` для логирования
```sql
CREATE TABLE onec_sync_log (
id SERIAL PRIMARY KEY,
entity_type VARCHAR(50) NOT NULL, -- 'contragent', 'order', etc.
onec_id UUID NOT NULL,
portal_id INTEGER,
action VARCHAR(20) NOT NULL, -- 'create', 'update', 'skip'
details JSONB,
synced_at TIMESTAMP DEFAULT NOW()
);
```
2. **Задача синхронизации:**
- Читаем `Catalog_Контрагенты` из 1С
- Дедупликация по ИНН (точное совпадение)
- Если ИНН нет — по наименованию + ИНН КПП
- Создаём/обновляем в таблице `customers`
- Логируем каждое действие
3. **Периодичность:** Раз в день (ночью) или по требованию
### Фаза 2: Синхронизация заказов
1. **Миграция:** Поле `onec_order_id` в `leads` или новая таблица
2. **Задача синхронизации:**
- Читаем `Document_ЗаказКлиента` из 1С
- Привязка к клиенту по `Контрагент_Key`
- Маппинг статусов
- Логирование
### Фаза 3 (опционально): Обратная запись
- Создание заказа в портале → создание в 1С
- Требует аккуратной обработки ошибок
- **Рекомендация:** Только после стабильности фаз 1-2
---
## 8. Технические детали
### 8.1 Python-клиент для OData
Рекомендуемая библиотека: `pyodata` или `requests` (raw OData).
```python
import base64
import httpx
class OneCFreshClient:
"""Клиент для работы с 1С-Фреш через OData."""
def __init__(self, base_url: str, tenant: str, login: str, password: str):
self.base_url = base_url.rstrip('/')
self.tenant = tenant
self.auth = base64.b64encode(f"{login}:{password}".encode()).decode()
async def get_contragents(self, top: int = 100, skip: int = 0) -> list:
"""Получить список контрагентов."""
url = f"{self.base_url}/a/unf/{self.tenant}/odata/standard.odata/Catalog_Контрагенты"
params = {
"$format": "json;odata=nometadata",
"$select": "Ref_Key,Description,ИНН,КПП",
"$filter": "not (IsFolder)",
"$top": str(top),
"$skip": str(skip),
}
headers = {"Authorization": f"Basic {self.auth}"}
async with httpx.AsyncClient() as client:
resp = await client.get(url, params=params, headers=headers)
resp.raise_for_status()
return resp.json().get("value", [])
async def get_contragent_by_inn(self, inn: str) -> dict | None:
"""Найти контрагента по ИНН."""
url = f"{self.base_url}/a/unf/{self.tenant}/odata/standard.odata/Catalog_Контрагенты"
params = {
"$format": "json;odata=nometadata",
"$select": "Ref_Key,Description,ИНН,КПП",
"$filter": f"(ИНН eq '{inn}')",
}
headers = {"Authorization": f"Basic {self.auth}"}
async with httpx.AsyncClient() as client:
resp = await client.get(url, params=params, headers=headers)
resp.raise_for_status()
items = resp.json().get("value", [])
return items[0] if items else None
```
### 8.2 Ограничения
| Ограничение | Описание | Решение |
|-------------|----------|---------|
| **Multi-tenancy** | Каждая база в своей области данных | Указать tenant в URL |
| **Публикация OData** | Должна быть включена в конфигурации | Проверить через `$metadata` |
| **Права доступа** | Сервисный пользователь должен иметь права на чтение | Настроить роли в 1С |
| **Пагинация** | Большие выборки — через `$top`/`$skip` | Построчная загрузка |
| **Rate limits** | Возможны ограничения на частоту запросов | Очередь задач, retry |
### 8.3 Проверка доступности
```bash
# Тестовый запрос метаданных
curl -u "login:password" \
"https://xxx.1cfresh.com/a/unf/34/odata/standard.odata/$metadata"
# Тестовый запрос контрагентов
curl -u "login:password" \
"https://xxx.1cfresh.com/a/unf/34/odata/standard.odata/Catalog_Контрагенты?\$format=json&\$top=5"
```
---
## 9. Сравнение с webhook (Система взаимодействия)
| Критерий | OData | Webhook |
|----------|-------|---------|
| **Чтение данных** | ✅ Да | ❌ Нет (только запись) |
| **Запись данных** | ✅ Да | ✅ Да (только в 1С) |
| **Направление** | Bidirectional | One-way (внешнее → 1С) |
| **Формат** | JSON (стандартный OData) | JSON (свой формат) |
| **Аутентификация** | Basic Auth | URL + логин/пароль |
| **Сложность** | Средняя | Низкая |
| **Использование** | Синхронизация данных | Уведомления, сообщения |
**Вывод:** OData — для синхронизации данных. Webhook — для отправки уведомлений в 1С.
---
## 10. Рекомендации
### Приоритет implementation
1. **OData синхронизация контрагентов** — самый важный функционал
2. **OData синхронизация заказов** — расширение функционала
3. **Webhook уведомления** — опционально, для двусторонней связи
### Вопросы к пользователю (для фазы 0)
1. URL базы в 1С-Фреш?
2. Логин/пароль сервисного пользователя?
3. Номер области данных (tenant)?
4. Какие данные в приоритете: контрагенты, заказы, или всё сразу?
5. Направление синхронизации: только из 1С → портал, или bidirectional?
### Рекомендация
**Начать с read-only синхронизации контрагентов** — самый безопасный и быстрый способ:
- Не требует записи обратно
- Минимальные риски
- Быстро даёт результат (клиенты из 1С появляются в портале)
- Потом можно расширять до заказов и bidirectional
---
## 11. Ссылки
- [Документация 1С-Фреш: OData](https://its.1c.ru/db/fresh/content/19956692/hdoc)
- [Платформа 1С: REST интерфейс](https://v8.1c.ru/platforma/rest-interfeys/)
- [OData: правила формирования имени ресурса](https://42clouds.com/ru-ru/manuals/interfeys-odata-pravila-formirovaniya-imeni-resursa/)
- [Работа с 1С через OData (Infostart)](https://infostart.ru/1c/articles/1570140/)
- [odata1c-client (GitHub)](https://github.com/Dakword/odata1c-client) — PHP-клиент с примерами
- [Контрагенты и контактные лица в 1С:УНФ](https://unf4you.ru/publ/kontragenty_i_kontaktnye_lica/1-1-0-407)
- [Заказ покупателя в 1С:УНФ](https://estart1c.ru/unf-30/189-kak-v-1sroznice-i-1sunf-sozdat-i-ispolzovat-zakaz-pokupatelja.html)