Как правильно спроектировать новую подсистему с документами в 1С?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Правильное проектирование подсистемы с документами в 1С
Это один из ключевых навыков 1С-архитектора. Я расскажу о методологии, которая позволяет спроектировать масштабируемую и поддерживаемую подсистему. Основываюсь на опыте 10+ лет разработки сложных систем.
Фаза 1: Бизнес-аналитика и требования
Шаг 1.1 — Определить жизненный цикл документа
Перед тем как открывать конфигуратор, нужно понять states документа:
Документ: "Заказ покупателя"
Lifecycle:
Черновик
↓ (Пользователь нажимает "На утверждение")
На утверждении
↓ (Менеджер утверждает)
Утверждён
↓ (Автоматически при создании акта выполнения)
Выполняется
↓ (Проведение документа)
Проведён
↓ (Отгрузка товара)
Отгружен
↓ (Оплачено)
Закрыт
Переходы и действия:
- Утверждение → требует права
- Проведение → требует проверок
- Отмена → возможна только в Черновике
- Возврат → возможен только в Утверждении
Это определяет структуру таблицы переходов состояний и обработчиков событий.
Шаг 1.2 — Определить аналитику документа
Перед тем как создавать поля, выпишите:
Аналитики регистров:
- По каким направлениям вести учёт?
- Контрагенты, Виды деятельности, Склады?
Итоги:
- Сумма по документу
- Количество товара
- Скидка
- Налоги
Текущее состояние:
- Статус проведения
- Дата создания, проведения
- Автор, утверждающее лицо
Это определяет реквизиты и табличные части документа.
Шаг 1.3 — Определить регистры
Какие регистры будет питать этот документ?
Документ "Заказ покупателя" пишет в:
- РегистрНакопления.Резерв (остатки)
- РегистрНакопления.Выручка (аналитика по начислениям)
- РегистрСведений.ПланГрафик (справочная информация)
- РегистрСведений.Согласования (кто утверждал и когда)
Не берите просто так "популярные" регистры — они должны соответствовать бизнес-логике.
Фаза 2: Проектирование структуры метаданных
Шаг 2.1 — Создать иерархию справочников
Для нашего примера нужны справочники:
Справочник "Контрагенты" (иерархический)
├─ Физические лица
└─ Юридические лица
Справочник "ВидыДеятельности"
Справочник "Склады" (иерархический)
├─ Склад А
├─ Склад Б
└─ ...
Справочник "Товары"
Реквизиты:
- ЕдиницаИзмерения
- ТипТовара (Материал, Услуга, ...)
- Себестоимость
Шаг 2.2 — Спроектировать структуру документа
// Заказ покупателя (структура)
Документ "ЗаказПокупателя"
Реквизиты:
Контрагент (Справочник.Контрагенты)
Дата (DateTime)
НомерДокумента (String)
ВидДеятельности (Справочник.ВидыДеятельности)
Табличные части:
Товары
Товар (Справочник.Товары)
Склад (Справочник.Склады)
Количество (Decimal)
ЦенаЕд (Decimal)
Сумма (Decimal)
Скидка (Decimal)
Согласования
ЛицоСогласующее (Справочник.Сотрудники)
ДатаСогласования (DateTime)
Комментарий (String)
Стандартные реквизиты:
Проведён (Boolean) — для контроля проведения
Дата (DateTime) — обязательна для документов
Фаза 3: Архитектура функциональности
Шаг 3.1 — Разделить на слои
Соблюдайте Onion Architecture:
┌─────────────────────────────────────┐
│ Presentation (UI) │ ← Формы, команды
├─────────────────────────────────────┤
│ Application (Services) │ ← Бизнес-процессы
├─────────────────────────────────────┤
│ Domain (Business Logic) │ ← Валидация, расчёты
├─────────────────────────────────────┤
│ Infrastructure (DB, External) │ ← Регистры, БД
└─────────────────────────────────────┘
Для нашего заказа:
// ===== DOMAIN LAYER =====
Общий модуль "ЗаказПокупателя" (Domain)
Процедура ПроверитьКорректность(Заказ) Экспорт
Если Заказ.Товары.Количество() = 0 Тогда
ВызватьИсключение "Заказ должен содержать товары";
КонецЕсли;
Если Заказ.Контрагент.Пусто() Тогда
ВызватьИсключение "Не выбран контрагент";
КонецЕсли;
КонецПроцедуры
Функция РассчитатьСумму(Заказ) Экспорт
Сумма = 0;
Для Каждого Строка Из Заказ.Товары Цикл
Сумма = Сумма + Строка.Сумма - Строка.Скидка;
КонецЦикла;
Возврат Сумма;
КонецФункции
// ===== APPLICATION LAYER =====
Общий модуль "СервисЗаказов" (Service)
Процедура ПроводитьЗаказ(ЗаказСсылка) Экспорт
Заказ = ЗаказСсылка.ПолучитьОбъект();
// Проверка (Domain)
ЗаказПокупателя.ПроверитьКорректность(Заказ);
// Проведение
ОтметитьНаПроведение(Заказ);
Заказ.Записать(РежимЗаписиДокумента.Проведение);
// Регистрация движений (Infrastructure)
РегистрацияДвижений(Заказ);
КонецПроцедуры
Процедура РегистрацияДвижений(Заказ) Экспорт
// Выручка
Для Каждого Строка Из Заказ.Товары Цикл
Движение = Движения.Выручка.Добавить();
Движение.ВидДеятельности = Заказ.ВидДеятельности;
Движение.Сумма = Строка.Сумма;
КонецЦикла;
// Резерв
Для Каждого Строка Из Заказ.Товары Цикл
Движение = Движения.Резерв.Добавить();
Движение.Товар = Строка.Товар;
Движение.Склад = Строка.Склад;
Движение.Количество = Строка.Количество;
КонецЦикла;
КонецПроцедуры
// ===== PRESENTATION LAYER =====
Модуль формы ЗаказПокупателя
Процедура КомандаПровести(Команда) Экспорт
Попытка
СервисЗаказов.ПроводитьЗаказ(Объект.Ссылка);
Сообщить("Заказ проведён");
Исключение
Сообщить("Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Шаг 3.2 — Определить точки расширяемости
// Для каждого ключевого момента — точка расширения
Общий модуль "РасширенияЗаказов" (для расширений)
// До проведения
Процедура ПредПроведением(ЗаказСсылка) Экспорт
// Здесь может добавить расширение свою логику
КонецПроцедуры
// После проведения
Процедура ПослеПроведения(ЗаказСсылка) Экспорт
// Например, отправить уведомление
КонецПроцедуры
Фаза 4: Реализация
Шаг 4.1 — Начните с модулей документа
// Модуль документа (минимум)
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения) Экспорт
// Только базовая валидация
Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
ЗаказПокупателя.ПроверитьКорректность(ЭтотОбъект);
КонецЕсли;
КонецПроцедуры
Процедура ПередПроведением(Отказ, РежимПроведения) Экспорт
РасширенияЗаказов.ПредПроведением(Ссылка);
КонецПроцедуры
Шаг 4.2 — Напишите тесты перед кодом
// Тесты должны предшествовать реализации
Процедура Тест_ПроверитьКорректность() Экспорт
// Тест 1: Заказ без товаров должен быть отклонён
Заказ = Новый ДокументОбъект.ЗаказПокупателя;
ПопыткаПроверки = Попытка
ЗаказПокупателя.ПроверитьКорректность(Заказ);
КонецПопытки;
Ассерт.Ошибка(ПопыткаПроверки, "Должна быть ошибка");
КонецПроцедуры
Процедура Тест_РассчитатьСумму() Экспорт
Заказ = СоздатьТестовыйЗаказ();
Сумма = ЗаказПокупателя.РассчитатьСумму(Заказ);
Ассерт.Равны(Сумма, 15000, "Сумма должна быть 15000");
КонецПроцедуры
Фаза 5: Документирование
Создайте техническую спецификацию:
// Документ: ТехСпека для подсистемы Заказы
1. Назначение
Подсистема предназначена для учёта заказов покупателей
2. Документы
- ЗаказПокупателя: Основной документ
3. Жизненный цикл
[диаграмма переходов состояний]
4. Регистры
- РегистрНакопления.Выручка
- РегистрНакопления.Резерв
5. Точки расширения
- РасширенияЗаказов.ПредПроведением
- РасширенияЗаказов.ПослеПроведения
6. Архитектура
[диаграмма слоёв]
Ключевые принципы
1. DDD (Domain-Driven Design)
- Начните с бизнеса, не с кода
- Язык бизнеса → язык кода
2. Onion Architecture
- Зависимости только инward
- Тестируемость на каждом слое
3. SOLID принципы
- Single Responsibility: каждый модуль одну задачу
- Open/Closed: расширяемость через точки расширения
- Dependency Inversion: сервисы, не прямые вызовы
4. Test-Driven Development
- Тесты перед кодом
- Минимум 80% покрытие
5. Документирование
- Техническая спецификация
- Точки расширения задокументированы
Типичные ошибки, которых нужно избежать
❌ Пытаетесь создать идеальную архитектуру сразу
✓ Начните с простого, потом рефакторьте
❌ Смешиваете Business Logic в модуле документа
✓ Выносите в отдельные модули (Services, Domain)
❌ Не пишете тесты
✓ Тесты перед кодом (TDD)
❌ Не документируете решения
✓ ТехСпека и архитектурные диаграммы обязательны
❌ Усложняете сверх меры
✓ KISS: начните простым решением
Итоговый чеклист
- Жизненный цикл документа определён
- Справочники спроектированы
- Структура документа утверждена
- Регистры идентифицированы
- Архитектура разбита на слои
- Точки расширения определены
- Написаны первые тесты
- Техническая спецификация создана
- Code review перед реализацией
- Покрытие тестами > 80%
Правильное проектирование подсистемы с документами — это инвестиция в качество и поддерживаемость системы на годы вперёд. Потратьте время на анализ и проектирование — это окупится многократно.