Оцифровка информационных карт

Ограниченный контекст Версия: 0.1 draft

Ограниченный контекст Сервиса: общая схема данных и её границы. Внутри контекста язык единый — термин значит одно и то же во всех частях модели.

⟨/⟩ Исходник

1. Границы контекста

Сервис — один ограниченный контекст. Язык внутри него единый: шифр, документ, информационная карта, форма документа, пакет ввода значат одно и то же в любой части модели, и модель у них одна на всех. Поэтому схема данных тоже одна — она приведена ниже и охватывает все сущности Сервиса.

Настоящая граница контекста проходит снаружи, по стыку с АБИС. Там другая модель, другой владелец и другой язык: то, что в АБИС называется документом, — библиографическая запись со своей структурой. Обмен идёт через контракт — файл выгрузки на выходе, — а не прямым обращением к чужой модели.

Из этого следует состав контекста: сущность принадлежит Сервису, если Сервис её создаёт и изменяет. Исключений нет: чужих данных Сервис у себя не держит. Приём реестров из АБИС и привязка карты к экземпляру фонда в состав не входят — вместе с ними из модели ушёл экземпляр фонда, единственная сущность, которая была проекцией чужой записи.

2. Группировка сущностей

Сущности разложены по папкам по фазам жизненного цикла данных — это навигационная группировка внутри одного контекста, а не отдельные контексты: границ языка между папками нет, ссылки между сущностями прямые.

Папка Что содержит Кто порождает данные
Capture/ пакет ввода, кадры изображений, отклонения вида, значения полей пользователь при вводе и обработка
Processing/ области-источники на кадре автоматическая обработка
Cards/ информационная карта, документы карты и их атрибуты; виды документов с составом атрибутов, типы значений и формы создание карты по итогам проверки; справочная часть ведётся администратором
Export/ выгрузка: сформированный файл для АБИС и его состав создание карты; реже — администратор повторно
Access/ пользователи, группы, функции, ключи claim, токены сессии администратор (доступ) и вход/выход

Состав документа тоже описан парой: вид документа и его атрибуты — то, что бывает; документ карты и его атрибуты — то, что заполнено. Каждый уровень заполненного ссылается на свой уровень описания.

3. Схема данных

Диаграмма ниже строится генератором из самих классов: показаны все сущности контекста, их свойства и связи. Разойтись с моделью она не может — она из неё выведена.

Перечисления (источники кадра, состояния пакета, виды типов значений, происхождение значения, свойства ядра карты) на схему не выносятся: они описаны в документах тех сущностей, где используются.

Class diagram

classDiagram
    direction LR
    class SourceArea["Область-источник"] {
        <<ValueObject>>
        +Double X
        +Double Y
        +Double Width
        +Double Height
    }
    class CardExport["Выгрузка"] {
        <<Entity>>
        +Guid Id
        +DateTime CreatedAt
        +Guid CreatedByUserId
        +String FormatCode
        +String FileName
        +String StorageKey
        +ExportOrigin Origin
        +IReadOnlyList~InformationCard~ Cards
    }
    class CardDocument["Документ информационной карты"] {
        <<Entity>>
        +Guid DocId
        +Nullable~Guid~ ParentId
        +DocumentKind Kind
        +IReadOnlyList~CardDocument~ NestedDocuments
        +IReadOnlyList~CardDocumentAttribute~ Attributes
    }
    class CardDocumentAttribute["Атрибут документа карты"] {
        <<Entity>>
        +IReadOnlyList~String~ Values
        +Guid FilledByUserId
        +DateTime FilledAt
        +CardDocument Document
        +DocumentKindAttribute KindAttribute
        +ValueOrigin Origin
    }
    class InformationCard["Информационная карта"] {
        <<Entity>>
        +Guid Id
        +DateOnly Date
        +Guid SourcePacketId
        +String Shelf
        +String InventoryNumber
        +String Title
        +String Author
        +Nullable~Int32~ Year
        +DateTime CreatedAt
        +Guid CreatedByUserId
        +Nullable~DateTime~ ExportedAt
        +DocumentKind Kind
        +IReadOnlyList~CardDocument~ Documents
    }
    class AttributeValueType["Тип значения"] {
        <<Entity>>
        +Guid Id
        +String Code
        +String Name
        +String Constraints
        +ValueKind Kind
    }
    class DocumentForm["Форма документа"] {
        <<Entity>>
        +Guid Id
        +String Name
        +Boolean IsActive
        +DocumentKind DocumentKind
        +IReadOnlyList~FormPage~ Pages
    }
    class FormPage["Страница формы"] {
        <<ValueObject>>
        +Int32 Number
        +String Title
        +String FilledBy
        +IReadOnlyList~FormSection~ Sections
        +PageDetectionProfile Detection
    }
    class FormSection["Раздел формы"] {
        <<ValueObject>>
        +String Title
        +Int32 Order
        +IReadOnlyList~FormSection~ Sections
        +IReadOnlyList~FormField~ Fields
    }
    class FormField["Поле формы"] {
        <<Entity>>
        +Guid Id
        +String Caption
        +Int32 Order
        +DocumentKindAttribute KindAttribute
        +SourceArea Area
    }
    class DocumentKind["Вид документа"] {
        <<Entity>>
        +Guid DocId
        +Nullable~Guid~ ParentId
        +String DocKind
        +String Name
        +IReadOnlyList~DocumentKind~ NestedKinds
        +IReadOnlyList~DocumentKindAttribute~ Attributes
    }
    class DocumentKindAttribute["Атрибут вида документа"] {
        <<Entity>>
        +String Code
        +String Name
        +Boolean IsRequired
        +Int32 Order
        +DocumentKind DocumentKind
        +AttributeValueType ValueType
        +CardCoreField CoreField
    }
    class PageDetectionProfile["Профиль автоопознания страницы"] {
        <<Entity>>
        +Guid Id
        +Int32 GlobalHLines
        +Int32 GlobalVLines
        +SourceArea AnchorFrame
        +IReadOnlyList~DiscriminatorZone~ Zones
    }
    class DiscriminatorZone["Зона-различие"] {
        <<ValueObject>>
        +String Name
        +Int32 ExpectedHLines
        +Int32 ExpectedVLines
        +SourceArea Area
    }
    class ImageFrame["Кадр изображения"] {
        <<Entity>>
        +Guid Id
        +Int32 Order
        +String OriginalFileName
        +DateTime CapturedAt
        +String StorageKey
        +Boolean AcceptedForRecognition
        +String NormalizedStorageKey
        +String NormalizationFlag
        +Nullable~DateTime~ NormalizedAt
        +FormPage Page
        +ImageSource Source
    }
    class InputPacket["Пакет ввода"] {
        <<Entity>>
        +Guid Id
        +String Number
        +DateTime QueuedAt
        +Nullable~Double~ FormConfidence
        +String RecognitionRequestJson
        +String RecognitionResultJson
        +Nullable~DateTime~ RecognizedAt
        +Guid CreatedByUserId
        +Nullable~Guid~ AssignedToUserId
        +Boolean Deleted
        +PacketState State
        +IReadOnlyList~ImageFrame~ Frames
        +DocumentForm Form
        +IReadOnlyList~FormRejection~ Rejections
        +IReadOnlyList~PacketFieldValue~ Values
    }
    class FormRejection["Отклонение вида ИК"] {
        <<ValueObject>>
        +DateTime RejectedAt
        +Guid RejectedByUserId
        +DocumentForm Rejected
        +DocumentForm Suggested
    }
    class PacketFieldValue["Значение поля пакета"] {
        <<Entity>>
        +Guid Id
        +IReadOnlyList~String~ Values
        +IReadOnlyList~String~ RecognizedValues
        +Nullable~Double~ Confidence
        +DocumentKindAttribute KindAttribute
        +FormField FormField
        +ValueOrigin Origin
        +ImageFrame ImageFrame
        +SourceArea Area
    }
    class Claim["Claim (ключ разрешения)"] {
        <<Entity>>
        +Guid Id
        +String Key
        +String Description
    }
    class Function["Функция"] {
        <<Entity>>
        +Guid Id
        +String Name
        +IReadOnlyList~FunctionClaimValue~ ClaimValues
    }
    class FunctionClaimValue["Claim-значение функции"] {
        <<Entity>>
        +Guid Id
        +String Value
        +Claim Claim
    }
    class Group["Группа полномочий"] {
        <<Entity>>
        +Guid Id
        +String Name
        +IReadOnlyList~GroupFunction~ Functions
    }
    class GroupFunction {
        <<Entity>>
        +Guid Id
        +Function Function
    }
    class UserActiveToken["Токены сессии"] {
        <<Entity>>
        +Guid Id
        +String Jti
        +DateTime IssuedAt
        +DateTime ExpiresAt
    }
    class UserInvalidatedToken {
        <<Entity>>
        +Guid Id
        +String Jti
        +DateTime InvalidatedAt
        +String Reason
    }
    class User["Пользователь"] {
        <<Entity>>
        +Guid Id
        +String Name
        +String Login
        +String Password
        +IReadOnlyList~UserGroup~ Groups
        +IReadOnlyList~UserActiveToken~ ActiveTokens
        +IReadOnlyList~UserInvalidatedToken~ InvalidatedTokens
    }
    class UserGroup {
        <<Entity>>
        +Guid Id
        +Group Group
    }
    style AttributeValueType fill:#eef2fb,stroke:#4a6fa5
    style DocumentForm fill:#eef2fb,stroke:#4a6fa5
    style FormPage fill:#eef2fb,stroke:#4a6fa5
    style FormSection fill:#eef2fb,stroke:#4a6fa5
    style FormField fill:#eef2fb,stroke:#4a6fa5
    style DocumentKind fill:#eef2fb,stroke:#4a6fa5
    style DocumentKindAttribute fill:#eef2fb,stroke:#4a6fa5
    style PageDetectionProfile fill:#eef2fb,stroke:#4a6fa5
    style DiscriminatorZone fill:#eef2fb,stroke:#4a6fa5
    CardExport --> "1..*" InformationCard : Cards
    CardDocument --> "1" DocumentKind : Kind
    CardDocument "1" *-- "0..*" CardDocument : NestedDocuments
    CardDocument "1" *-- "0..*" CardDocumentAttribute : Attributes
    CardDocumentAttribute --> "1" CardDocument : Document
    CardDocumentAttribute --> "1" DocumentKindAttribute : KindAttribute
    InformationCard --> "1" DocumentKind : Kind
    InformationCard "1" *-- "1..*" CardDocument : Documents
    DocumentForm --> "1" DocumentKind : DocumentKind
    DocumentForm "1" *-- "1..*" FormPage : Pages
    FormPage "1" *-- "0..*" FormSection : Sections
    FormPage "1" *-- "0..1" PageDetectionProfile : Detection
    FormSection "1" *-- "0..*" FormSection : Sections
    FormSection "1" *-- "0..*" FormField : Fields
    FormField --> "1" DocumentKindAttribute : KindAttribute
    FormField "1" *-- "0..1" SourceArea : Area
    DocumentKind "1" *-- "0..*" DocumentKind : NestedKinds
    DocumentKind "1" *-- "0..*" DocumentKindAttribute : Attributes
    DocumentKindAttribute --> "1" DocumentKind : DocumentKind
    DocumentKindAttribute --> "1" AttributeValueType : ValueType
    PageDetectionProfile "1" *-- "1" SourceArea : AnchorFrame
    PageDetectionProfile "1" *-- "0..*" DiscriminatorZone : Zones
    DiscriminatorZone "1" *-- "1" SourceArea : Area
    ImageFrame --> "0..1" FormPage : Page
    InputPacket "1" *-- "1..*" ImageFrame : Frames
    InputPacket --> "0..1" DocumentForm : Form
    InputPacket "1" *-- "0..*" FormRejection : Rejections
    InputPacket "1" *-- "0..*" PacketFieldValue : Values
    FormRejection --> "0..1" DocumentForm : Rejected
    FormRejection --> "0..1" DocumentForm : Suggested
    PacketFieldValue --> "1" DocumentKindAttribute : KindAttribute
    PacketFieldValue --> "0..1" FormField : FormField
    PacketFieldValue --> "0..1" ImageFrame : ImageFrame
    PacketFieldValue "1" *-- "0..1" SourceArea : Area
    Function "1" *-- "0..*" FunctionClaimValue : ClaimValues
    FunctionClaimValue --> "1" Claim : Claim
    Group "1" *-- "0..*" GroupFunction : Functions
    GroupFunction --> "1" Function : Function
    User "1" *-- "0..*" UserGroup : Groups
    User "1" *-- "0..*" UserActiveToken : ActiveTokens
    User "1" *-- "0..*" UserInvalidatedToken : InvalidatedTokens
    UserGroup --> "1" Group : Group

Документы контекста

Доменные артефакты

сущностьСтатусВерсия
Атрибут вида документаdraft0.3
Атрибут документа картыdraft0.1
Вид документаdraft0.1
Выгрузкаdraft0.1
Группа полномочийdraft0.1
Документ информационной картыdraft0.1
Значение поля пакетаdraft0.1
Зона-различиеdraft0.1
Информационная картаdraft0.4
Кадр изображенияdraft0.2
Область-источникdraft0.1
Отклонение вида ИКdraft0.1
Пакет вводаdraft0.3
Поле формыdraft0.1
Пользовательdraft0.1
Профиль автоопознания страницыdraft0.1
Раздел формыdraft0.1
Страница формыdraft0.1
Тип значенияdraft0.5
Токены сессииdraft0.1
Форма документаdraft0.1
Функцияdraft0.1
Claim (ключ разрешения)draft0.1
Claim-значение функцииdraft0.1

Документы

НазваниеСтатусВерсия
Образцы бумажных информационных картdraft0.3
Обязательные атрибуты по видам ИКdraft0.1
Разбор образца выгрузки в АБИСdraft0.1
Справочники заказчикаdraft0.2