Оцифровка информационных карт
Ограниченный контекст Сервиса: общая схема данных и её границы. Внутри контекста язык единый — термин значит одно и то же во всех частях модели.
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
Документы контекста
Доменные артефакты
| сущность | Статус | Версия |
|---|---|---|
| Атрибут вида документа | draft | 0.3 |
| Атрибут документа карты | draft | 0.1 |
| Вид документа | draft | 0.1 |
| Выгрузка | draft | 0.1 |
| Группа полномочий | draft | 0.1 |
| Документ информационной карты | draft | 0.1 |
| Значение поля пакета | draft | 0.1 |
| Зона-различие | draft | 0.1 |
| Информационная карта | draft | 0.4 |
| Кадр изображения | draft | 0.2 |
| Область-источник | draft | 0.1 |
| Отклонение вида ИК | draft | 0.1 |
| Пакет ввода | draft | 0.3 |
| Поле формы | draft | 0.1 |
| Пользователь | draft | 0.1 |
| Профиль автоопознания страницы | draft | 0.1 |
| Раздел формы | draft | 0.1 |
| Страница формы | draft | 0.1 |
| Тип значения | draft | 0.5 |
| Токены сессии | draft | 0.1 |
| Форма документа | draft | 0.1 |
| Функция | draft | 0.1 |
| Claim (ключ разрешения) | draft | 0.1 |
| Claim-значение функции | draft | 0.1 |
Документы
| Название | Статус | Версия |
|---|---|---|
| Образцы бумажных информационных карт | draft | 0.3 |
| Обязательные атрибуты по видам ИК | draft | 0.1 |
| Разбор образца выгрузки в АБИС | draft | 0.1 |
| Справочники заказчика | draft | 0.2 |
Структурные связи
Используется
- Handler Handler: ClassifyFrame
- Handler Handler: DeleteInputPacket (мягкое)
- Handler Handler: ForceDeleteInputPacket (жёсткое)
- Handler Handler: GetInputQueue
- Handler Handler: GetUserProfile
- Handler Handler: LoginByPassword
- Handler Handler: Logout
- Handler Handler: NormalizePacket
- Handler Handler: SubmitInputPacket