Конфигурирование сервера ^^^^^^^^^^^^^^^^^^^^^^^^ СМЭВ QL сервер содержит два конфигурационных файла: - **credentials.yaml** - конфигурирует представление сервера - **application.yaml** - конфигурирует поведение сервера Состав настроек credentials.yaml: .. code-block:: yaml version: 1.0.0 system: mnemonic: smev_ql_mnemonic instance: smev_ql_instance Язык и синтаксис ^^^^^^^^^^^^^^^^^ Моделирование ############# Для моделирования документного слоя данных в спецификации выбран язык разметки ``YAML``. Запросы и ответы ################# Для написания запросов, а также в качестве сериализатора ответов, спецификация определяет использование JSON. Типизация ^^^^^^^^^^ Фактические типы данных наследуют типы данных JSON (включая NULL): - string; - number; - object; - array; - boolean; - null. Типы данных в модели и приведение типов ####################################### В описании модели допускается указание фактического типа данных атрибута ресурса **вторым элементом массива type**. Указание является опциональным, по умолчанию подразумевается неограниченный **STRING**. Пример из описания модели: .. code-block:: yaml fields: id: name: Идентификатор записи type: - number - SHORT length: 20 nullable: not NULL key: PRIMARY В качестве второго уточняющего типа следует применять типы НСУД: - STRING; - DOUBLE; - FLOAT; - BOOLEAN; - BYTE (не поддерживается на витрине); - BINARY; - BIG_DECIMAL (не поддерживается на витрине); - LONG; - INTEGER; - SHORT; - DATE; - TIME; - TIMESTAMP. Моделирование данных ^^^^^^^^^^^^^^^^^^^^^ Модели данных описываются в формате YAML в папке проекта models согласно спецификации СМЭВ QL. Структура базовой модели ######################### Базовая модель должна ставиться впереди общего файла моделей, так как от ее алиасов наследуется элементы пользовательских моделей. Описание базовой модели данных в формате YAML имеет следующую структуру: .. code-block:: yaml default_string: &ds name: Строка type: - string - STRING length: 0 nullable: NULL key: NONE source: NONE default_number: &dn name: Число type: - integer - INTEGER length: 0 nullable: NULL key: NONE source: NONE primary_key: &pk name: Ключ type: - string - STRING length: 0 nullable: NULL key: PRIMAY source: NONE base_model: &base_model default_fields: &default_fields Структура модели данных ####################### Каждая модель представляет из себя YAML-файл, который должен быть соединен с базовой моделью для прохождения валидации. Первый блок модели определяет ее мета-данные и атрибутивный состав. **Мета-данные и поля модели** .. code-block:: yaml resources: # slots — техническое название модели, по нему производятся все связи - slots: *base_model # значение name — название модели на русском языке name: Слоты # fields — список полей модели fields: # список полей может включать перечень полей из default_fields <<: *default_fields # поля по-умолчанию наследуются от ds (default_string) из базовой модели id: *ds resource_id: *ds # у поля может быть переопределен source (по-умолчанию у каждого поля источник всей модели) type: *ds source: field: tag_type age: *ds source: field: tag_age visitTime: *ds duration: *ds status: *ds create_ts: *ds update_ts: *ds update_ts: *ds Второй блок модели описывает связи моделей друг с другом через ключи ``primary_key`` и ``foreign_key``. Ключи могут быть составными (описывается массивом), ключи не обязательно должны быть ключами из БД. Связи имеют два типа: 1. belongs_to 2. has_many (один ко многим) **Связи модели** .. code-block:: yaml # Блок connections описывает связи модели (по названию) через явно указываемых два ключа connections: belongs_to: - resource: primary_key: [ id ] foreign_key: [ resource_id ] has_many: - book: primary_key: [ id ] foreign_key: [ slot_id ] - unaccessible_period: primary_key: [ resource_id, type ] foreign_key: [ resource_id, type ] Блок ограничений и разрешений использования условий поиска. **Связи модели** .. code-block:: yaml # Блок conditions описывает ограничения и разрешения на использование условий поиска conditions: allowed: [id, name] # если заполнено, то поиск разрешен только по этим полям и полям с ключами denied: [snils] # если заполнено, то поиск запрещен по этим ключам always: # наличие условий в блоке always должно ко всем запросам ресурса добавлять эти условия, если указаны в запросе, то перетирать - region: ["=", "77"] - blocked: ["=", true] Блок — **extract**, описывает названия **source** из которого нужно извлекать модель и ее таблицу. **Источники модели** .. code-block:: yaml extract: source: - name: prostore table: misdm.slots **Источники по условиям** В блоке c указанием источника в модели допускается указание условий его выбора через блок ``conditions``. Блок ``conditions`` содержит массив условий применения источника на основании значений полученных в запросе атрибутов: .. code-block:: yaml extract: source: - name: prostore1 table: misdm.slots conditions: # попадание в промежуток - range: field: age from: 0 to: 2 - eq: field: color not: "blue" - name: prostore2 table: misdm.39slots conditions: # ограничения по (не)равенству - eq: field: resource_id is: 1 - name: prostore3 table: misdm.39slots conditions: # ограничения по наличию в источнике - eq: field: snils extract: source: redis table: default_table key: resource_hashed_id algorithm: md5 # select count(*) > 0 from offices.offices where resource_hashed_id = ? # параметр: md5(snils) is: true - name: prostore_default table: misdm.39slots conditions: - fallback: true Загрузка ######### Модели данных считываются, валидируются и загружаются в память из папки **models** при запуске СМЭВ QL сервера. По-умолчанию используется версия **model**, на которую ссылается symlink **current**, при его отсутствии по-умолчанию считается **старшая** версия. .. note:: Модели и версии, **начинающиеся с подчеркивания (_) НЕ загружаются**, они находятся в стадии проектирования. Guard-атрибуты ############### Для ограничения возможности получения некоторых атрибутов без предварительного предоставления их же (или дополнительных) значения, извлекающим необходимо определить атрибуты-ограничители в блоке guard. Пример: .. code-block:: yaml fields: <<: *default_fields first_name: *ds last_name: <<: *ds guard: [last_name] snils: <<: *ds guard: [last_name first_name snils] В примере извлечение **first_name** не ограничивается. Для получения **last_name** фамилия должна быть передана в блоке conditions, а для получения **snils** в conditions должны присутствовать фамилия, имя и сам СНИЛС. .. _request: Запросы ^^^^^^^^ Запросы к серверу выполняют методом POST и содержат в теле JSON-объект, состоящий из обязательных блоков: - Блок Credentials; - Блок Query; Также пространстве методов server находятся методы, помогающие эксплуатации корректно конфигурировать хранилища данных относительно модели СМЭВ QL. Блок Credentials ################ .. code-block:: json "credentials":{ "system":{ "mnemonic":"117bed7f-1c07-4079-a446-1161588db4e5", "instance_id":"ccb4a88f-f44b-43e7-8a97-3e45c8345e90", "user_id":"5ed38461-0907-486a-930a-7b443482932c" }, "request":{ "id":"df5a0073-c6be-4d8c-8eb2-9b2f4188a429", "sub_id":"0cdb59ce-224b-4118-8da1-c5ea08a5d955", "name":"driver_data", "purpose_id":"ed1170f1-3caa-4985-aa38-c9c5a190b770", "audit":"false", "audit_id":"fc1048fe-323d-4eeb-92df-5710b3d1d100", "audit_token":"39e47aac-45d2-44c1-8c26-2d9b28b1703b" }, "signature":{ "digest": null, "signature": null } } Блок Query ########## .. code-block:: json { "query": { "office": { "conditions": { "phone": "(347) 246-53-00" }, "attributes": [ "id", "phone", "name" ], "cabinet": { "conditions": { "available": true }, "attributes": [ "number", "name", "seats" ], "online_room": { "conditions": { "public": true, "software": "zoom" }, "attributes": [ "url" ] }, "parking": { "conditions": { "free": true, "available": true }, "attributes": [ "number", "floor" ] } } } } } Условия фильтрации Conditions """""""""""""""""""""""""""""" Объединение условий только по `and` (MVP) Операции сравнения (op): - = (по умолчанию) - > - >= - < - <= - in - like (на перспективу) Условия сравнения применимы к численным типам, датам, временам и таймштампам. Варианты определения условий фильрации: По равенству .. code-block:: json { "query": { "office": { "conditions": { "phone": "(347) 246-53-00" } } } } На основе сравнения, краткая запись .. code-block:: json { "query": { "office": { "conditions": { "area": [">","130"] } } } } На основе сравнения, полная запись .. code-block:: json { "query": { "office": { "conditions": { "area": { "op": ">", "value": "130" } } } } } Комплексное условие .. code-block:: json { "query": { "office": { "conditions": { "area": [">","130"], "floor": ["in", [1, 2]] } } } } **OR (ИЛИ) в условиях** В **conditions** СМЭВ QL запроса поддерживается возможность указывать логический ИЛИ через зарезервированное слово **or**. В блок **or** необходимо передать массив объектов, содержащих условия в свою очередь объединённые логическим **И** (**AND**). Все условия, находящиеся на одном уровне с **or** группируются через логическое **И** (**AND**), как при обычном СМЭВ QL Запросе. Пример: .. code-block:: json "conditions": { "lastname": "П", "middlename": "И", "birthdate": "2021-11-29 00:00:00", "or": [ { "vin": "в1" }, { "vin2": "в2", "model": "bmw" } ], "fetch": { "order": [["id", "ASC"], ["number", "DESC"]], // ASC default "page": [2, 10] // limit 10 offset 10 } } Условия описанного выше запроса (без учета fetch) соберутся в следующую конструкцию: .. code-block:: yaml ... WHERE (lastname = 'П' AND middlename = 'И' AND birthdate = '2021-11-29 00:00:00') OR (vin ='в1') OR (vin2='в2' AND model = 'bmw') ... Сортировка и пагинация """"""""""""""""""""""" В блоке **conditions** опционально можно добавить блок **fetch**, в котором указывать условия сортировки и выбора страниц. Пример блока: .. code-block:: json "conditions": { "lastname": "П", "middlename": "И", "birthdate": "2021-11-29 00:00:00", "fetch": { "order": [["id", "ASC"], ["number", "DESC"]], // ASC default "page": [2, 10] // limit 10 offset 10 } } Если порядок сортировки не указан, то применяется ASC. Если не указаны страницы, то по умолчанию всегда устанавливается первая страница с лимитом, равными параметру **default** блока **pagination** в файле конфигураций ``application.yaml``. Если запрашивается элементов на страницу больше, чем значение max, то должно использоваться дефолтное значение. .. code-block:: yaml pagination: default: 100 //количество элементов на странице по умолчанию max: 1000 //максимальное количество элементов на странице Эксплуатационные запросы ######################### В пространстве методов server находятся методы, помогающие эксплуатации корректно конфигурировать хранилища данных относительно модели СМЭВ QL. Метод возврата списка обязательных для создания индексов: ``GET server/indexes/required`` В ответе должен возвращаться JSON с полями, используемыми в связях моделей (connections) и блоке conditions.allowed моделей, если они определены (conditions) .. code-block:: json { "server": { "mnemonic": "#mnemonic", "instance": "#instance" }, "indexes": { "connections": [{ "source": "#source_name2", "table": "#table_name2", "fields": ["#field_name1", "#field_name2"] }, { "source": "#source_name2", "table": "#table_name2", "fields": ["#field_name1", "#field_name2"] } ], "conditions": [{ "source": "#source_name2", "table": "#table_name2", "fields": ["#field_name1", "#field_name2"] }, { "source": "#source_name2", "table": "#table_name2", "fields": ["#field_name1", "#field_name2"] } ] } } Обработка запросов ^^^^^^^^^^^^^^^^^^^ Логирование мета-данных ######################## У каждого запроса логируются данные из блока credentials в info и выше. Формат строчки лога: .. code-block:: json { "level": "info", "time": "2000-01-01T01:01:01.111Z", "name": "#{smevql_server_name}.request", "system": { "mnemonic": "117bed7f-1c07-4079-a446-1161588db4e5", "instance_id": "ccb4a88f-f44b-43e7-8a97-3e45c8345e90", "user_id": "5ed38461-0907-486a-930a-7b443482932c" }, "request": { "id": "df5a0073-c6be-4d8c-8eb2-9b2f4188a429", "sub_id": "0cdb59ce-224b-4118-8da1-c5ea08a5d955", "name": "driver_data", "purpose_id": "ed1170f1-3caa-4985-aa38-c9c5a190b770", "audit": "false", "audit_id": "fc1048fe-323d-4eeb-92df-5710b3d1d100", "audit_token": "39e47aac-45d2-44c1-8c26-2d9b28b1703b" } } Для каждого входящего запроса логируется каждый отправленный запрос к источнику: .. code-block:: json { "level": "info", "time": "2000-01-01T01:01:01.111Z", "name": "#{smevql_server_name}.request", "system": { "mnemonic": "117bed7f-1c07-4079-a446-1161588db4e5", "instance_id": "ccb4a88f-f44b-43e7-8a97-3e45c8345e90", "user_id": "5ed38461-0907-486a-930a-7b443482932c" }, "request": { "id": "df5a0073-c6be-4d8c-8eb2-9b2f4188a429", "sub_id": "0cdb59ce-224b-4118-8da1-c5ea08a5d955", "name": "driver_data", "purpose_id": "ed1170f1-3caa-4985-aa38-c9c5a190b770", "audit": "false", "audit_id": "fc1048fe-323d-4eeb-92df-5710b3d1d100", "audit_token": "39e47aac-45d2-44c1-8c26-2d9b28b1703b" }, "source_request": { "id": "1cdb59ce-224b-4118-8da1-c5ea08a5d955", "source": "#{source_name}" } } Передача идентификаторов: 1. source_request.id передается в queryId тела запроса в Простор. 2. В x-request-id передается склейка {request.id};{request.sub_id};{source_request.id} Логирование ответа .. code-block:: json { "level": "info", "time": "2000-01-01T01:01:01.111Z", "name": "#{smevql_server_name}.response", "system": { "mnemonic": "117bed7f-1c07-4079-a446-1161588db4e5", "instance_id": "ccb4a88f-f44b-43e7-8a97-3e45c8345e90", "user_id": "5ed38461-0907-486a-930a-7b443482932c" }, "request": { "id": "df5a0073-c6be-4d8c-8eb2-9b2f4188a429", "sub_id": "0cdb59ce-224b-4118-8da1-c5ea08a5d955", "name": "driver_data", "purpose_id": "ed1170f1-3caa-4985-aa38-c9c5a190b770", "audit": "false", "audit_id": "fc1048fe-323d-4eeb-92df-5710b3d1d100", "audit_token": "39e47aac-45d2-44c1-8c26-2d9b28b1703b" }, "source_request": { "id": "1cdb59ce-224b-4118-8da1-c5ea08a5d955", "source": "#{source_name}" }, "response": { "duration": "1ms", "code": 200, "result": "ok" } } Построение плана ################# Входные данные: - загруженные модели, описывающие атрибутный состав сущностей, связи между сущностями и источники; - запрос поступивший к серверу. Необходимо определить набор запросов и порядок их исполнения SMQEVQL сервером, обеспечить параллельное исполнение независимых запросов. Вид плана запроса: .. code-block:: yaml plan: level: 1 - source: prostore1 query: SELECT id, phone, name FROM office WHERE phone = '(347) 246-53-00'; pk: id alias: offices level: 2 - source: prostore2 query: SELECT id, number, name, seats FROM cabinet WHERE office_id in (@offices) AND available = 'true'; pk: id alias: cabinets - source: prostore1 query: SELECT id, number, floor FROM parking WHERE office_id in (@offices) free = 'true' AND available = 'true'; pk: number, flor alias: parkings level: 3 - source: vostok7 query: SELECT url FROM online_room WHERE cabinet_id in (@cabinets) AND public = 'true' AND software = 'zoom'; pk: null alias: online_rooms Сначала параллельно выполняются запросы первого уровня, затем запрос второго уровня на основе данных полученных на первом уровне. Фомирование плана запроса основывается на внешнем объединении данных в сторону основной сущности. Порядок формирования плана запроса: - на основе query определяется основная запрашиваемая сущность; - на основе query определяются вспомогательные сущности; - на основе query определяются conditions к основной сущности; - на основе query определяются conditions к вспомогательным сущностям; - на первом уровне плана формируется запрос к основной сущности на основе: - запрошенных атрибутов; - данных модели; - условий фильтрации. Отмечаются поля, составляющие PK. Первичные ключи, даже отсутствующие в атрибутах запроса к серверу должны быть в запросе к источнику. - формируется запрос к вспомогательным сущностям на основе: - запрошенных атрибутов; - данных модели; - условий фильтрации; - с добавлением фильрации по PK основной или предшествующей сущности. Первичные ключи, даже отсутствующие в атрибутах запроса к серверу должны быть в запросе к источнику, за исключением терминальных запросов. .. _request_plan: .. figure:: img/request_plan.png :align: center :alt: План запроса План запроса соответсвует иерархии построенной от основной сущности на основе связей (model\connections). .. _graf_plan: .. figure:: img/graf_plan.png :align: center :alt: Граф план Ответы ^^^^^^^ Ответы СМЭВ QL сервера представляют из себя объект JSON, схема которого определяется составом запроса. Например для запроса: .. code-block:: json { "query":{ "people":{ "conditions":{ "age":"<35" }, "attributes":[ "name", "phone", "vsu_code" ], "military_office":{ "attributes":[ "address" ] } } }, "credentials":{ } } Ответ будет следующим: .. code-block:: json { "response":{ "people":[ { "name":"Иван", "phone":"+79011001010", "vsu_code":"1025", "military_office":[ { "address":"г.Москва, ул.Угрешко" } ] }, { "name":"Пётр", "phone":"+79022002020", "vsu_code":"1026", "military_office":[ { "address":"г.Москва, Хилков переулок" } ] } ] }, "credentials":{ } } Стейт-машина СМЭВ QL ^^^^^^^^^^^^^^^^^^^^^ СМЭВ QL содержит встроенную машину состояний для изменения объектов модели внутри витрин данных. Одновременно с этим Стейт машина может, в качестве подтверждения перехода состояния, использовать внешний источник (например ИС Электронной очереди). Карта состояний и переходов описывается в виде YAML-файла state.yaml располагаемого в папке states/<имя-модели>/<х.х версия модели> инстанса СМЭВ QL Сервера. Описание формата и правил карты состояний: .. code-block:: yaml model: slot # имя модели states: # массив состояний объекта - state: available # название состояния available attributes: # массив атрибутов, описывающих состояние - name: status # состояние определятся значением атрибута status value: AVAILABLE # значение атрибута для описываемого состояния initial: true - state: booked attributes: - name: status value: RECORDED - state: reserved attributes: - name: status value: RESERVED - state: cancelled attributes: - name: status value: CANCELED - state: blocked attributes: - name: status value: BLOCKED events: # список событий изменения состояний, из них создаются методы API - event: book # создает метод POST /states/slot/book from: # массив состояний из которых возможен вызов события - available - reserved to: booked # в какое состояние переводится объект после события hooks: # массив связанных событий - model: book # после перевода надо вызвать событие init для модели book event: init confirm: source: rmis_rest # названия источника endpoint: /booking/book method: post body: payload # что включать в тело запроса (full|state|conditions|payload|credentials) accept: # условие принятия jsonpath: $.status.statusCode eq: 0 # ожидаем, что statusCode будет равен 0 - event: reserve from: available to: reserved - event: block from: available to: blocked - event: cancel from: - available - reserved - booked - blocked to: cancelled hooks: - model: book event: cancel При наличии заполненных состояний машины СМЭВ QL Сервер генерирует API c набором HTTP-методов, отвечающих за изменение и просмотр состояний объектов: 1. GET /states — получить карту переходов 2. GET /states/ — получить карту переходов конкретной модели 3. POST /states// — выполнить переход состояний для модели Запрос выполнения перехода: .. code-block:: POST /states/slot/book { "state": { "conditions": { "id": "d9e70331-b4c0-4e96-96b6-322ac75e5188" # slot_id }, "payload": { "bookId":"82dcac12-0a29-4fff-b9a7-8dfc84f7853d", "patient_Id":"23453456", "booking_type":"APPOINTMENT", "caseNumber":"73367196", "preliminaryReservation": false, "email":"email@gmail.com", "mobilePhone":"89150000102", "referral_id":"102111", "cards_id":"102" } }, "credentials": { "system": { "mnemonic": "117bed7f-1c07-4079-a446-1161588db4e5", "instance_id": "ccb4a88f-f44b-43e7-8a97-3e45c8345e90", "user_id": "5ed38461-0907-486a-930a-7b443482932c" }, "request": { "id": "df5a0073-c6be-4d8c-8eb2-9b2f4188a429", "sub_id": "0cdb59ce-224b-4118-8da1-c5ea08a5d955", "name": "request_name", "purpose_id": "ed1170f1-3caa-4985-aa38-c9c5a190b770", "audit": false, "audit_id": "fc1048fe-323d-4eeb-92df-5710b3d1d100", "audit_token": false } } } Спецификация интерфейса Стейт-машины ##################################### .. code-block:: yaml openapi: 3.0.0 x-stoplight: id: 5i2oag6m5eq3v info: title: SmevQLStateMachine version: '1.0' description: '' servers: - url: 'http://localhost:3000' paths: /states: parameters: [] get: summary: Get models tags: [] responses: '200': description: '' content: application/x-yaml: schema: $ref: '#/components/schemas/Models' examples: {} application/xml: schema: type: object properties: {} multipart/form-data: schema: type: object properties: {} text/html: schema: type: object properties: {} operationId: get-models description: Retrieve the information of models '/states/{model}': parameters: - schema: type: string name: model in: path required: true get: summary: Get model tags: [] responses: '200': description: Model Found content: application/x-yaml: schema: $ref: '#/components/schemas/Model' examples: {} '400': description: Bad Request '404': description: Model Not Found operationId: get-model description: Retrieve the information of model parameters: [] '/states/{model}/{event}': post: summary: State change operationId: post-state responses: '200': description: State Updated content: plain/text: schema: type: string examples: {} '400': description: Bad request '404': description: Not Found requestBody: content: application/json: schema: $ref: '#/components/schemas/StateUpdate' examples: {} description: Post the necessary fields for the API to create a new user. description: Update state parameters: [] parameters: - schema: type: string name: model in: path required: true - schema: type: string name: event in: path required: true components: schemas: State: type: object x-stoplight: id: 89f55561cae04 properties: state: type: string attributes: type: array minItems: 1 items: $ref: '#/components/schemas/Attribute' initial: type: boolean Model: type: object x-stoplight: id: b96a73db1e1b2 properties: model: type: string states: type: array minItems: 1 items: $ref: '#/components/schemas/State' events: type: array items: $ref: '#/components/schemas/Event' Events: title: Events x-stoplight: id: qdvbkmgs9xkli type: array items: $ref: '#/components/schemas/Event' States: $ref: '#/components/schemas/State' x-stoplight: id: wab1w6ro30nrl Event: title: Event x-stoplight: id: sr024y2v7khum type: object properties: event: type: string from: type: string to: type: string Models: title: ModelSet x-stoplight: id: e7de590d788a7 type: array items: $ref: '#/components/schemas/ModelInstance' ModelInstance: type: object properties: model: type: string states: $ref: '#/components/schemas/States' events: $ref: '#/components/schemas/Events' ModelSet: type: array items: $ref: '#/components/schemas/Model' Attribute: title: Attribute x-stoplight: id: 3kiqu047734tc type: object properties: name: type: string value: type: string description: '' StateUpdate: title: StateUpdate x-stoplight: id: 2iyfifo0q1dt2 type: object properties: state: type: object properties: conditions: type: object payload: type: object credentials: type: object properties: system: type: object properties: mnemonic: type: string instance_id: type: string user_id: type: string request: type: object properties: id: type: string format: uuid sub_id: type: string format: uuid name: type: string purpose_id: type: string format: uuid audit: type: boolean audit_id: type: string format: uuid audit_token: type: string **Пример реализации: Спецификация интерфейса Стейт-машины РМИС (OpenAPI)** .. code-block:: yaml openapi: 3.0.0 x-stoplight: id: 5i2oag6m5eq3v info: title: SmevQLStateMachine version: '1.0' description: '' servers: - url: 'http://localhost:3000' paths: /states: parameters: [] get: summary: Get models tags: [] responses: '200': description: '' content: application/x-yaml: schema: $ref: '#/components/schemas/Models' examples: {} application/xml: schema: type: object properties: {} multipart/form-data: schema: type: object properties: {} text/html: schema: type: object properties: {} operationId: get-models description: Retrieve the information of models '/states/{model}': parameters: - schema: type: string name: model in: path required: true get: summary: Get model tags: [] responses: '200': description: Model Found content: application/x-yaml: schema: $ref: '#/components/schemas/Model' examples: {} '400': description: Bad Request '404': description: Model Not Found operationId: get-model description: Retrieve the information of model parameters: [] '/states/{model}/{event}': post: summary: State change operationId: post-state responses: '200': description: State Updated content: plain/text: schema: type: string examples: {} '400': description: Bad request '404': description: Not Found requestBody: content: application/json: schema: $ref: '#/components/schemas/StateUpdate' examples: {} description: Post the necessary fields for the API to create a new user. description: Update state parameters: [] parameters: - schema: type: string name: model in: path required: true - schema: type: string name: event in: path required: true components: schemas: State: type: object x-stoplight: id: 89f55561cae04 properties: state: type: string attributes: type: array minItems: 1 items: $ref: '#/components/schemas/Attribute' initial: type: boolean Model: type: object x-stoplight: id: b96a73db1e1b2 properties: model: type: string states: type: array minItems: 1 items: $ref: '#/components/schemas/State' events: type: array items: $ref: '#/components/schemas/Event' Events: title: Events x-stoplight: id: qdvbkmgs9xkli type: array items: $ref: '#/components/schemas/Event' States: $ref: '#/components/schemas/State' x-stoplight: id: wab1w6ro30nrl Event: title: Event x-stoplight: id: sr024y2v7khum type: object properties: event: type: string from: type: string to: type: string Models: title: ModelSet x-stoplight: id: e7de590d788a7 type: array items: $ref: '#/components/schemas/ModelInstance' ModelInstance: type: object properties: model: type: string states: $ref: '#/components/schemas/States' events: $ref: '#/components/schemas/Events' ModelSet: type: array items: $ref: '#/components/schemas/Model' Attribute: title: Attribute x-stoplight: id: 3kiqu047734tc type: object properties: name: type: string value: type: string description: '' StateUpdate: title: StateUpdate x-stoplight: id: 2iyfifo0q1dt2 type: object properties: state: type: object properties: conditions: type: object properties: id: type: string format: uuid payload: type: object properties: book_id: type: string format: uuid patient_id: type: string booking_type: type: string case_number: type: string preliminary_reservation: type: boolean email: type: string mobile_phone: type: string referral_id: type: string cards_id: type: string credentials: type: object properties: system: type: object properties: mnemonic: type: string instance_id: type: string user_id: type: string request: type: object properties: id: type: string format: uuid sub_id: type: string format: uuid name: type: string purpose_id: type: string format: uuid audit: type: boolean audit_id: type: string format: uuid audit_token: type: string Выполнение операций обновления данных в витрине """""""""""""""""""""""""""""""""""""""""""""""" Инсерты в витрину выполняются в порядке поступления запросов. Каждый экземпляр СМЭВ QL сервера ведет нарастающий счетчик инсертов. Каждый экземпляр СМЭВ QL сервера создает один поток управления дельтами, который выполняет: 1. Периодически (период конфигурируемая величина, по умолчанию 60 сек) проверяет значение счетчика числа инсертов, если значение счетчика более 0 - Выполняет открытие и закрытие дельты с флагом immediate, ошибки открытия и закрытия дельты игнорируются. Попытка закрытия дельты выполняется независимо от успешности открытия дельты. - Обнуляет значение счетчика. 2. Периодически (период конфигурируемая величина, по умолчанию 30 мин) - Выполняет открытие и закрытие дельты с флагом immediate, ошибки открытия и закрытия дельты игнорируются. Попытка закрытия дельты выполняется независимо от успешности открытия дельты. Чтение данных сервером СМЭВQL выполняется с применением AS OF . Обновление объектов через Стейт-машину """"""""""""""""""""""""""""""""""""""""" Через Стейт-машину можно обновлять записи в витрине. Для этого при конфигурировании карты состояний необходимо задать значение у **event** ``updatable: true``. При этом если требуется дать возможность обновлять только часть атрибутов, то ограничить этот список можно перечислив атрибуты в массиве ``updatable_attributes``. .. code-block:: yaml - event: reserve from: available to: reserved updatable: true // по умолчанию false для всех, кроме init, возможность изменять запись при переводе статуса updatable_attributes: [] // массив атрибутов, которые можно обновлять, пустой — можно все Данные для обновления будут браться из блока **payload** запроса на смену состояния. Для события init такое конфигурирование не требуется - по умолчанию обновления разрешены для всех атрибутов из **payload**. Ошибки ^^^^^^^ Ошибки выводятся в блоке **response**: .. code-block:: json { "response": { "errors": [ { "error": "Запрещен вывод атрибутов без переданного guard", "code": "401" } ] }, "credentials": { } } Базовые ошибки СМЭВ Ql ###################### **1ХХ Ошибки разбора запроса** * 101 Запрос не должен называться 'errors' — Неправильное название запроса 'errors' **2ХХ Ошибки модели** * 201 Неизвестный атрибут — У ресурса не найден атрибут с соотв. именем * 202 Неизвестный ресурс — Ресурс с соотв. именем не зарегистрирован в модели данных * 203 Неизвестная связь — Не найдена связь между двумя ресурсами * 204 Неправильная связь — Размеры ключей не соответствуют для соединения одного ресурса с другим **3ХХ Ошибки источников** * 301 Неизвестный источник — Не найдено описание источника данных с соотв. именем * 302 Неизвестный адаптер — Не найден адаптер с соотв. именем **4ХХ Ошибки доступов и ограничений** * 401 Запрещен вывод атрибутов без переданного guard — Среди запрашиваемых атрибутов есть атрибут с невыполненными ограничениями в блоке guard (не переданы в запросе атрибуты из guard) * 402 Недостаточно атрибутов для выбора источника — Среди атрибутов фильтрации нет атрибутов, необходимых для выбора источника * 403 Запрещенные атрибуты для поиска — Среди атрибутов фильтрации есть атрибуты, указанные в блоке denied модели * 404 Атрибуты для поиска не разрешены — Среди атрибутов фильтрации есть атрибуты, которые не указаны в разрешающем блоке allowed модели * 405 Попытка переопределения фиксированных условий поиска — Среди атрибутов фильтрации есть атрибуты, которые пытаются переопределить фиксированные ограничения поиска в блоке always модели **9ХХ Прочие ошибки** * 901 Непредвиденная ошибка — Непредвиденная ошибка