D09 · Модель данных: учёт договоров на платные образовательные услуги¶
Платформонезависимая модель данных среза D09 «учёт договоров». Описывает сущности, их поведение, связи, инварианты и ключевые алгоритмы. Реализация на конкретной платформе (виды объектов, регистры) — вне рамок фреймворка (см. репозиторий-референс реализации).
1. Несущие принципы¶
Модель построена на событийной парадигме — той же, что и учебный контур (D05), поэтому контуры стыкуются без швов:
- Состояние меняется только событием (приказом). Прямого редактирования данных нет.
- Факт неизменяем. Начисление, платёж, возврат, ценовая запись после возникновения не правятся и не удаляются.
- Коррекция — встречная запись (сторно), а не правка. Ошибочный факт гасится сторно-записью со ссылкой на исходную; нетто вычисляется.
- Изменения — только вперёд. Условия меняются новой версией плана с даты вступления; периоды, обязательство по которым уже возникло, заморожены.
- Финансовый контур синхронен с академическим. Обязательство возникает по событию начала оплачиваемого периода, а не по календарю.
- Система фиксирует, а не решает. Считает задолженность и сигнализирует о сроках; решение о льготе, рассрочке, взыскании — за人ответственным подразделением.
Две оси, на которых держится модель¶
- План ↔ Факт. План — договор, график, плановая сумма, цена договора (намерение, может версионироваться). Факт — начисления, платежи (реальность, заморожен).
- Версии плана во времени. Договор — версия 1; каждое изменение условий (допсоглашение, индексация, приказ) — новая версия, действующая вперёд. Действующий план на дату = договор + все версии с датой вступления ≤ этой даты.
2. Сущности¶
Сгруппированы по контурам. Полные академические сущности (траектория, зачётная книжка, перезачёт) принадлежат D05 — здесь только граница.
2.1 НСИ и правила¶
| Сущность | Назначение | Ключевые атрибуты | Связи |
|---|---|---|---|
| Образовательная услуга | Что продаётся; точка схождения академики, цены и политики | программа, форма возмещения, вид образования, тип шаблона | ← Договор; 1→N Цена |
| Цена услуги | Цена услуги за конкретный период обучения | услуга, период, сумма, единица, дата вступления, основание-приказ | неизменяема; история цен |
| Вид образования | Носитель каскада учётной политики | наименование | ← Услуга, Политика |
| Учётная политика | Конфигурируемые параметры расчёта | уровень каскада, параметр, значение, дата действия | каскад: услуга > вид > организация |
| Тип / версия шаблона договора | Версионируемый текст договора | тип, дата вступления, текст | слепок в версии плана v1 |
| Категория обучающихся | Основание льготы (отдельное измерение) | тип, режим применения, модификатор, условие сохранения, срок действия | ← начисление |
| Период обучения | Измерение времени учёбы | тип (год/семестр), границы | используется в ценах, графике, начислениях |
Цена всегда периодная. «Целиком» — вырожденный случай одного периода: короткий курс = одна ценовая запись, длинная программа = по записи на семестр/год. Полная стоимость договора — не отдельный реквизит, а сумма периодных цен. Переопределение цены — на двух уровнях: в прейскуранте (новая ценовая запись, для будущих договоров) и в договоре (новая версия плана, для конкретного). В обоих случаях переопределяется конкретный период конкретной услуги — поэтому длинная услуга индексируется частями, а короткая целиком.
Три режима применения льготы (параметр учётной политики): - Снижение цены в договоре — скидка отражается в приложении к договору; начисление идёт по сниженной цене с первого дня. - Поверх при расчёте начисления — цена в договоре базовая; скидка применяется при каждом начислении. Гибче при временных льготах. - Условное с триггером — льгота включается при наступлении условия (напр. средний балл ≥ 4.5 по итогам сессии → скидка на следующий семестр). Условие сохранения проверяется по событию из D04; при несоблюдении скидка снимается новой версией плана.
Правило комбинирования скидок (если у обучающегося несколько категорий) — конфигурируется политикой: суммируются / берётся максимальная / применяется по приоритету вида. Не настроено явно → «максимальная» как безопасный дефолт.
2.2 Договорной контур¶
| Сущность | Назначение | Ключевые атрибуты | Связи |
|---|---|---|---|
| Договор | Долгоживущая ось денег; план v1 | номер, обучающийся, услуга, дата начала обучения, стороны | 1→N Версия плана; ← все факты |
| Стороны договора | Роли, которые могут принадлежать разным лицам | обучающийся, заказчик, плательщик(и) [± доли] | ← платёж, первичка |
| Версия плана | Изменение условий (v1=заключение, v2…n) | договор, № версии, дата вступления, основание (ДС/индексация/приказ), график [период, сумма], слепок шаблона (v1), категория | источник суммы для начисления |
| График по периодам | Производный план: когда и сколько ожидается | период, сумма (из периодных цен) | снимок на версию; полная сумма — итог |
Договор — предусловие зачисления: зачисление невозможно без заключённого договора (при этом договор может быть ещё не оплачен). Сам договор не редактируется — изменяется только новой версией плана. Версия умеет не только переоценивать будущие периоды, но и добавлять период (повторное обучение); полная сумма как итог графика растёт сама.
Цена — в приложении к договору, не в теле. Тело договора фиксирует услугу, стороны и общие условия (не меняется). Приложение содержит график платежей по периодам. При изменении цены (индексация, допсоглашение) оформляется новое приложение — тело договора остаётся неизменным. Это следствие из «версии плана»: v1 = тело + приложение v1; v2 = тело + приложение v2; слепок шаблона фиксируется один раз при подписании v1.
2.3 Финансовый контур¶
| Сущность | Назначение | Ключевые атрибуты | Поведение |
|---|---|---|---|
| Начисление | Обязательство за период (факт) | договор, период, сумма, версия-источник, событие-основание, дата вступления триггера | возникает по триггеру; снимает сумму с версии на дату вступления; блокируется |
| Платёж | Поступление денег (факт) | плательщик, договор (может быть пуст), сумма, дата, источник/инструмент, внешний ИД | идемпотентен по внешнему ИД |
| Распределение | Привязка платежа к начислениям | платёж, начисление, сумма | гасит долг; FIFO по умолчанию, в пределах договора |
| Возврат средств | Движение денег обратно (не сторно) | договор, плательщик, сумма, основание, инициатор | отдельная неизменяемая запись |
| Ожидаемое поступление | Гарантия (маткапитал/кредит) | договор, сумма, источник, статус, срок | подавляет санкции, долг не гасит |
| Сторно | Встречная запись к ошибочному факту | исходный факт, причина | один факт — одно действующее сторно |
| Академическое событие | Сигнал из D05 (триггер) | договор/обучающийся, тип, дата вступления, дата приказа, внешний ИД | идемпотентно; не доверяется вслепую |
Платёж сам по себе не гасит долг — его гасит распределение. Платёж поступает на «кошелёк» плательщика; распределение переносит сумму в «оплачено» против конкретных начислений; возврат выводит деньги наружу. Платёж без распределения допустим (суспенс). Задолженность = начислено − оплачено — производная величина, не хранится.
Три задолженности — одна мета-механика¶
Доклад §5 (доклад в inbox: 2026-07-06-doklad-digital-infrastructure.pdf) фиксирует
единство природы:
- Дисциплинарная (D04) — из учебных событий внутри дисциплины (пропуск, несданный модульный контроль, незащищённая лабораторная)
- Академическая (D04) — из аттестационных учебных событий уровня программы (экзамен, курсовая, ГИА); работает ФЗ-273 ч. 5 ст. 58
- Финансовая (D09, эта сущность) — из административных событий D05 (приказы, запускающие оплачиваемый период по договору)
Одна мета-механика: событие → обязательство → запись. Задолженность каждого вида — вычисляемое состояние обязательства (существует и не закрыто положительной записью).
Разные источники событий: дисциплинарная и академическая — из учебных событий D04; финансовая — из административных событий D05 (приказов). Финансовое обязательство не порождается фактом проведения занятий D04 напрямую — оно порождается приказом, запускающим оплачиваемый период (зачисление / перевод / условный перевод / повторное обучение).
Учебный контур поставляет финансовому «оказанный объём услуги» (журнал D04) только для расчёта возврата при расторжении — не для запуска начислений.
3. Жизненный цикл договора¶
Состояния: Проект → Заключён → Действует → (Приостановлен) → Расторгнут / Исполнен.
- Проект → Заключён — подписание договора.
- Проект → Аннулирован — зачисление не состоялось (начислений не было; не путать с расторжением).
- Заключён → Действует — приказ о зачислении; дата начала обучения = триггер первого начисления.
- Действует — события начала периода (перевод / условный перевод / повтор) порождают начисления; изменения условий создают новые версии плана; принимаются платежи.
- Действует ↔ Приостановлен — академотпуск замораживает новые начисления (долг сохраняется); возврат из отпуска возобновляет.
- → Расторгнут — отчисление; запускается алгоритм возврата.
- Расторгнут → Действует — отмена приказа об отчислении (сторно события); начисления восстанавливаются только за реально оказанные периоды, не автоматически.
- → Исполнен — выпуск.
Две оси закрытия. Академическое расторжение прекращает начисления, но финансово договор остаётся открытым, пока сальдо ≠ 0 (идёт взыскание долга или оформляется возврат). Финансовое закрытие — отдельное событие при сальдо = 0.
4. Стык с академическим контуром (D05)¶
Терминологическое уточнение. «Академическое событие» в D09 — это приказ D05 (документное событие: зачисление, перевод, отпуск, отчисление). НЕ путать с «учебным событием» D04 (генератор обязательств: занятие, экзамен, модульный контроль). Это две разные сущности в двух разных доменах — одинаковое слово «событие» используется в двух смыслах. См. D04/GUIDE.md, раздел «Два слоя понятия «событие»».
Финансовое обязательство порождается административным событием D05 (приказом), не учебным событием D04. Наступил семестр по приказу о переводе → обязательство по договору; сам факт проведения занятий D04 → оказанный объём услуги (для расчёта возврата при расторжении, D09-P05), но не порождает начислений.
Обязательства следуют за приказами. Реакция финансового контура однозначна для каждого типа события:
| Академическое событие (D05) | Реакция финансового контура |
|---|---|
| Зачисление | Требует существующего договора; дата начала → 1-е начисление |
| Перевод / условный перевод | Триггер начисления следующего периода |
| Оставление на повторное обучение | Версия плана добавляет период; триггер начисления |
| Академотпуск | Договор → «Приостановлен»; начисления заморожены |
| Возврат из отпуска | Возобновление; смена редакции учебного плана → смена услуги |
| Отчисление | Договор → «Расторгнут»; алгоритм возврата; причина → правило возврата |
| Отмена отчисления | Реверс статуса; начисления только за оказанное |
| Восстановление | Новый договор — новая финансовая ветка |
| Нет перевода (академдолг) | Нет события начала периода → нет начисления |
Событие датируется датой вступления в силу (не датой приказа); приказы часто оформляются задним числом, поэтому событие может прийти позже и с ранней датой — это обрабатывается через сторно и повторный расчёт, без правки факта.
5. Инварианты¶
То, что система запрещает независимо от интерфейса и действий пользователя — граница между «корректной моделью» и «системой, которую нельзя сломать».
Факт и неизменяемость - Факт не редактируется и не удаляется; изменение — только встречной записью (сторно). - Сторно ссылается ровно на один факт; повторное сторно уже сторнированного запрещено. - Сторно-запись сама не сторнируется и не редактируется.
Деньги и распределение - Сумма распределений платежа ≤ суммы платежа. - Распределение ссылается на существующее несторнированное начисление. - Распределение — строго внутри своего договора; междоговорное движение — только явный перенос. - Платёж без распределения допустим (суспенс); начисление без оплаты допустимо (долг). - Отрицательный долг из дубля платежа невозможен (идемпотентность).
План и версии - Версия плана не изменяет период, чей триггер уже сработал. - Версии упорядочены; при равной дате вступления порядок — по номеру. - Начисление снимает сумму с версии, действующей на дату вступления триггера.
События - Один приказ = одно финансовое событие (идемпотентность). - Платёж уникален по внешнему идентификатору. - Событие-триггер обязано ссылаться на договор или обучающегося.
Жизненный цикл - Переходы статусов — только по разрешённой матрице. - В «Проекте» и «Приостановлен» новые начисления не порождаются. - Договор не закрывается финансово, пока сальдо ≠ 0.
Закрытый период - Факт в закрытом периоде не сторнируется и не изменяется автоматически. - Коррекция закрытого периода — управляемой записью в текущем открытом периоде, без каскадного пересчёта прошлого. - Ценовая запись, на которую сослалось начисление, не сторнируется.
6. Ключевые алгоритмы¶
Отчисление и возврат за незавершённый период. Один алгоритм на три случая (отчисление в середине периода, после условного перевода, частично оплаченный период): 1. начисление незавершённого периода сторнируется и заменяется новым — на фактически оказанный объём (по единице расчёта возврата); 2. начисления не начавшихся периодов сторнируются в ноль; 3. затем сверка с распределёнными платежами: переплата → возврат, недоплата → долг. Если единица расчёта деятельностная (ЗЕ, занятие), а данных нет — расчёт блокируется с сигналом (либо параметром падает на календарное правило).
Перераспределение при сторно начисления. Сторно освобождает распределения; платежи возвращаются в нераспределённые и FIFO прогоняется заново по актуальным начислениям.
Единица расчёта возврата определяет источник истины об оказанном объёме: календарная (день/месяц/период) → автомат (функция от дат); деятельностная (занятие/ЗЕ) → журнал.
Фиксация цены предоплатой — пропорционально оплаченной доле: оплаченная доля периода закрепляется по версии на дату платежа, неоплаченная индексируется при срабатывании триггера.
7. ERD (mermaid)¶
graph LR
PROG["Образовательная программа"] --> SVC["Образовательная услуга"]
SVC --> PRICE["Цена услуги (за период)"]
SVC --> POLICY["Учётная политика"]
PERSON["Физлицо"] --> STUD["Обучающийся"]
STUD --> DOG["Договор"]
STUD --> PROG
DOG --> VER["Версия плана v1..n"]
DOG --> SVC
VER --> SCHED["График по периодам"]
SCHED -.суммы из.-> PRICE
ORDER["Приказ (D05)"] ==>|триггер| ACCR["Начисление"]
ORDER -.статус.-> DOG
VER -->|сумма периода| ACCR
PAY["Платёж"] --> ALLOC["Распределение"]
ALLOC --> ACCR
REFUND["Возврат"] -.из кошелька.-> PAY
STORNO["Сторно"] -.встречная.-> ACCR
EXPECT["Ожидаемое поступление"] -.подавляет санкции.-> DOG
ACCR -.начислено − оплачено.-> DEBT["Задолженность (срез)"]
Полная концепция (фундамент, операционные алгоритмы, инварианты, карта стыков контуров) — в исходных материалах пакета. Реализация на 1С — в отдельном референсе, вне фреймворка.