AZykov (обсуждение | вклад) |
AZykov (обсуждение | вклад) |
||
(не показана 1 промежуточная версия этого же участника) | |||
Строка 61: | Строка 61: | ||
* onAfterDelete - событие вызывается после удаления объекта класса | * onAfterDelete - событие вызывается после удаления объекта класса | ||
* onAfterModify - событие вызвается после модификации объекта класса | * onAfterModify - событие вызвается после модификации объекта класса | ||
* onAfterReload - | * onAfterReload - событие после перезагрузки класса из хранилища. Используется при потере актуальности кеша | ||
* onAfterUpdate - | * onAfterUpdate - универсальное событие после delete/modify/insert | ||
В параметр функции, вызываемой каждым событием передается дженерик-параметр IDataUpdateParams, который может быть типизирован каким-либо интерфейсом. | В параметр функции, вызываемой каждым событием передается дженерик-параметр IDataUpdateParams, который может быть типизирован каким-либо интерфейсом. | ||
Строка 273: | Строка 273: | ||
= Вызов сервисов платформы и работа с внутренним API = | = Вызов сервисов платформы и работа с внутренним API = | ||
Работу с сервисами платформы можно условно разделить | Работу с сервисами платформы можно условно разделить на две категории: | ||
* Работа с сервисами продуктового слоя - вызов сервисов, реализованных в сторонних пакетах | |||
* Работа с платформенными сервисами - вызов базовых сервисов платформы | |||
Полную документацию по работе с платформенными сервисами можно найти на [https://vendor.era-platform.ru/docs/era/latest/api/index.html портале Vendor]. | |||
Работа с сервисами продуктового слоя сводится к изучению их исходного кода (он выгружается в разделе Services). Техническая же сторона работы с вызовами описана в статье [[Разработка сервисов]]. | |||
Следующая статья курса: [[Работа с внешними системами. Возможности интеграции]] | Следующая статья курса: [[Работа с внешними системами. Возможности интеграции]] | ||
Предыдущая статья курса: [[Получение информации о пользователе]] | Предыдущая статья курса: [[Получение информации о пользователе]] | ||
[[Категория:Курс "Разработка приложений"]] | [[Категория:Курс "Разработка приложений"]] |
Текущая версия от 13:20, 13 марта 2025
Предыдущая статья курса: Получение информации о пользователе
Общая информация
В рамках разработки сервисов, одной из ключевых задач является работа с данными платформы.
Основной способ работы с данными классов в хранилище - это использование классов-обёрток. Такие классы автоматически генерируются платформой на основании настроек классов в пакетах. Эти классы выгружаются вместе с исходными кодами сервисов и могут использоваться в коде сервисов для быстрого и удобного взаимодействия с данными.
С помощью классов-обёрток возможны следующие действия с данными:
- Коллекция (classMultiName)
- Подписка на события объекта класса (Insert, Update, Delete)
- Получение объекта класса по ID
- Поиск объекта класса
- Объект класса (className)
- Создание
- Модификация
- Удаление

Рассмотрим каждое возможное действие более детально и с примерами.
Так же, для большего удоства и ориентирования по базовым классам платформы и других пакетов, удобно использовать приложение Объектная модель, которое позволяет быстро посмотреть список полей классов во всех пакетах, а также значения перечислений.
Если при работе в IDE, например Visual Studio Code, autocompletion не предлагает для выбора классы-обертки из каких либо пакетов, рекомендуется открыть в IDE index.ts файл этого пакета. В этом случае, IDE дозагрузит необходимые данные классов и они начнут появляться.
Подписка на события класса
Для доступа к событиям классов используется коллекция объектов этих классов. Её название аналогично названию classMultiName.
В примере кода ниже, создается приватное свойство класса для хранения коллекции, затем в конструкторе эта коллекция инициализируется, и далее происходит бинд события на метод внутри класса сервиса.
import { GlobalUtils, Converter } from "./../../utils";
import { Service } from "./../../platform/core";
import { ITicket, ITickets } from "../model";
import { Tickets } from "../classes";
import { IBaseEntity, IDataUpdateParams } from "../../base/model";
class Server2Service extends Service {
private _tickets: ITickets; //свойство класса, через которое мы будем доступаться к коллекции Tickets
constructor() {
super("creomate_tutorial.Server2Service");
// onCreateCode
this._tickets = new Tickets(this.context); //инициализируем коллекцию Tickets
this._tickets.onAfterInsert(this.onTicketAfterInsert.bind(this)); //привязываем метод onTicketAfterInsert к событию onAfterInsert коллекции Tickets
this.load();
}
onTicketAfterInsert(params_: IDataUpdateParams<ITicket>){
this.log.info(params_.updateKind); //В этом свойстве хранится тип опецации (удаление, изменение, добавление)
this.log.info(params_.id); //В этом свойстве хранится ID объекта, над которым была совершена операция
this.log.info(params_.entity?.subject); //В свойстве entity хранятся данные объекта, в данном случае получаем поле subject из объекта класса
}
}
export default Server2Service;
Данный пример кода будет выводить в лог-журнал информацию об операции, идентификаторе и теме обращения каждый раз при добавлении нового обращения.
Для каждого класса доступны следующие события для обработки в рамках сервиса:
- onAfterInsert - событие вызывается после добавления нового объекта класса
- onBeforeDelete - событие вызывается перед удалением объекта класса
- onAfterDelete - событие вызывается после удаления объекта класса
- onAfterModify - событие вызвается после модификации объекта класса
- onAfterReload - событие после перезагрузки класса из хранилища. Используется при потере актуальности кеша
- onAfterUpdate - универсальное событие после delete/modify/insert
В параметр функции, вызываемой каждым событием передается дженерик-параметр IDataUpdateParams, который может быть типизирован каким-либо интерфейсом.
Вариантом по-умолчанию можно считать IDataUpdateParams<IBaseEntity>, в таком случае в параметре невозможно будет получить значения свойств класса, вызвавшего событие. Будет доступен только его ID.
Однако, если использовать типизацию интерфейсом того класса, чьи изменения ожидаются, например - IDataUpdateParams<ITicket>, то через свойство entity моно получить доступ к свойствам экземпляра класса.
Также, в данном параметре передаются две коллекции - oldData и newData. В этих коллекциях можно получить изначальные и новые значения свойств объекта, при обработке событий изменения объекта.
Получение объекта класса по ID
Для получения объекта класса по его идентификатору, в коллекции присутствует два метода:
getByID - метод, позволяющий получить экземпляр класса по ID из кеша или из хранилища. Если экземпляр по ID не найден, вернет undefined
getbyIDStrong - метод, позволяющий получить экземпляр класса по ID из кеша или из хранилища. Если экземпляр по ID не найден, возникнет исключение
Оба метода являются асинхронными, соответственно, в отличии от предыдущего примера, метод класса, который их вызывает, также должен быть асинхронным.
import { GlobalUtils, Converter } from "./../../utils";
import { Service } from "./../../platform/core";
import { ITicket, ITickets } from "../model";
import { Tickets } from "../classes";
import { IBaseEntity, IDataUpdateParams } from "../../base/model";
class Server2Service extends Service {
private _tickets: ITickets; //свойство класса, через которое мы будем доступаться к коллекции Tickets
constructor() {
super("creomate_tutorial.Server2Service");
// onCreateCode
this._tickets = new Tickets(this.context); //инициализируем коллекцию Tickets
this.load();
}
async myServiceMethod(ticketId: string){
const ticket = await this._tickets.getByID(ticketId);
try{
const ticketStrong = await this._tickets.getByIDStrong(ticketId);
}catch(e){
this.log.exception("myServiceMethod: get ticket strong", e);
}
}
}
export default Server2Service;
Поиск объекта класса
Метод коллекции find позволяет осуществлять поиск по коллекции с помощью предиката.
В данном примере, по коллекции _tickets осуществляется поиск такого ticket, у котрого subject не заполнен.
import { GlobalUtils, Converter } from "./../../utils";
import { Service } from "./../../platform/core";
import { ITicket, ITickets } from "../model";
import { Tickets } from "../classes";
import { IBaseEntity, IDataUpdateParams } from "../../base/model";
class Server2Service extends Service {
private _tickets: ITickets; //свойство класса, через которое мы будем доступаться к коллекции Tickets
constructor() {
super("creomate_tutorial.Server2Service");
// onCreateCode
this._tickets = new Tickets(this.context); //инициализируем коллекцию Tickets
this.load();
}
myFindTicketMethod(ticketId: string){
const ticket = this._tickets.find(item_ => item_.subject === "");
}
}
export default Server2Service;
Создание объекта класса
Для создания нового объекта используется метод коллекции addNew.
Данный метод является асинхронным и создает новый объект класса, либо генерирует исключение.
import { GlobalUtils, Converter } from "./../../utils";
import { Service } from "./../../platform/core";
import { ITicket, ITickets } from "../model";
import { Tickets } from "../classes";
import { IBaseEntity, IDataUpdateParams } from "../../base/model";
class Server2Service extends Service {
private _tickets: ITickets; //свойство класса, через которое мы будем доступаться к коллекции Tickets
constructor() {
super("creomate_tutorial.Server2Service");
// onCreateCode
this._tickets = new Tickets(this.context); //инициализируем коллекцию Tickets
this.load();
}
async createTicketMethod(subject:string, description:string){
const newTicket = await this._tickets.addNew(ticket_=>{
ticket_.subject = subject,
ticket_.description = description
})
}
}
export default Server2Service;
Модификация объекта класса
Для изменения объекта класса, необходимо каким-либо образом получить его экземпляр. Примеры возможных вариантов получения:
- Получение entity с помощью подписки на событие
- Получение entity по ID
- Получение entity с помощью поиска find
- Получение entity как параметра метода из другого метода
После получения entity, можно напрямую изменять его свойства. Для убоства конвертации данных, представлен класс Converter, содержащий основные методы конвертации данных для их представления пользователю.
После внесения изменений в свойства класса, необходимо применить их с помощью асинхронного метода applyUpdates().
import { GlobalUtils, Converter } from "./../../utils";
import { Service } from "./../../platform/core";
import { ITicket, ITickets } from "../model";
import { Tickets } from "../classes";
import { IBaseEntity, IDataUpdateParams } from "../../base/model";
class Server2Service extends Service {
private _tickets: ITickets; //свойство класса, через которое мы будем доступаться к коллекции Tickets
constructor() {
super("creomate_tutorial.Server2Service");
// onCreateCode
this._tickets = new Tickets(this.context); //инициализируем коллекцию Tickets
this.load();
}
async modifyTicketDescription(id: string){
try{
const ticket = await this._tickets.getByIDStrong(id);
ticket.description = ticket.description + "\n" + Converter.dateTimeToFullDateDisplay(GlobalUtils.nowDateTime());
await ticket.applyUpdates();
}catch(e){
this.log.exception("modifyTicketDescription: get ticket by ID", e);
}
}
}
export default Server2Service;
Удаление объекта класса
Для удаления объекта класса, его экземпляр необходимо также получить любым из способов.
Для удаления объекта класса используется асинхронный метод delete.
Использование метода может вызвать исключение, например если какие-либо проверки прерывают операцию удаления объекта.
import { GlobalUtils, Converter } from "./../../utils";
import { Service } from "./../../platform/core";
import { ITicket, ITickets } from "../model";
import { Tickets } from "../classes";
import { IBaseEntity, IDataUpdateParams } from "../../base/model";
class Server2Service extends Service {
private _tickets: ITickets; //свойство класса, через которое мы будем доступаться к коллекции Tickets
constructor() {
super("creomate_tutorial.Server2Service");
// onCreateCode
this._tickets = new Tickets(this.context); //инициализируем коллекцию Tickets
this.load();
}
async deleteTicketById(id: string){
try{
const ticket = await this._tickets.getByIDStrong(id);
try{
await ticket.delete();
}catch(e){
this.log.exception("deleteTicketById", e);
}
}catch(e){
this.log.exception("deleteTicketById: get ticket by ID", e);
}
}
}
export default Server2Service;
Вызов сервисов платформы и работа с внутренним API
Работу с сервисами платформы можно условно разделить на две категории:
- Работа с сервисами продуктового слоя - вызов сервисов, реализованных в сторонних пакетах
- Работа с платформенными сервисами - вызов базовых сервисов платформы
Полную документацию по работе с платформенными сервисами можно найти на портале Vendor.
Работа с сервисами продуктового слоя сводится к изучению их исходного кода (он выгружается в разделе Services). Техническая же сторона работы с вызовами описана в статье Разработка сервисов.
Следующая статья курса: Работа с внешними системами. Возможности интеграции
Предыдущая статья курса: Получение информации о пользователе