Документы
Как в документе отключить сообщение о непроданных товарах стандартного ассортимента?
Необходимо добавить action-скрипт на точку расширения stmobile://module/skudocs/config в котором конфигурируется соответствующий параметр:
function doAction() {
var conf = {
"isNeedCheckUnsoldAssortment": false
}
api.result.setConfig(conf);
}
Как добавить в документ свою колонку с каким-то значением?
Добавление кастомной колонки в документ осуществлется двумя action-скриптами: один на preopen, другой на iteminit.
Скрипт на preopen будет вызван однажды при открытии документа и служит для добавления колонки, а скрипт на iteminit будет вызван для каждой строки документа и служит для заполнения значения.
Создайте два каталога:
preopen и
iteminit.
Манифест action-скрипта на событие preopen будет выглядеть следующим образом:
{
"uri": "stmobile://action/<ДОКУМЕНТ>/preopen",
"type": "action",
"datascript": {
"script_file": "preopen.js"
}
}
Где <ДОКУМЕНТ> - название документа, например
preorder.
Теперь создайте соответствующий data-скрипт с именем
preopen.js.
Создание колонки осуществляется следующим образом:
var newAttr = api.form.newRowsAttribute('columnNameHere'); // Добавление колонки
newAttr.title = "Название колонки"; // Установка заголовка
Более подробно о доступных полях: Attribute
Добавьте схожим образом манифест скрипта на событие iteminit:
{
"uri": "stmobile://action/<ДОКУМЕНТ>/iteminit",
"type": "action",
"datascript": {
"script_file": "iteminit.js"
}
}
И создайте data-скрипт
iteminit.js.
В data-скрипте необходимо получить доступ к конкретному строчному атрибуту:
var currAttr = api.form.rowAttribute('columnNameHere', api.context.rowItemId);
currAttr.value = 42; // установка значения
Для обмена данными между двумя скриптами используйте
кэш.
Для работы необходимо создать манифест обработчика действия (action) на URI
stmobile://document/tma/form/config.
Дата-скрипт должен содержать следующую функцию (
имя функции предопределено):
function mtcall_mechanicsFormConfig() {
var config = {
conditionsPanelVisible: true, // отображение блока "Условие акции"
conditionsPanelEnabled: false, // редактирование блока "Условие акции"
bonusPanelVisible: true, // отображение блока "Бонус"
bonusPanelEnabled: false // редактирование блока "Бонус"
}
api.result.setConfig(config)
}
api.result.setConfig принимает в качестве параметра объект и устанавливает конфигурацию формы.
Для работы необходимо создать манифест обработчика действия (action) на URI
stmobile://document/survey/form/config.
Дата-скрипт должен содержать следующую функцию (
имя функции предопределено):
function mtcall_editAnswerConfig() {
var config = {
isAllowedBarcodeManualEdit: true, // включить редактирование штрихкода
}
api.result.setConfig(config)
}
api.result.setConfig принимает в качестве параметра объект и устанавливает конфигурацию формы.
Почему я не могу установить новое значение в документе из точки расширения itemchange?
Точка расширения itemchange срабатывает при изменении значения в колонке. Однако, если установить новое значение (value) у объекта, возвращаемого методом api.form.rowAttribute, то значение в дальнейшем перезапишется тем, что хранится в памяти калькулятора. Поэтому единственно верным вариантом является установка необходимого значения в точках расширения itempresave или itempostsave, а точка расширения itemchange может служить лишь для получения очередного вводимого значения.
Как работать с обработчиками действий "Акции и бонусы"?
stmobile://tma/bonus/preregistration
Вызывается перед проведением бонуса и позволяет изменить параметры, передающиеся на проведение (количество бонусных балов, скидка и etc), так же позволяет провести прерывание процесса оформления бонуса.
На вход передается структура registerData в контексте (api.context.registerData), структура имеет вид:
{
bonusItemsList:
[
{
skuId: ID // идентификатор товара к которому применяется бонус
value: number // количество бонусов
},
... ,
],
bonusPoint: number // количество бонусных балов переданных на сохранение, не доступно к изменению
}
На выход скрипта надо передать точно такую же структуру, она подменит текущую переданную на сохранение.
Если структура будет пуста, в базу ничего не будет записано, но бонусные баллы будут потрачены:
api.result.setData("bonusItemsList" , {...});
api.result.setData("bonusPoint" , 1);
stmobile://tma/bonus/postregistration
Вызывается после проведение бонуса и только регистрирует факт проведения.
Не требует возвращения данных
stmobile://tma/bonus/preunregistration
Вызывается перед отменой бонуса и позволяет изменить параметры передающиеся на отмену (количество бонусных балов, скидка и etc), так же позволяет провести прерывание процесса отмены бонуса.
Работа со структурами подобна preregistration.
stmobile://tma/bonus/postunregistration
Вызывается после отмены бонуса и только регистрирует факт проведения
Не требует возвращения данных
Как заполнить опросный лист своими значениями ?
Чтобы заполнить документ ОЛ своими значениями по умолчанию, необходимо использовать точку расширения stmobile://document/survey/customanswers.
Манифест скрипта:
{
"uri": "stmobile://document/survey/customanswers",
"type": "action",
"datascript": {
"script_file": "customAnswers.js"
}
}
Содержимое файла customAnswers.js:
function doAction() {
const { distributorId, templateId } = api.context;
const topics = api.survey.service.topics(templateId).value;
const answers = [];
topics.forEach((topic) => {
const questions = api.survey.service.questions(templateId, topic.id, distributorId).value;
questions.forEach((question) => {
const { possibleValues } = question.answerValuesRange;
const answer = {
topicId: topic.id,
questionId: question.id,
values: [],
};
switch (question.answerType) {
case 'DataTypeInteger':
answer.values.push(357);
break;
case 'DataTypeReal':
answer.values.push(111.111);
break;
case 'DataTypeYesNo':
answer.values.push(1);
break;
case 'DataTypeYesNoUnknown':
answer.values.push(2);
break;
case 'DataTypeSingle':
answer.values.push(possibleValues[1].value);
break;
case 'DataTypeMultiple':
answer.values.push(possibleValues[1].value);
break;
case 'DataTypeText':
answer.values.push('text');
break;
case 'DataTypeBarCode':
answer.values.push('1q2w3e4r5t');
break;
case 'DataTypeDate':
answer.values.push(new Date(2019, 3, 25));
break;
case 'DataTypeTime':
answer.values.push(new Date(1900, 0, 1, 2, 30));
break;
case 'DataTypeDateTime':
answer.values.push(new Date(2019, 3, 25, 14, 40));
break;
default:
answer.values.push('-');
}
answers.push(answer);
});
});
api.result.setParams("customAnswers", answers);
}
Как кастомизировать серийные расширения через настройки манифеста в репозитории "mt_extensions"?
stmobile://tma/bonus/preregistration
Для кастомизации в шаблон или data-скрипт необходимо добавить условия и методы, расширяющие текущий функционал,
а также условия управления новым функционалом, которые зависят от наличия/отсутствия полученных через
api.context.metaConfig настроек.
В
additionalFiles инди-конфигурации нужно добавить, сохраняя вложенность папок серийного расширения,
manifest.json с полем config,
в котором указаны настройки для работы нового функционала. Data-скрипт и шаблон указывать не нужно.
Ниже представлены реализации с описанием и настройками манифеста.
Отображение значений доп. атрибута заголовочной части документа "Отгрузка" для отчёта "Продажи. Кратко"
Данное дополнение позволяет выводить один доп. атрибут заголовочной части документа "Отгрузка" для отображения в отчёте "Продажи. Кратко".
Для этого необходимо задать код доп. атрибута и указать его в manifest.json. В отчёте будет отображаться колонка с названием этого доп. атрибута и соответствующие значения для документов.
Пример настройки манифеста с доп. атрибутом "Источник заказа":
{
"uri": "stmobile://report/routeandoutletreports/sales_documents",
"type": "report",
"title": "qsTr(Sales. Short)",
"config": {
"extAttrCode": "Sales_PreorderSource"
}
}
Визиты
Как отменить автоматический вывод выбора результата посещения ТТ и вернуть свое значение?
Для отмены автоматического запроса результата визита необходимо вернуть из скрипта visit/presave resultId посредством api.result.setData. Получение модели результатов посещения осуществляется методом api.visits.reasonModel
Примерный скрипт на presave визита:
var reasons = api.visit.reasonModel();
var ret = api.interactive.selectSingleValue("Результат посещения", reasons, reasons[0].value);
if (!ret.success) {
// нажали "Отмена"
...
}
else {
var reasonId = ret.value;
api.result.setData("reasonId", reasonId);
}
Карточка ТТ
Как настроить отображение модулей в карточке ТТ?
1. Откройте файл manifest.json карточки ТТ в вашей папке МТ:
\extensions\reports\outletreport\manifest.json
2. Найдите в файле manifest.json пункт "config", подпункт "modules".
Для каждого подключенного модуля есть свой набор свойств в подпункте "modules".
Cписок доступных модулей (актуально для версии 4.4.8):
1. last_visits - Последние визиты
2. limits - Лимиты
3. matched_outlets - Сопоставленные точки
4. outlet_photos - Фотографии точки
5. properties - Общая информация
6. visits_calendar - Календарь визитов
Содержимое файла manifest.json
{
...
"config": {
"settingsKey": "myreport_open_modules",
"modules": [
{
"name": "my_module", // имя подключенного модуля (обязат.)
"position": 1, // порядок сортировки (обязат.)
"uiName": "qsTr(My module)", // заголовок, который будет отображен в интерфейсе (обязат.)
"visibilityCheck": true, // проверка отображения модуля
"reloadCheck": "self", // проверка необходимости перезагрузки модуля
"isDisabled": false // отключение загрузки модуля
}
]
}
...
}
Изменение порядка модулей
- Модули выстраиваются в колонку (сверху вниз). На порядок сортировки указывает свойство "position".
- Чем меньше значение "position", тем ближе к началу.
- Чтобы изменить положение модуля, замените для него свойство "position", например, "position": 4,.
Загрузка модуля
- Для того, чтобы модуль не загружался установите для него свойство "isDisabled" в значение true.
ВАЖНО!
формат json очень требователен к синтаксису:
- строки в двойных кавычках
- числа и булевы значения без кавычек
- сохраняйте знаки препинания
- комментарии запрещены
Формы
Почему не обновляется значение атрибута при использовании api.form.rowAttribute?
Чтобы настройки для атрибута применялись из скрипта, а не из конфига, для атрибута необходимо установить флаг
force:
// Скрываем колонку
const rest = api.form.rowAttribute('NameRestStore');
rest.force = true;
rest.view = false;
JavaScript
Почему в новых версиях МТ у меня не работает регулярное выражение? (а раньше работало)
Скорее всего в регулярном выражении используется флаг
g. JS-движок старых версий МТ не совсем точно следовал букве стандарта, в связи с чем значение свойства lastIndex сбрасывалось при повторном выполнении сравнения. Однако, это не верно, необходимо сбрасывать указатель. Пример:
// Было
...
for (var i = 0; i <= length; i++) {
var reg = /(привет)?/g;
var match = reg.exec(data[i]);
if (match[1]) result.push(match[1]);
}
...
// Надо
...
var reg = /(привет)?/g;
for (var i = 0; i <= length; i++) {
var match = reg.exec(data[i]);
if (match[1]) result.push(match[1]);
reg.lastIndex = 0;
}
...
HTML
Как вывести шаблонизатором несколько раз одно и то же
Встроенный в МТ шаблонизатор Grantlee имеет недокументированный тэг range, работающий аналогично одноименной функции языка Python. Примеры:
<ul>
{% range 5 as num %}
<li>{{ num }}</li>
{% endrange %}
</ul>
Получится:
<ul>
{% range 5 10 as num %}
<li>{{ num }}</li>
{% endrange %}
</ul>
Получится:
<ul>
{% range 5 30 5 as num %}
<li>{{ num }}</li>
{% endrange %}
</ul>
Получится:
Датаскрипт:
...
mapper.rating = 4;
...
{% range rating %}
*
{% endrange %}
Получится:
* * * *
Как исправить проблемы с отображением контента когда что-либо оказывается поверх WebView (контекстные меню, глобальное меню, интерактивы)?
Необходимо добавить мета-тег в заголовочную часть шаблона HTML, содержащий поля
name со значением
snapshot и
content со значением
EnablePixelCopy:
<meta name="snapshot" content="EnablePixelCopy" />
Не работает API
Копирование/вставка наименований методов из документации
В документации в заголовках api могут присутствовать некорректные символы, а именно, одна из точек является другим символом юникода.
Копирование методов из документации в код может привести к синтаксическим ошибкам при исполнении.
// Примерный текст ошибки
Can not call method of undefined
При этом линтер не подчеркнет некорректные символы, а внешне они будут выглядеть одинаково.
SQL
Почему на устройстве я получаю ошибку "too many terms in compound SELECT"?
Сократите количество выражений SELECT, превышен их лимит (500), скорее всего неудачно сформирован запрос.
Общее
Как поменять глобальное меню и/или добавить свои пункты?
Создайте action-скрипт на URI stmobile://globalmenu/items
В функции doAction необходимо получить посредством api.context.config массив объектов в формате JSON, который содержит структуры, описывающие каждый элемент меню. Далее можно заменить или добавить пользовательские элементы, после чего отдать полученный массив обратно при помощи api.result.setConfig. В каждом элементе обязательно должны быть заполнены поля name, title, uri.
Внимание: в примере проверка по совпадению имени модуля является регистронезависимой.
Пример реализации расширения для кастомизации глобального меню:
function doAction() {
var defaultItems = api.context.config;
var userDefinedItems = [
{
"name": "Summary",
"icon": "globalmenu/dashboard",
"title": "Summary",
"uri": "stmobile://dashboard"
},
{
"name": "route",
"icon": "globalmenu/route",
"title": "Supervisor Routes",
"uri": "stmobile://route",
"subtitle": "Ленинградский р-н"
}
];
for (var i = 0; i < userDefinedItems.length; i++) {
var isFound = false;
for(var j = 0; j < defaultItems.length; j++) {
var userObject = userDefinedItems[i];
var defaultObject = defaultItems[j];
if (defaultObject.hasOwnProperty["name"] &&
defaultObject["name"].toLowerCase() === userObject["name"].toLowerCase())
{
defaultObject["title"] = userObject["title"];
defaultObject["icon"] = userObject["icon"];
defaultObject["uri"] = userObject["uri"];
defaultObject["subtitle"] = userObject["subtitle"];
isFound = true;
}
}
if (!isFound) defaultItems.push(userObject);
}
api.result.setConfig(defaultItems);
api.result.type = "ok";
}