В практике автоматизации бизнес-процессов часто возникает требование от отделов продаж: обеспечить, чтобы пакет документов по одной сделке (Счет на оплату, Акт/Накладная и Счет-фактура) имел одинаковый номер. С точки зрения «чистой» методологии 1С и бухгалтерского учета, это не является обязательным требованием, и разные виды документов обычно имеют независимые нумераторы. Однако, для удобства коммуникации с клиентами («Оплатите счет №500 по акту №500»), такая задача ставится программистам регулярно.
В этой статье мы подробно разберем, как реализовать механизм единой нумерации в конфигурации «1С:Бухгалтерия предприятия 3.0» (БП 3.0), не нарушив при этом типовые механизмы и не создав хаос в учете. Мы рассмотрим технические ограничения, способы их обхода и приведем примеры кода.
Суть задачи, которую мы решаем: существует некое автоматизированное рабочее место (АРМ) менеджера или специальный документ «Договор-заявка». При нажатии кнопки пользователь хочет программно создать сразу три документа:
Для оптимизации этого процесса часто используется пакетное формирование накладных и счетов-фактур на основании счета покупателю, что позволяет избежать ручного ввода данных. Главное условие: номера всех трех документов должны совпадать. Если номер 105 присвоен Реализации, то и Счет, и СФ должны быть №105.
Прежде чем писать код, давайте проанализируем, как работает нумерация в современных конфигурациях на базе БСП (Библиотеки Стандартных Подсистем), к которым относится и БП 3.0. В системе 1С нумерация базируется на следующих принципах:
ПрефиксИБ + ПрефиксОрганизации + СобственноНомер.В некоторых случаях стандартная логика может быть изменена, например, когда требуется нумерация счетов-фактур и документов реализации по дате создания. Если мы просто попытаемся программно присвоить Док.Номер = "0000-000105", система может либо перезаписать его при записи, либо выдать ошибку неуникальности.
Самый надежный способ с точки зрения платформы 1С — это создание единого объекта метаданных Нумератор. Он требует включения возможности изменения конфигурации, но гарантирует, что 1С сама будет следить за уникальностью в пределах группы документов.
Как это сделать:
НумераторПродаж.РеализацияТоваровУслуг, СчетНаОплатуПокупателю, СчетФактураВыданный.НумераторПродаж.Плюсы подхода: Сквозная нумерация поддерживается платформой. Минусы подхода: Вы меняете типовую структуру метаданных. Кроме того, Счет №6 после Реализации №5 нарушит условие «одинаковых номеров», так как они будут идти последовательно, а не синхронно.
Более гибкий подход — это программное назначение номера в момент создания. Нам необходимо выбрать «Ведущий» документ (обычно это Реализация), а остальные документы (Счет и СФ) сделаем «Ведомыми» — для этого подойдёт настройка правил создания связанных документов.
Чтобы автоматически созданные документы не конфликтовали с ручным вводом, выделите для них отдельное пространство номеров. Для этого удобно использовать готовое расширение, которое обеспечит установку префикса у документов по условию.
Например, если организация имеет префикс «МС», то обычные документы будут «МС00-00001». Документы по заявкам могут иметь префикс «МСДЗ-00001». В более специфических случаях может потребоваться префикс даты в номерах счетов и реализаций или даже полная замена, когда используется дата вместо префикса документа.
В БП 3.0 механизм нумерации срабатывает в момент записи. Чтобы вмешаться в этот процесс, лучше всего использовать расширение конфигурации, реализующее алгоритм, при котором происходит автоматическая установка номера счета-фактуры как у реализации.
В событии ПриУстановкеНовогоНомера мы можем отказаться от стандартной генерации:
Процедура Расш_ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
// Проверяем, что документ создается на основании нашей Реализации
Если ЗначениеЗаполнено(ДокументОснование)
И ТипЗнч(ДокументОснование) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
НомерОснования = ДокументОснование.Номер;
Если ЗначениеЗаполнено(НомерОснования) Тогда
СтандартнаяОбработка = Ложь;
ЭтотОбъект.Номер = НомерОснования;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
При обработке нажатия кнопки мы должны гарантировать целостность данных через транзакции:
Процедура СоздатьПакетДокументов(ДанныеЗаявки)
УстановитьПривилегированныйРежим(Истина);
НачатьТранзакцию();
Попытка
// 1. Создаем и записываем Реализацию
НовРеализация = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
// ... заполнение ...
НовРеализация.УстановитьНовыйНомер(ЭтотОбъект.Организация.Префикс + "ДЗ-");
НовРеализация.Записать(РежимЗаписиДокумента.Проведение);
ЗафиксированныйНомер = НовРеализация.Номер;
// 2. Создаем Счет-фактуру
НовСчетФактура = Документы.СчетФактураВыданный.СоздатьДокумент();
НовСчетФактура.ДокументОснование = НовРеализация.Ссылка;
НовСчетФактура.Номер = ЗафиксированныйНомер;
НовСчетФактура.ОбменДанными.Загрузка = Истина;
НовСчетФактура.Записать(РежимЗаписиДокумента.Запись);
НовСчетФактура.ОбменДанными.Загрузка = Ложь;
НовСчетФактура.Записать(РежимЗаписиДокумента.Проведение);
// 3. Создаем Счет на оплату
НовСчет = Документы.СчетНаОплатуПокупателю.СоздатьДокумент();
НовСчет.Номер = ЗафиксированныйНомер;
НовСчет.ОбменДанными.Загрузка = Истина;
НовСчет.Записать(РежимЗаписиДокумента.Запись);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить("Не удалось создать пакет документов: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Если номер уже занят, база данных выдаст ошибку уникальности индекса. Именно поэтому мы используем Попытка ... Исключение. Чтобы минимизировать коллизии, используйте уникальный префикс (например, "ДЗ"). Вероятность того, что кто-то вручную введет такой номер, крайне мала.
Если организация перейдет на использование УПД (статус 1), то потребность в синхронизации номеров между Реализацией и Счетом-фактурой отпадет автоматически. В этом случае номер Счета-фактуры фактически равен номеру Реализации, и вам останется только синхронизировать номер Счета на оплату с номером УПД.
Для реализации единой нумерации в БП 3.0 наиболее эффективным является следующий подход:
ОбменДанными.Загрузка = Истина при первой записи зависимых документов, либо внедрите расширение с программным перехватом номера.