⟨/⟩ Ntr/50_Domain/EnergyProfileCollectionTaskModel/EnergyProfileCollectionTask.cs

107 строк · в начало

using System;
using Rugrid.Sdaid.Notation.Documents;

using OrgObject = Rugrid.Sdaid.Epas.Ntr.Domain.OrgObjectModel.OrgObject;
using TaskStatus = Rugrid.Sdaid.Epas.Ntr.Domain.Reference.SysReference.TaskStatus;

namespace Rugrid.Sdaid.Epas.Ntr.Domain.EnergyProfileCollectionTaskModel
{
    /// <summary>
    /// Доменная сущность. Перенесено дословно из ntr-01/domain/energy-profile-collection-task-model/energy-profile-collection-task.md.
    /// </summary>
    public class DOC_EnergyProfileCollectionTask : IDomainEntityDocument, IHasStructuralLinks, IFolder<NtrDomainFolder>
    {
        public SdaidLink[] Links => new[]
        {
            Rel.Uses<Rugrid.Sdaid.Epas.Ntr.Domain.BuildingModel.DOC_Building>(),
            Rel.Uses<Rugrid.Sdaid.Epas.Ntr.Domain.EnergyProfileModel.DOC_EnergyProfile>(),
            Rel.Uses<Rugrid.Sdaid.Epas.Ntr.Domain.OrgObjectModel.DOC_OrgObject>(),
            Rel.Uses<Rugrid.Sdaid.Epas.Ntr.Domain.Reference.SysReference.DOC_EnergyProfileStatus>(),
            Rel.Uses<Rugrid.Sdaid.Epas.Ntr.Domain.Reference.SysReference.DOC_TaskStatus>(),
        };

        public static string _refName = "Задание на сбор энергопрофиля (сущность)";

        public string Name => "Задание на сбор энергопрофиля (сущность)";

        public string Description => "Алиасы: Задание на сбор энергопрофиля (сущность). parents: [energy-profile-collection-task-diagram].";

        public string Version => "1.0";
        public string Status => "accepted";
        public string[] Comments => new string[0];

                public Type Entity => typeof(EnergyProfileCollectionTask);

        public static string Body = """"

**Поведение:**

- Дата начала / окончания сбора - информационные поля. Пользователь сам устанавливает / снимает флаг "Сбор завершён". Флаг должен определять "обработка_завершена" связанных Энергопрофилей. 
- "Создать энергопрофили по заданию" - вызов операции создания энергопрофиля для каждого здания организационного объекта за отчётный период.

**Операция "Создать энергопрофили по заданию":**

1. **Область зданий.** Выбираются все [[../building-model/building|Здания]], у которых `nav_id` входит в поддерево [[../org-object-model/org-object|Организационного объекта]] задания: сам узел `task.org_object_id` и все нижестоящие по иерархии (Компания → Исполнительный аппарат / МЭС → ПМЭС → Подстанция). Здания, привязанные к оргобъектам вне этого поддерева, не участвуют.
2. **Период эксплуатации здания** (`start_date` / `finish_date`) **не** учитывается на этапе создания профилей. Возможное ужесточение (фильтрация по пересечению отчётного периода задания и периода эксплуатации здания) — отложено.
3. **Уникальность.** На пару `(task_id, building_id)` создаётся **один** [[../energy-profile-model/energy-profile|Энергопрофиль]]. Если для такой пары профиль уже существует — он **не пересоздаётся** и его поля **не меняются**. Ничего не удаляется.
4. **Идемпотентность.** Повторный запуск операции для того же задания безопасен: уже существующие профили остаются без изменений, новые создаются только для зданий, у которых профиля в рамках этого задания ещё не было.
5. **Предусловие по статусу задания.** Если `task_status.code = "completed"` (Сбор завершён), запуск операции **запрещён** — возвращается ошибка.
6. **Начальные значения создаваемого Энергопрофиля:**
   - `energy_profile_collection_task_id = task.id`;
   - `building_id = b.id`;
   - `name` — **не сохраняется**: формируется при чтении / на UI по формуле из домена (см. [[../energy-profile-model/energy-profile|Энергопрофиль]]). При создании профиля не записывается.
   - все ссылки на модели потребления (`normative_calculation_model_id`, `standard_calculation_model_id`, `technological_calculation_model_id`, `custom_calculation_model_id`) — `null` (заполняются отдельной операцией);
   - `status_id` — статус [[../reference/sys-reference/energy-profile-status|Статус энергопрофиля]] с `code = "in_progress"` (Формируется).
"""";

    }

    /// <summary>
    /// Доменная сущность «Задание на сбор энергопрофиля (сущность)».
    /// Класс — источник структуры: таблица свойств и диаграмма связей на странице документа
    /// строятся генератором по нему. Прозу и разбор ведёт документ DOC_EnergyProfileCollectionTask.
    /// </summary>
    [DomainEntity]
    public class EnergyProfileCollectionTask
    {
        /// <summary>Идентификатор записи</summary>
        [DomainField(Alias = "id", RequiredOnCreate = true, Immutable = true)]
        public Guid Id { get; set; }

        /// <summary>Организационный объект</summary>
        [Relation]
        [DomainField(Alias = "nav_id", RequiredOnCreate = true, Immutable = true)]
        public OrgObject? Nav { get; set; }

        /// <summary>Наименование</summary>
        [DomainField(
            Alias = "name",
            RequiredOnCreate = true,
            Calculated = "Да, вычисляется при чтении / на UI; не хранится. Маска: $\"{{FK → Организационный объект. Наименование} ({Год начала отчётного периода}-{Год окончания отчётного периода})\" Пример: ПАО «Россети» (2026-2026)"
        )]
        public string? Name { get; set; }

        /// <summary>Год начала отчётного периода</summary>
        [DomainField(Alias = "report_period_start", RequiredOnCreate = true, Default = "Текущий год")]
        public int ReportPeriodStart { get; set; }

        /// <summary>Год окончания отчётного периода</summary>
        [DomainField(Alias = "report_period_finish", RequiredOnCreate = true, Default = "Текущий год")]
        public int ReportPeriodFinish { get; set; }

        /// <summary>Дата начала сбора данных</summary>
        [DomainField(Alias = "collect_period_start", RequiredOnCreate = true, Default = "Текущая дата")]
        public DateTime CollectPeriodStart { get; set; }

        /// <summary>Дата окончания сбора данных</summary>
        [DomainField(Alias = "collect_period_finish", RequiredOnCreate = true, Default = "Текущая дата + месяц")]
        public DateTime CollectPeriodFinish { get; set; }

        /// <summary>Статус</summary>
        [Relation]
        [DomainField(Alias = "status_id", RequiredOnCreate = true, Default = "false", Description = "устанавливается пользователем")]
        public TaskStatus? Status { get; set; }
    }

}