Как правильно спроектировать систему начисления и оплаты коммунальных услуг в 1С 7.7?

Программист 1С v7.7 Управленческий учет Сфера услуг, туризм и социальный сектор
← На главную

При разработке учетной конфигурации для сферы ЖКХ и коммунальных расчетов начинающие разработчики часто совершают типовую ошибку: создают отдельные справочники, документы и регистры под каждый вид услуги (газ, вода, электроэнергия). Это приводит к неоправданному разрастанию структуры метаданных, усложнению программного кода, форм отчетов и трудностям при добавлении новых услуг.

Разберем по шагам, как грамотно построить архитектуру решения на платформе 1С 7.7, организовать структуру регистров, настроить хранение тарифов и реализовать разграничение доступа для пользователей.

Оптимизация структуры метаданных

Вместо пложения однотипных объектов метаданных (ОплатаГаза, ОплатаЭлектроэнергии, ОплатаВоды) спроектируем универсальную модель. Рассмотрим основные элементы структуры:

  1. Справочник Абоненты (или ЛицевыеСчета): содержит данные о плательщиках. Для привязки к сеансу пользователя добавим реквизит Логин (тип «Строка»).
  2. Справочник Услуги: содержит перечень коммунальных услуг (водоснабжение, газоснабжение, электроэнергия, отопление).
  3. Справочник Тарифы: цены на услуги. Для хранения тарифов используем периодический реквизит Цена (или Тариф), так как стоимость услуг регулярно меняется со временем.
  4. Документ ВводПоказанийСчетчиков: фиксирует текущие показания приборов учета по абоненту и услуге, рассчитывает объем потребления и формирует сумму начисления.
  5. Документ ОплатаУслуг: фиксирует факт поступления денежных средств от абонента в разрезе конкретной услуги или по общему сальдо.

Проектирование регистров накопления

Проанализируем структуру регистров. Для решения задачи начисления и взаиморасчетов бухгалтерский план счетов и проводки не всегда удобны, так как баланс в рамках простой подсистемы не сойдется. Оптимальным решением является использование механизма оперативного учета (регистров накопления).

Для корректного учета нам потребуются два регистра типа «Остатки»:

  1. Регистр ПоказанияСчетчиков:
    • Измерения: Абонент (Справочник.Абоненты), Услуга (Справочник.Услуги).
    • Ресурсы: Значение (Число) — фиксирует текущее конечное показание прибора учета.
  2. Регистр Взаиморасчеты:
    • Измерения: Абонент, Услуга.
    • Ресурсы: Сумма (Число) — положительный остаток отражает задолженность абонента, отрицательный — переплату (аванс).

Выясним логику движений регистров при проведении документов:

  1. Документ ВводПоказанийСчетчиков:
    • Получает предыдущее показание из регистра ПоказанияСчетчиков на момент документа.
    • Вычисляет расход: Расход = ТекущееПоказание - ПредыдущееПоказание.
    • Получает актуальный тариф на дату документа: Тариф = СпрТарифы.Цена.Получить(ДатаДок).
    • Рассчитывает сумму: СуммаНачисления = Расход * Тариф.
    • Делает движение по регистру ПоказанияСчетчиков с новым значением.
    • Делает Приход (увеличение задолженности абонента) в регистр Взаиморасчеты на сумму начисления.
  2. Документ ОплатаУслуг:
    • Делает Расход (уменьшение задолженности абонента) в регистр Взаиморасчеты на сумму платежа.

Реализация расчета начислений в модуле проведения

Посмотрим на пример логики проведения документа ввода показаний в модуле документа 1С 7.7:


Процедура ОбработкаПроведения()
    // Получаем предыдущие показания по регистру
    РегПоказания = СоздатьОбъект("Регистр.ПоказанияСчетчиков");
    РегПоказания.УстановитьЗначениеФильтра("Абонент", Абонент);
    РегПоказания.УстановитьЗначениеФильтра("Услуга", Услуга);
    РегПоказания.Остатки(ТекущийДокумент(), 1);
    
    ПредыдущееПоказание = РегПоказания.Значение;
    
    Если НовоеПоказание < ПредыдущееПоказание Тогда
        Сообщить("Новое показание не может быть меньше предыдущего!");
        НеПроводить();
        Возврат;
    КонецЕсли;
    
    Расход = НовоеПоказание - ПредыдущееПоказание;
    
    // Получение периодического тарифа на дату документа
    Тариф = Услуга.Тариф.Получить(ДатаДок);
    СуммаНачисления = Расход * Тариф;
    
    // Движение по приборам учета
    Регистр.ПоказанияСчетчиков.Абонент = Абонент;
    Регистр.ПоказанияСчетчиков.Услуга  = Услуга;
    Регистр.ПоказанияСчетчиков.Значение = НовоеПоказание;
    Регистр.ПоказанияСчетчиков.ДвижениеРасходВыполнить();
    
    // Движение по взаиморасчетам (увеличение долга абонента)
    Регистр.Взаиморасчеты.Абонент = Абонент;
    Регистр.Взаиморасчеты.Услуга  = Услуга;
    Регистр.Взаиморасчеты.Сумма   = СуммаНачисления;
    Регистр.Взаиморасчеты.ДвижениеПриходВыполнить();
КонецПроцедуры

Ограничение доступа и имитация личного кабинета

В платформе 1С 7.7 отсутствует механизм RLS (Record Level Security), который позволяет на уровне СУБД фильтровать данные по правам доступа. Поэтому разграничение доступа для абонентов реализуется программными методами интерфейса.

Разберем основные шаги по изоляции данных абонента:

  1. Определение текущего абонента: в глобальном модуле или при открытии форм используем функцию ИмяПользователя() и находим соответствующий элемент в справочнике Абоненты по совпадению с реквизитом Логин.
  2. Автозаполнение и блокировка реквизитов: в процедуре ПриОткрытии() документов оплаты и ввода показаний автоматически подставляем найденного абонента и программно отключаем доступность поля ввода для исключения выбора другого лицевого счета.
  3. Защита при записи: в процедуре ПриЗаписи() обязательно проверяем соответствие реквизита Абонент текущему авторизованному пользователю.
  4. Фильтрация журналов документов: в формах журналов и списков применяем метод УстановитьОтбор("Абонент", ТекАбонент), скрывая записи других пользователей, а также отключаем стандартные панели навигации и меню «Операции» для профиля абонента.

Посмотрим на пример процедуры инициализации формы документа:


Процедура ПриОткрытии()
    Если НазваниеНабораПрав() = "Абонент" Тогда
        СпрАбоненты = СоздатьОбъект("Справочник.Абоненты");
        Если СпрАбоненты.НайтиПоРеквизиту("Логин", ИмяПользователя(), 1) = 1 Тогда
            Если Выбран() = 0 Тогда
                Абонент = СпрАбоненты.ТекущийЭлемент();
            КонецЕсли;
            Форма.Абонент.Доступность(0);
        Иначе
            Предупреждение("Пользователь не сопоставлен с карточкой абонента!");
            СтатусВозврата(0);
            Возврат;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Использование единых документов и связанных регистров позволяет создать масштабируемую систему, пригодную для добавления любых видов коммунальных услуг без изменения базовой структуры конфигурации.

← На главную