Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents

Мета

Веб-сервіс WS використовується для завантаження реєстру медичних виробів. Процес використовує сервіс jabba. В ході виконання запиту створюється джоба, на базі якої створюються задачі. Кожна задача це один запит для створення сутності з реєстру.

Ключові положення

  1. Це метод GraphQL, який використовується тільки в адміністративній панелі.

  2. Тільки автентифіковані та авторизовані співробітники NHS з відповідним скоупом можуть завантажити реєстр медичних виробів.

  3. Даний веб-сервіс WS використовує сервіс jabba. В ході виконання запиту створюється джоба, на базі якої створюються задачі. Кожна задача це один запит для створення сутності з реєстру.

  4. Вхідні дані для реєстру медичних виробів мають бути в форматі .csv та з символами (тобто лапки, лінії - " як \"; нові лінії розміщені як \r\n ).

  5. Кожен медичний виріб в реєстрі перевіряється так же як і в https:/wiki/spaces/RMDN/pages/18339135535/e-health-ua.atlassian.net/wiki/pages/createpage.action?spaceKey=RMDN&title=%5BNEW%5D%20%28GraphQl%29%20Create%20Device%20definition WS.

Специфікація

Expand
titleindex.graphql
Code Block
languagegraphql
  "Creates a single `DeviceRegistryJob`."
  uploadDeviceRegistry(input: UploadDeviceRegistryInput!): UploadDeviceRegistryPayload
Expand
titledeviceRegistryJobs.graphql
Code Block
languagegraphql
"""
Input for `uploadDeviceRegistry` mutation.

User must have a scope **device_registry:write**
"""
input UploadDeviceRegistryInput {
  "Type of register originating device registry data. The value should be present in the `REGISTER_TYPE` dictionary."
  registerType: String!
  "Create device registry reason description."
  reasonDescription: String!
  "String with input file in csv format with device register."
  csvData: String!
}

"""
Return type for `uploadDeviceRegistry` mutation.
"""
type UploadDeviceRegistryPayload {
  "Created `DeviceRegistryJob`."
  deviceRegistryJob: DeviceRegistryJob
}

"""
An object for DeviceRegistryJob.
"""
type DeviceRegistryJob implements Node {
  "The ID of an object"
  id: ID!
  "Primary key identifier from the database"
  databaseId: UUID!
  "Job name."
  name: String
  "Device registry Job status."
  status: JobStatus!
  "Job execution strategy."
  strategy: JobStrategy!
  "Date and time when the job starts."
  startedAt: DateTime!
  "Date and time when the job ends."
  endedAt: DateTime
  "Tasks within this job."
  tasks(
    "A condition to be used in determining which values should be returned by the collection."
    filter: TaskFilter
    "The method to use when ordering collection items."
    orderBy: TaskOrderBy
    "Read all values in the set after (below) this cursor."
    after: String
    "Read all values in the set before (above) this cursor."
    before: String
    "Only read the first _n_ values of the set."
    first: Int
    "Only read the last _n_ values of the set."
    last: Int
  ): DeviceRegistryTaskConnection!
  "Type of register originating device registry data. The value should be present in the `REGISTER_TYPE` dictionary."
  registerType: String!
  "Device registry job reason description."
  reasonDescription: String!
}

"""
A connection to a list of `DeviceRegistryTask` values.
"""
type DeviceRegistryTaskConnection {
  "Information to aid in pagination."
  pageInfo: PageInfo!
  "A list of nodes."
  nodes: [DeviceRegistryTask]
  "A list of edges."
  edges: [DeviceRegistryTaskEdge]
}

"""
Reads and enables pagination through a set of `DeviceRegistryTask`.
"""
type DeviceRegistryTaskEdge {
  "The item at the end of the edge."
  node: DeviceRegistryTask!
  "A cursor for use in pagination."
  cursor: String!
}

"""
A child of a `DeviceRegistryJob`, contains the result of task execution.
"""
type DeviceRegistryTask implements Node {
  "The ID of an object"
  id: ID!
  "Primary key identifier from the database"
  databaseId: UUID!
  "Task name."
  name: String
  "Task status, is set automatically."
  status: TaskStatus!
  "Task meta data."
  meta: DeviceRegistryTaskMeta
  "Date and time when task was executed."
  endedAt: DateTime
  "Task error."
  error: TaskError
  "Technical information when task was inserted into the DB."
  insertedAt: DateTime!
  "Technical information when task was updated in the DB."
  updatedAt: DateTime!
}

"""
Metadata of a `DeviceRegistryTask`.
"""
type DeviceRegistryTaskMeta {
  "Line number of csv file from input."
  csvDataLine: Int  
}

Авторизація

  • Перевірити валідність токену доступу

    • в разі помилки - повернути 401 (“Invalid access token”) при неуспішних перевірках

  • Перевірити, що токен дійсний

    • в разі помилки - повернути 401 (“Invalid access token”)

  • Перевірити скоупи користувача на можливість виконання даної дії (скоуп = 'device_registry:write')

    • повернути 403 (“Your scope does not allow to access this resource. Missing allowances: device_registry:write”) в разі невалідних скоупів

Перевірити юридичну особу

  • Отримати client_id з токену.

  • Перевірити статус юридичної особи (status = ACTIVE)

    • в разі помилки - повернути 409 ('client_id refers to legal entity that is not active')

  • Перевірити тип клієнта (type = NHS)

    • в разі помилки - повернути 403 ('You don't have permission to access this resource')

Перевірити запит

  • Перевірити, що потрібні поля вказано у відповідності до специфікації

    • в разі помилки - повернути 422 ('required property <field_name> was not present') де field_name - назва відсутнього поля

  • Перевірити, що не вказано додаткових полів, які не відповідають схемі

    • в разі помилки - повернути 422 ('Unknown field')

  • Перевірити, що кожне поле в запиті відповідає типу в специфікації

    • в разі помилки - повернути 422 (In field <<field_name>>: Expected type <<field_type>>, found <<actual_value>>.') де field_name - назва поля з помилкою, field_type - очікуваний тип поля, actual_value - значення, що було вказано в полі

  • Перевірити, що $.registerType = 'UPLOAD_DEVICE_DEFINITIONS_REGISTRY'

    • в разі помилки - повернути 422 ('Invalid register_type')

  • Перевірити, що $.csvData розмір вхідного поля валідний - файл csv з максимальною кількістю рядків 30000 дозволено.

    • в разі помилки - повернути 422 ('The number of tasks for the job with a sequential execution strategy is limited to 30,000')

  • Перевірити, що вхідний $.csvData відповідає структурі файлу (описано в табличці нижче)

    • в разі помилки - повернути 422 з переліком помилок перевірок

Приклад файлу

View file
nameupload_device_definition_registry_example1example2 (1) (1).csv

*Примітка. Поля device_names.name, device_names.type, properties.type, properties.value_integer, properties.value_string, properties.value_boolean, properties.value_decimal можуть бути вказані в масиві. Значення мають бути розділені | (відповідно).

Сервісна логіка

  1. Створити джобу з типом upload_device_definition_registry в таблиці джоби JABBA DB.

  2. Для кожного рядку у вхідному файлі створити окрему задачу на job в таблиці задач в JABBA DB з додатковими задачами metadata:

    1. назва = ‘Create device definition’

    2. meta.csv_data_line = рядок з csv_file

  3. Для кожної створеної задачі:

    1. Перевірити запис по медичному вирібу у відповідності до https://e-health-ua.atlassian.net/wiki/spaces/RMDNEH/pages/17670799630/NEW+GraphQl+Create+Device+definition#Validate17782014108#Validate-device-definition

      1. в разі помилки валідації - оновити статус задачі на FAILED з відповідним текстом помилки, перейти до задачі

    2. Створити новий медичний виріб в таблицях device_definitions та device_definition_names (PRM DB) у відповідності до співпадіння полів

    3. Оновити статус задачі на PROCESSED, перейти до наступної задачі

  4. Відобразити ідентифікатор джоби з результатом у відповідності до специфікації.

Співпадіння полів

device_definitions

Атрибут

Джерело та логіка

Тип та обмеження

Н/О

id

uuid_generate_v4(), auto

uuid

О

external_id

external_id, з запиту

varchar(255)

Н

classification_type

classification_type, з запиту

varchar(255)

О

description

description, з запиту

varchar(2000)

Н

manufacturer_name

manufacturer_name, з запиту

varchar(255)

О

manufacturer_country

manufacturer_country, з запиту

varchar(255)

О

model_number

model_number, з запиту

varchar(255)

О

part_number

part_number, з запиту

varchar(255)

Н

packaging_type

packaging_type, з запиту

varchar(255)

О

packaging_count

packaging_count, з запиту

int

О

packaging_unit

packaging_unit, з запиту

varchar(255)

О

note

note, з запиту

varchar(2000)

Н

is_active

true, auto

boolean

О

inserted_at

now(), auto

timestamp

О

updated_at

now(), auto

timestamp

О

inserted_by

user_id, з токену

uuid

О

updated_by

user_id, з токену

uuid

О

properties

properties.type + properties.value[X], з запиту, масив об'єктів

jsonb

Н

parent_id

parent_id, з запиту

uuid

Н

device_definition_names

Для кожного об'єкту масивуdevice_names.name та device_names.type створити окремий запис.

...