Редактирование базового раздела
Технические вопросы
7.x

Добрый день, Коллеги!!!
Возникла потребность отредактировать модуль OpportunitySection. Я создал замещающий объект этого модуля, но изменения не вступили в силу (Очистка редиста, кэша была). Почему ? Есть догадка что нужно проапдейтить в базе данных айди модуля раздела? Если да тогда какие таблицы нужно апдейтить ? Или можна как то без вмешательства в бд это здалать ?

Нравится

5 комментариев

"Ильюша Сергей Николаевич" написал:

Добрый день, Коллеги!!!

Возникла потребность отредактировать модуль OpportunitySection. Я создал замещающий объект этого модуля, но изменения не вступили в силу (Очистка редиста, кэша была). Почему ? Есть догадка что нужно проапдейтить в базе данных айди модуля раздела? Если да тогда какие таблицы нужно апдейтить ? Или можна как то без вмешательства в бд это здалать ?

Подписаться на обновления этого материала


Добрый день!
Подскажите каким образом вы проверили что Ваши изменения не вступили в силу?
Вы видите свой скрипт в браузере?

"Бондаренко Александр Сергеевич" написал:Добрый день!
Подскажите каким образом вы проверили что Ваши изменения не вступили в силу?
Вы видите свой скрипт в браузере?

В браузере вижу, дебаг проходит, но интерфейс не меняется. Таблица EditPageModification пуста.
Я для теста просто сгенерил модуль с помощью NUISchemaGenerator и вставил в замещающий модуль и хотел чтобы выводилось только название в реестре

А вы заместили страницу раздела или страницу карточки?

"Бондаренко Александр Сергеевич" написал:А вы заместили страницу раздела или страницу карточки?

Раздела, в посте выше написал OpportunitySection.

Таблица EditPageModification предназначена для карточек.
У вас в таблице SysProfileData есть настроенный профиль для колонок вашего раздела.
Почистите его.

Показать все комментарии

Были в объекте две колонки, обе обязательные для заполнения.
Сейчас необходимость в обязательности отпала.
Выставил в объекте свойство "Обязателбна для заполнения" в "нет".
Перенес изменения, сгенерировал код, проверил - перенеслось, почистил профиль, редис и кеш браузера.
В странице карточки редактирования записи признаки обязательно для заполнения у полей не стоят.

Все равно поля остаются обязательными и ругается требуя их заполнить.

Это что механизьм как нипель работает? Отменить уже нельзя?

Нравится

4 комментария

Также обязательность могла проставиться в карточке в колонке датасорса. Посмотреть можно в метаданных. Исправить — там же, или же просто удалить в карточке колонку датасорса и создать заново.

о как. Попробую.

Ну у колонки датасорса в карточке редактирвоания такого признака просто нет.

А вот удаление/добавление колонок помогло. :-)
Сенькс.

Он должен быть, если установлен, видимым в метаданных. В дизайнере это свойство не показывается.

Например, поле Name у контакта в режиме редактирования:

{
  "CP1": "c7d8e34a4f1bf4788b57dcad801c2f0bb",
  "UId": "65c7bbe5-2bb3-46b9-8afc-ec988bd13bf8",
  "CP3": "Name",
  "CP5": "10e5b380-25f3-474d-8dec-6b4084180ac7",
  "CP6": "10e5b380-25f3-474d-8dec-6b4084180ac7",
  "CP25": "Name",
  "CP27": "a5cca792-47dd-428a-83fb-5c92bdd97ff8",
  "CP20": 1,
  "CP21": 1,
  "CP28": true
},

Оно же в режиме просотра:

{
  "ID": "c3980e1af43094f35b319f3eccb295ee5",
  "UId": "65c7bbe5-2bb3-46b9-8afc-ec988bd13bf8",
  "Name": "Name",
  "CreatedInSchemaUId": "10e5b380-25f3-474d-8dec-6b4084180ac7",
  "ModifiedInSchemaUId": "10e5b380-25f3-474d-8dec-6b4084180ac7",
  "Path": "Name",
  "MetaPath": "a5cca792-47dd-428a-83fb-5c92bdd97ff8",
  "OrderDirection": 1,
  "OrderPosition": 1,
  "Required": true
},

Я про дизайнер и говорил.
А в метаданных допереть что CP28 это то что нам надо -- та еще задача.
В режиме просмотра оно конечно Required, но это сначала там найти, потом сям, потом поменять. И так два раза. Проще удалить/добавить.
Ладно, проехали, главное все решается быстро и просто.

Показать все комментарии
Технические вопросы
Разработка

Работаю с довольно сильно перепиленным террасофтом. Не могу понять, почему функция, используемая во многих сервисах, не инициализирует открытие моего датасета и как следствие - заполнение грида. Всё это делается для новой группы, в новом скрипте, с новыми окнами, наследующими свойства базовых Функция следующая:

function InitializeGridData() {
        var GridWindow = wndGridData.Window;
        PrepareGridWindow(GridWindow, dlClients);
        PrepareCommonDetails('ClientsID');
}

Нравится

4 комментария

поставьте

debugger;

внутри PrepareGridWindow и посмотрите как она будет отрабатывать - станет ясно, что не работает

Артем,
попробуйте указать DataSet и открыть его, например:

SetAttribute(GridWindow, 'DatasetUSI', 'ds_Dataset');
GridWindow.ComponentsByName('dlData').Dataset.Open(); 	

Да я могу открыть датасет другим методом без проблем. Мне интересно почему не открывается именно этим, притом, в воркспейсе в невизуальных элементах указан датасет линк с именем, но в нем отсутствует ссылка на датасет впринципе. Это на аналогичных примерах и грид формируется данными, не пойми откуда. В скрипте тоже не нашел ничего касательно датасета формирующегося грида, но откуда тогда он наполняется? Вот для меня загадка.

Артем, почему же не пойми откуда?
На примере раздела "Контакты". Вот Datalink в "wnd_ContactGridArea":

Вот DataSet:

Вот установка DataSet в scr_ContactGridArea:

function Initialize(Window) {
	SetAttribute(Window, 'DatasetUSI', 'ds_Contact');
...
}

И есть инициализация в scr_ContactsWorkspace.
Может я не так понял вопрос?

Показать все комментарии
Технические вопросы
Разработка

Приветствую. Необходим приблизительный алгоритм и немножко кода для реализации задачи:)
Имеем воркспейс. В верхней части контейнер с гридом сотрудников и поле лукап для фильтра по фио, в нижней части - фрейм с 3 закладками(3 контейнера, 3 грида). Каждый должен выводить информацию, например о продажах выбранным из верхнего грида человека и т.п.
Хотелось узнать мнение опытных разработчиков о плане пошаговой реализации и хотя бы минимальную ориентацию на необходимые фрагменты кода, т.к. свои я уже набросал, но чувствую что имеется более рациональный вариант стандартными средствами террасофта. Большое спасибо преждевременно.

Нравится

1 комментарий

Во-первых, есть раздел Итоги))
Во-вторых, какого-то особого алгоритма тут нет: Вам, может быть, стоило сделать обычный раздел с тремя деталями. Посмотрите реализацию любого основного раздела (Контрагенты, Контакты) и функции обновления деталей в скриптах воркспейсов (RefreshDetails, RefresgCommonDetail)

Показать все комментарии
Технические вопросы
Разработка

Здравствуйте. В контейнер выводится грид с данными, добавление, удаление и комирование работает по принципу наследования BaseWindow. Однако, изменение не работает. И при двойном клике на строчку(элемент) в гриде открывается окошко добавления нового, с заблокированным полем и сразу же вылезает ошибка. Датасет вроде подключен...Что я забыл?

Нравится

7 комментариев

Добрый день, Артем.

Прикрепить скриншот ошибки ;)

Как правило, такие ошибки бывают при установке inner джоинов в сервисе запроса. Проверяйте sq_.

Ошибка ядра, я бы перерегистрировал библиотеки и почистил кеш. Если не поможет - отлаживался бы, чтобы понять на каком моменте происходит свал.

Данная проблема исключительно с моими новыми гридами происходит. С теми, что были раньше - всё в порядке...

"Нестеров Артем Валерьевич" написал:при двойном клике на строчку(элемент) в гриде открывается окошко добавления нового, с заблокированным полем и сразу же вылезает ошибка

как будто бы у Вас не передается ИД выделенной записи

Странно...Вопрос, с чего бы?

Вряд ли возможно ответить на этот вопрос при таком количестве входящих данных.
Подключитесь к процессу отладчиком, или отправьте сервисы в службу технической поддержки.

Показать все комментарии
Технические вопросы
7.x

Добрый день, подскажите пожалуйста как можно решить такую задачу:
На странице продаж есть группа элементов "Продукты" и група элементов "Счет", как добавленые продукты продажи подтянуть в счет продажи автоматически. Тоесть: при добавлении счета, перейдя на странину заполнения счета, в разделе продукты счета не надо было заполнять их, а там уже были подтянуты продукты которые добавили в продаже!

Нравится

3 комментария

Юрий, как я писал в ответ на обращение, подтянуть записи на деталь не получится до сохранения записи. Поэтому, рациональней было бы создать БП, который стартует по сигналу объекта Счет и имеет связь с Продажей. По процессу можно считывать данные продуктов с детали связанной продажи и создавать аналогичные записи в объекте детали продукта в счете.

Не все понял но примерно так! Сигнал(Счет, после добавления карточки)->>чтения данных(продукты в продаже, по колонке продукты)->> добавления данных (1 объект продукты в продаже добавить по колонке продукт в продукты в счете)->>завершить?

А как на странице продажи реализовать логику автосуммирования, аналогичную той, какая есть на странице Счета, когда поле Общая сумма равно сумме сумм (=)) всех продуктов на детали Продукты?

Показать все комментарии
Реализация фильтра
Технические вопросы
Разработка

Здравствуйте. Создал новый воркспейс, на нем отображается грид, в который выводятся данный из таблицы. В другом фрейме имеется лукапдатаконтрол и , в который выводятся данные, доступные для фильтрации и чекбокс, который активирует фильтр, также имеется кнопка "Применить". Вопрос в том, как пошагово реализовать работу фильтра и где подсмотреть понятную работу скрипта. В гриде выведены ID и Имя. Фильтрация по имени. Т.е. например, при параметре фильтра "Илья" должны вывестись ID всех записей с именем "Илья". Зараннее спасибо.

Нравится

2 комментария

Здравствуйте.

Подобное реализовано в базовой версии. Созданы чекбокс и лукап. При нажатии на чекбокс происходит обновление рабочего места, при изменении значении в лукапе, если чекбокс нажат, происходит обновление рабочего места. При обновлении рабочего места происходит закрытие/открытие набора данных. На событии "перед открытием набора данных" происходит фильтрация набора данных по значению лукапа.
Это алгоритм. Пример можно посмотреть в сервисах wnd_TasksWorkspace и scr_TasksWorkspace. Функции ApplyContactFilter (применение фильтра), dlTasksOnDatasetBeforeOpen (обработчик события перед открытием набора данных), edtTaskOwnerOnChange (обработчик события изменения лукапа), chbShowForContactOnClick (обработчик события нажатия чекбокса), RefreshTasks (обновление рабочего места).

Алгоритм предельно понятен, спасибо. Теперь попробуем реализацию на практике:)

Показать все комментарии
счет
Технические вопросы
7.x

Здравствуйте, подскажите пожалуйста как можно решить задачю!

В карточке продаж в группе элементов "Счета" по одному нажатию нужно формировать и прикреплять счет к этой продаже не переходя и редактирую карточку счета! тоесть: Нажимаю на кнопку Добавить и в этот момент вся информация продажи и продукты продажи в том числе, подтягивались в счет, автоматически создавали его и добавляли в группу элементов "Счет"( вообщем все что мы делаем руками при добавлении счета, нажал-> открыл-> заполнил->сохранил, делалось автоматически )
Буду благодарен за инф.

Нравится

8 комментариев

Здравствуйте.

Необходимо создать действие в карточке продажи. Для этого, необходимо создать расширяющий клиентский модуль.
В качестве родительской страницы указать соответственно страницу карточки продажи.

Далее в левом блоке кода, добавить примерно такой код:

define('OpportunityPage', ['ext-base', 'terrasoft', 'sandbox', , 'Opportunity', 'OpportunityPageStructure',
    'OpportunityPageResources', 'GeneralDetails'],
    function(Ext, Terrasoft, sandbox, Opportunity, structure, resources, GeneralDetails) {
 
        structure.userCode = function() {
 
this.methods.createInvoice = function(){             
    //код для создания счета
   //получить данные продажи можно так
   var opportunityId = this.get('Id');
   var OpportunityTitle = this.get('Title');
};
this.actions = [
{
    caption: 'Создать счет',
    methodName: 'createInvoice'
}
];
        };
     return structure;
    });

После публикации, у Вас на странице появится действие "Создать счет".
В функции createInvoice необходимо прописать логику добавления нового счета.
Как получить значения полей текущей продажи есть в примере.
Чтобы получить файлы продажи - нужно будет создавать отдельные select'ы, а затем и insert'ы.
Примеры можно посмотреть в исходных кодах конфигурации.

Дмитрий, большое Вам спасибо, просто огромное))

> Чтобы получить файлы продажи - нужно будет создавать отдельные select'ы, а затем и insert'ы.
Примеры можно посмотреть в исходных кодах конфигурации.

А можно указать место, где это можно посмотреть?

Здравствуйте, Наталья!

Пример можно посмотреть в схеме MoneyModule, функции "function onLoadCurrencyRate".

А можно перейти на страницу счета через
function goToPage()
{
var url = document.getElementById('id_Элемента');
document.location.href = url.value;
} ???
Из-за того что анг язык в BPM не работает, уж больно сложно придумывать код)

а где можно глянуть пример отображения карточки, или пример перехода по нажатию на пунк действия и переход на карточку?

Юрий,

this.add('EditPageName', null, this);

Дмитрий :lol: Большое спасибо)

Показать все комментарии
выбор
заблокированы
кнопки
Технические вопросы
Разработка

Объясняю суть проблемы:
Если пройдем по пути Раздел Счета -> Деталь Задачи (создадим новую, или изменим) -> в карточке задачи щелкаем чтобы выбрать контрагента (контакта и т.д.), появляется список (в нем кнопки Добавить, Изменить, Удалить активны)

В своем созданном разделе, детали, если пройти по такому же пути, раздел - деталь - выбор, то на гриде кнопки не активны.

Может кто сталкивался с такой проблемой, как активировать?

Нравится

1 комментарий
select
Технические вопросы
5.x

Как сконструировать условие OR в Select`е? Есть запрос на TSQL:

SELECT *
FROM
[dbo].[WorkUnitAction]
WHERE
[WorkUnitId] = @p1
AND [Id] > @p2
AND [CreatedOn] @p3
AND NOT [ActionResultId] IS NULL
AND ([GroupId] > @p4 OR GroupId IS NULL)
ORDER BY
[CreatedOn] DESC

нужно его написать на шарпе..

Нравится

3 комментария

Как-то так:

...
                .And().OpenBlock("GroupId").IsNotEqual(Column.Parameter(p4))
                        .Or("GroupId").IsNull()
                .CloseBlock()
...

Тут больше по теме.

"Зверев Александр" написал:
Тут больше по теме.

За пример спасибо! А ссылка не открывается, почему-то "У Вас нет доступа к этой странице"(

Алексей, цитирую ту самую страницу.

"Венжик Игорь" написал:

Часто возникает ситуация когда необходимо сделать специфичечкий запрос к БД, который невозможно или сложно воспроизвести с помощью бизнес-сущностей. Например запросы к таблицам прав доступа, к системным таблицам. (Не законченная статья...)

В таких случая необходимо строить кастомные запросы:

Select select =

        new Select(UserConnection)

                .Column("Id")

                .Column("SysSchemaId")

                .Column("Name")

                .Column("SysSchemaManagerName")

                .Column("SysSchemaFolderId")

                .Column("MetaDataModifiedOn")

        .From("VwSysSchemaInSolution")

        .Where("SysSolutionId").IsEqual(new QueryParameter("solutionId", userConnection.Solution.Id))

                .And("SysSchemaId").In(schemas)

                .And("SysSchemaStateInSolution").IsNotEqual(Column.Const((int)StoringObjectState.Deleted))

                .And().OpenBlock("LockedById").IsNull()

                        .Or("LockedById").IsEqual(new QueryParameter("currentUserId", userConnection.CurrentUser.Id))

                .CloseBlock()

                as Select;

Для выполнения запросов к БД в нашей системе есть специальный объект DBExecutor. Экземпляр которого содержится в каждом UserConnection-е. То есть одному пользователю всегда доступен только один экземпляр DBExecutor-а, и пользователь не может сам создавать новые экземпляры.

Что бы получить экземпляр DBExecutor-а необходимо вызвать метод UserConnection.EnsureDBConnection().

using (var dbExecutor = UserConnection.EnsureDBConnection()) {



}

Для вызова всегда необходимо использовать конструкцию using!

Давайте раcсмотрим несколько вариантов работы

Допустим нам необходимо выполнить простой запрос:

Select select =

        new Select(UserConnection)

                .Column("Name")

        .From("Contact")

        .Where("City").IsEqual(Column.Parameter("Киев"))

  1. Получение значения из первой строки, первого столбца выборки

    Есть два способа

    var name = select.ExecuteScalar<string>();

    или

    string name;

    using (var dbExecutor = UserConnection.EnsureDBConnection()) {

            name = select.ExecuteScalar<string>(dbExecutor);

    }

    Оба способа вернут один и тот же результат. Если вы выполняете одиночный запрос тогда используйте первый вариант, он является оберткой над вторым. Второй вариант, с передачей dbExecutor-а, будет полезен если выполнять несколько запросов к БД в рамках одной транзакции.

  2. Получение списка значений:

    List<string> names = new List<string>();

    using (var dbExecutor = UserConnection.EnsureDBConnection()) {

            using (var reader = select.ExecuteReader(dbExecutor)) {

                    while(reader.Read()) {

                            int columnOrdinal = reader.GetOrdinal("Name");

                            names.Add(reader.GetString(columnOrdinal));

                    }

            }

    }

  3. Выполнение запроса в рамках транзакции:

    Оба запроса в базу будут выполнены в рамках транзакции и в случае свала транзакция откатится.

    List<string> names = new List<string>();

    using (var dbExecutor = UserConnection.EnsureDBConnection()) {



    >>      dbExecutor.StartTransaction();

           

            using (var reader = select.ExecuteReader(dbExecutor)) {

                    while(reader.Read()) {

                            int columnOrdinal = reader.GetOrdinal("Name");

                            names.Add(reader.GetString(columnOrdinal));

                    }

            }

            insert.Execute(dbExecutor);



    >>      dbExecutor.CommitTransaction();



    }

    Транзакция начинается вызовом метода dbExecutor.StartTransaction и заканчивается вызовом CommitTransaction или RollbackTransaction. В случае когда выполнение вышло за область видимости блока using и CommitTransaction не был вызван, происходит автоматический откат транзакции. Таким образом нет необходимости оборачивать транзакцию в try/catch блок, т.к. если был свал во время выполнения транзакция автоматически откатится.

    Внимание! В текущей реализации даже если не передавать dbExecutor в метод Execute(), все равно запрос будет выполнен в текущей транзакции, если такая существует. Но для избежания сложностей в будущем, всегда при выполнении нескольких запросов в рамках транзакций - всегда передавайте dbExecutor в методы Execute, ExecuteReader, ExecuteScalar.

Подписаться на обновления этого материала

Показать все комментарии