Для приготовления CRUD нам понадобится 1C, Python и ... PostgreSQL. Сначала нужно включить REST OData в 1C.
Поиск будем осуществлять следующей функцией на Python
import requests # импортируем библиотеку
def filter( # определяем функцию
entity, # имя сущности
filter=None, # фильтр для поиска сущности
select=None, # выбор только заданных полей сущности
):
url = f'http(s)://1c.host.name/api/odata/standard.odata/{entity}' # конструируем адрес
headers = dict(Accept='application/json') # задаём тип ответа
params = dict() # объявляем параметры
if filter is not None: params['$filter'] = filter # если задан фильтр, то задаём его
if select is not None: params['$select'] = select # если задан выбор полей, то задаём его
response = requests.get(url, headers=headers, params=params) # выполняем запрос
try: json = response.json() # получаем результат и пытаемся преобразовать его в json
except: raise Exception(response.text) # а в случае неудачи поднимаем исключение
if 'odata.error' in json: raise Exception(json['odata.error']['message']['value']) # если в результате ошибка, то поднимаем исключение
return json['value'] # возвращаем массив сущностей
и на ... PL/pgSQL с помощью расширения pg_curl
create or replace function filter( -- создаём или меняем функцию
entity text, -- имя сущности
filter text default null, -- фильтр для поиска сущности
"select" text default null -- выбор только заданных полей сущности
) returns jsonb language plpgsql as $body$ declare -- возвращающую json на языке PL/pgSQL
url text default format($$http(s)://1c.host.name/api/odata/standard.odata/%s?$$, curl_easy_escape(entity)); -- объявляем и конструируем адрес
jsonb jsonb; -- объявляем возвращаемую переменную
text text; -- и вспомогательную переменную
begin
perform curl_easy_setopt_url(url); -- задаём адрес
perform curl_header_append('Accept', 'application/json'); -- задаём тип ответа
if filter is not null then perform curl_url_append('$filter', filter); end if; -- если задан фильтр, то задаём его
if "select" is not null then perform curl_url_append('$select', "select"); end if; -- если задан выбор полей, то задаём его
perform curl_easy_perform(); -- выполняем запрос
text = convert_from(curl_easy_getinfo_data_in(), 'utf-8'); -- получаем результат
begin jsonb = text; exception when invalid_text_representation then raise exception '%', text; end; -- пытаемся преобразовать результат в json, а в случае неудачи поднимаем исключение
if jsonb->'odata.error' is not null then raise exception '%', jsonb->'odata.error'->'message'->>'value'; end if; -- если в результате ошибка, то поднимаем исключение
return nullif(jsonb->'value', '[]'); -- возвращаем непустой массив сущностей или ничего
end;$body$;
Чтение будем осуществлять следующей функцией на Python
import requests # импортируем библиотеку
def read( # определяем функцию
entity, # имя сущности
guid, # идентификатор сущности
select=None, # выбор только заданных полей сущности
):
url = f'''http(s)://1c.host.name/api/odata/standard.odata/{entity}(guid'{guid}')''' # конструируем адрес
headers = dict(Accept='application/json') # задаём тип ответа
params = dict() # объявляем параметры
if select is not None: params['$select'] = select # если задан выбор полей, то задаём его
response = requests.get(url, headers=headers, params=params) # выполняем запрос
try: json = response.json() # получаем результат и пытаемся преобразовать его в json
except: raise Exception(response.text) # а в случае неудачи поднимаем исключение
if 'odata.error' in json: raise Exception(json['odata.error']['message']['value']) # если в результате ошибка, то поднимаем исключение
return json # возвращаем сущность
и на ... PL/pgSQL
create or replace function read( -- создаём или меняем функцию
entity text, -- имя сущности
guid uuid, -- идентификатор сущности
"select" text default null -- выбор только заданных полей сущности
) returns jsonb language plpgsql as $body$ declare -- возвращающую json на языке PL/pgSQL
url text default format($$http(s)://1c.host.name/api/odata/standard.odata/%s(guid'%s')?$$, curl_easy_escape(entity), curl_easy_escape(guid::text)); -- объявляем и конструируем адрес
jsonb jsonb; -- объявляем возвращаемую переменную
text text; -- и вспомогательную переменную
begin
perform curl_easy_setopt_url(url); -- задаём адрес
perform curl_header_append('Accept', 'application/json'); -- задаём тип ответа
if "select" is not null then perform curl_url_append('$select', "select"); end if; -- если задан выбор полей, то задаём его
perform curl_easy_perform(); -- выполняем запрос
text = convert_from(curl_easy_getinfo_data_in(), 'utf-8'); -- получаем результат
begin jsonb = text; exception when invalid_text_representation then raise exception '%', text; end; -- пытаемся преобразовать результат в json, а в случае неудачи поднимаем исключение
if jsonb->'odata.error' is not null then raise exception '%', jsonb->'odata.error'->'message'->>'value'; end if; -- если в результате ошибка, то поднимаем исключение
return jsonb; -- возвращаем сущность
end;$body$;
Создание будем осуществлять следующей функцией на Python
import requests # импортируем библиотеку
def create( # определяем функцию
entity, # имя сущности
data, # тело сущности
select=None, # выбор только заданных полей сущности
):
url = f'http(s)://1c.host.name/api/odata/standard.odata/{entity}' # конструируем адрес
headers = dict(Accept='application/json') # задаём тип ответа
response = requests.post(url, headers=headers, data=data) # выполняем запрос
try: json = response.json() # получаем результат и пытаемся преобразовать его в json
except: raise Exception(response.text) # а в случае неудачи поднимаем исключение
if 'odata.error' in json: raise Exception(json['odata.error']['message']['value']) # если в результате ошибка, то поднимаем исключение
if select is not None: return read(entity, json['Ref_Key'], select) # если задан выбор полей, то заново читаем и возвращаем сущность
return json # иначе просто возвращаем сущность
и на ... PL/pgSQL
create or replace function "create"( -- создаём или меняем функцию
entity text, -- имя сущности
jsonb jsonb, -- тело сущности
"select" text default null -- выбор только заданных полей сущности
) returns jsonb language plpgsql as $body$ declare -- возвращающую json на языке PL/pgSQL
url text default format($$http(s)://1c.host.name/api/odata/standard.odata/%s?$$, curl_easy_escape(entity)); -- объявляем и конструируем адрес
text text; -- объявляем вспомогательную переменную
begin
perform curl_easy_setopt_postfields(convert_to(jsonb::text, 'utf-8')); -- задаём тело
perform curl_easy_setopt_url(url); -- задаём адрес
perform curl_header_append('Accept', 'application/json'); -- задаём тип ответа
perform curl_easy_perform(); -- выполняем запрос
text = convert_from(curl_easy_getinfo_data_in(), 'utf-8'); -- получаем результат
begin jsonb = text; exception when invalid_text_representation then raise exception '%', text; end; -- пытаемся преобразовать результат в json, а в случае неудачи поднимаем исключение
if jsonb->'odata.error' is not null then raise exception '%', jsonb->'odata.error'->'message'->>'value'; end if; -- если в результате ошибка, то поднимаем исключение
if "select" is not null then return read(entity, (jsonb->>'Ref_Key')::uuid, "select"); end if; -- если задан выбор полей, то заново читаем и возвращаем сущность
return jsonb; -- иначе просто возвращаем сущность
end;$body$;
Удаление будем осуществлять следующей функцией на Python
import requests # импортируем библиотеку
def delete( # определяем функцию
entity, # имя сущности
guid, # идентификатор сущности
):
url = f'''http(s)://1c.host.name/api/odata/standard.odata/{entity}(guid'{guid}')''' # конструируем адрес
headers = dict(Accept='application/json') # задаём тип ответа
response = requests.delete(url, headers=headers) # выполняем запрос
try: json = response.json() # получаем результат и пытаемся преобразовать его в json
except: raise Exception(response.text) # а в случае неудачи поднимаем исключение
if 'odata.error' in json: raise Exception(json['odata.error']['message']['value']) # если в результате ошибка, то поднимаем исключение
и на ... PL/pgSQL
create or replace function delete( -- создаём или меняем функцию
entity text, -- имя сущности
guid uuid -- идентификатор сущности
) returns void language plpgsql as $body$ declare -- ничего не возвращающую на языке PL/pgSQL
url text default format($$http(s)://1c.host.name/api/odata/standard.odata/%s(guid'%s')?$$, curl_easy_escape(entity), curl_easy_escape(guid::text)); -- объявляем и конструируем адрес
jsonb jsonb; -- объявляем вспомогательную переменную
text text; -- и ещё одну
begin
perform curl_easy_setopt_customrequest('DELETE'); -- задаём тип запроса
perform curl_easy_setopt_url(url); -- задаём адрес
perform curl_header_append('Accept', 'application/json'); -- задаём тип ответа
perform curl_easy_perform(); -- выполняем запрос
text = convert_from(curl_easy_getinfo_data_in(), 'utf-8'); -- получаем результат
begin jsonb = text; exception when invalid_text_representation then raise exception '%', text; end; -- пытаемся преобразовать результат в json, а в случае неудачи поднимаем исключение
if jsonb->'odata.error' is not null then raise exception '%', jsonb->'odata.error'->'message'->>'value'; end if; -- если в результате ошибка, то поднимаем исключение
end;$body$;
Обновление будем осуществлять следующей функцией на Python
import requests # импортируем библиотеку
def update( # определяем функцию
entity, # имя сущности
guid, # идентификатор сущности
data, # тело сущности
select=None, # выбор только заданных полей сущности
):
url = f'''http(s)://1c.host.name/api/odata/standard.odata/{entity}(guid'{guid}')''' # конструируем адрес
headers = dict(Accept='application/json') # задаём тип ответа
response = requests.patch(url, headers=headers, data=data) # выполняем запрос
try: json = response.json() # получаем результат и пытаемся преобразовать его в json
except: raise Exception(response.text) # а в случае неудачи поднимаем исключение
if 'odata.error' in json: raise Exception(json['odata.error']['message']['value']) # если в результате ошибка, то поднимаем исключение
if select is not None: return read(entity, json['Ref_Key'], select) # если задан выбор полей, то заново читаем и возвращаем сущность
return json # иначе просто возвращаем сущность
и на ... PL/pgSQL
create or replace function update( -- создаём или меняем функцию
entity text, -- имя сущности
guid uuid, -- идентификатор сущности
jsonb jsonb, -- тело сущности
"select" text default null -- выбор только заданных полей сущности
) returns jsonb language plpgsql as $body$ declare -- возвращающую json на языке PL/pgSQL
url text default format($$http(s)://1c.host.name/api/odata/standard.odata/%s(guid'%s')?$$, curl_easy_escape(entity), curl_easy_escape(guid::text)); -- объявляем и конструируем адрес
text text; -- объявляем вспомогательную переменную
begin
perform curl_easy_setopt_customrequest('PATCH'); -- задаём тип запроса
perform curl_easy_setopt_postfields(convert_to(jsonb::text, 'utf-8')); -- задаём тело
perform curl_easy_setopt_url(url); -- задаём адрес
perform curl_header_append('Accept', 'application/json'); -- задаём тип ответа
perform curl_easy_perform(); -- выполняем запрос
text = convert_from(curl_easy_getinfo_data_in(), 'utf-8'); -- получаем результат
begin jsonb = text; exception when invalid_text_representation then raise exception '%', text; end; -- пытаемся преобразовать результат в json, а в случае неудачи поднимаем исключение
if jsonb->'odata.error' is not null then raise exception '%', jsonb->'odata.error'->'message'->>'value'; end if; -- если в результате ошибка, то поднимаем исключение
if "select" is not null then return read(entity, (jsonb->>'Ref_Key')::uuid, "select"); end if; -- если задан выбор полей, то заново читаем и возвращаем сущность
return jsonb; -- иначе просто возвращаем сущность
end;$body$;
Можно ещё сделать кеширование при чтении и обновление только при изменении.
Комментарии (4)
Deterok
18.05.2022 13:13+1Хаатит уже уродовать так Python. Отвратительное вырвиглазное форматирвоание.
shibanovan
Как то не тянет это на статью на хабре) Для подобного есть github
Вы бы рассказали, с какой задачей столкнулись, рассказали бы что реализовали всем этим кодом
Еще не понятно зачем тут PL/SQL?
RekGRpth Автор
загружаю в 1C из биллинга
Контрагенты
Номенклатура
РеализацияТоваровУслуг
СчетНаОплатуПокупателю
СчетФактураВыданный
PL/pgSQL потому, что в биллинге используется база PostgreSQL и проще было загрузку сделать асинхронно с помощью планировщика
shibanovan
А python, видимо, тоже пригодился?