Доброго дня!

Приведу пример на стандартных объектах. В карточке Контрагента есть поле Страна. В справочник Страна добавлено поле Источник. Нужно в поле Источник записывать информацию о том, из какого объекта (контрагента) была создана эта запись. 

Сценарий такой:

- Пользователь через лукап в поле Страна открывает окно поиска

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

 

Вопрос. Как сохранить сведения об источнике добавления записи...что она добавлена именно из этого контрагента?

Есть похожая тема: https://community.terrasoft.ru/questions/zapolnenie-polei-v-kartocke-pr… там нет решения.. и новых ответов тоже.

 

Спасибо!

 

Нравится

4 комментария
Лучший ответ

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

Думаю простого решения нет, как вариант сохранить в сессии пользователя источник (название страницы редактирования) переопределить добавление записи в LookupPage (заполнять источник из сессии)

Если делать свою страницу выбора со справочника (наследник LookupPage), то потом можно его подключить добавив в атрибут (Пример для страницы выбора из справочника городов): 

"City": {
	"dataValueType": Terrasoft.DataValueType.LOOKUP,
	"lookupListConfig": {
		lookupPageName: "MyBaseLookup",
	}
}

Подробнее тут

Так же похожий вопрос обсуждался тут

 

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

Тогда можно ещё проще: при сохранении контрагента во встроенном или отдельном БП проверять значение «Страна.Источник» и если там пусто, заполнять Id этого контрагента.

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

 

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

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

Пытаюсь синхронизировать Организационные роли с AD, при запуске синхронизации пользователи перемещаются, но в журнале появляется ошибка "Terrasoft.Common.DbOperationException: The UPDATE statement conflicted with the FOREIGN KEY constraint "FKMpbRxbvqMdsx1Iial2kKB1MywA". The conflict occurred in database "TerrasoftDB", table "dbo.Account", column 'Id'."

FK связывает столбец AccountId в таблице Contact и Id в Account.

Id в таблице проверил, пустых и битых нет.

Не подскажете, куда копать?

Нравится

8 комментариев
Лучший ответ

В синхронизации с АД в лоб был зашит контрагент с именем Наша компания и id="E308B781-3C5B-4ECB-89EF-5C1ED4DA488E"

Проверьте что в базе (таблица Account) есть такой Id. Если нет создайте запись. Контрагента наша компания не рекомендуется удалять лучше  его переименовать в название вашей компании!

Обычно такая ошибка может возникнуть, если в поле пытаются вставить Id, которого нет в базе данных. В данном случае Id из таблицы Account.

Посмотрите sql-профайлером, на каком именно запросе происходит свал и проанализируйте его значения.

В синхронизации с АД в лоб был зашит контрагент с именем Наша компания и id="E308B781-3C5B-4ECB-89EF-5C1ED4DA488E"

Проверьте что в базе (таблица Account) есть такой Id. Если нет создайте запись. Контрагента наша компания не рекомендуется удалять лучше  его переименовать в название вашей компании!

Спасибо, Алла, нашел ошибку с помощью Профайлера.

Спасибо, Григорий, вы правы, контрагента с таким Id в таблице нет, но и в свойствах контакта указан другой контрагент с именем Восток Запад и типом "Наша компания", который существует. Не пойму откуда взялся Id E308B781-3C5B-4ECB-89EF-5C1ED4DA488E? Создать конечно могу, но разобраться бы как это работает.

Виталий Егоров,

Если наткнулись на E308B781-3C5B-4ECB-89EF-5C1ED4DA488E, то как я и писал в лоб зашито в интеграции с АД :) Лучше востановите контрагента

Спасибо, Григорий.

А не помните случайно, в какой схеме это можно увидеть?

Виталий Егоров,

Увы нет, но она в нескольких местах вылазила недавно вот всплыла в формировании счета на оплату.

Например, если поискать через базу по коду, в схеме AccountConsts и в БП объекта Invoice упомянут этот GUID.

select *
from SysSchemaSource
where source like '%E308B781-3C5B-4ECB-89EF-5C1ED4DA488E%'

 

Всем огромное спасибо, ошибка устранена.

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

Коллеги,

Читаю в документации по бизнес-процессам как можно обрабатывать параметры типа "коллекция". В частности такой фрагмент "...Также обработать параметры типа “коллекция” можно с помощью элемента [Задание-сценарий]. Например, можно использовать сценарий для преобразования коллекций записей в отдельные записи, которые можно передать в другие элементы процесса...". Но, к сожалению, не нашел примеров такого сценария. Не может ли кто-то привести пример кода элемента бизнес-процесса [Задание-сценарий] для работы с параметром типа "коллекция"?

Заранее спасибо.

Нравится

5 комментариев
Лучший ответ

Добрый день!

Пример работы с коллекцией (после элемента "Считать данные"):

var entities = Get<ICompositeObjectList<ICompositeObject>>("ReadDataUserTask1.ResultCompositeObjectList");
 
var result = "";
 
foreach(var entity in entities) 
{
    	var Name = "";
    	if (entity.TryGetValue<string>("Number", out Name))
    	{
    		result = result + Name + ", ";  
    	}
}
 
return true;

 

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

 

Добрый день!

Пример работы с коллекцией (после элемента "Считать данные"):

var entities = Get<ICompositeObjectList<ICompositeObject>>("ReadDataUserTask1.ResultCompositeObjectList");
 
var result = "";
 
foreach(var entity in entities) 
{
    	var Name = "";
    	if (entity.TryGetValue<string>("Number", out Name))
    	{
    		result = result + Name + ", ";  
    	}
}
 
return true;

 

Григорий Чех,

Большое спасибо.

Сидоров Александр В.,

 Большое спасибо.

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

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

Здравствуйте, коллеги!

Создал по аналогии с CreateInvoiceFromOrder создание счета из договора - CreateInvoiceFromContract

Все работает отлично, за исключением одного момента

В новом счете не заполняется поле Supplier (подразумевается, что это наша компания), всегда пустое после открытия карточки.

Ранее обнаружил, что и CreateInvoiceFromOrder не работал, ибо что то там foreign key в таблице Account, оказалось, что в в объекте Invoice по умолчанию стояло заполнять это поле каким то левым гуидом e308b781-3c5b-4ecb-89ef-5c1ed4da488e. Я это дело исправил в одном из своих пакетов, но видно все равно это как то сказывается.

Прошу помощи.

Нравится

11 комментариев
Лучший ответ

Борис Леонов,

namespace Terrasoft.Configuration

{

    public static class AccountConsts

    {

        public static readonly Guid OurCompanyAccountId = new Guid("E308B781-3C5B-4ECB-89EF-5C1ED4DA488E");

    }

}

OurCompanyAccountId  это Id Нашей компании, рекомендуется при начале внедрения эту запись переименовать в название вашей компании, возможно вы ее удалили изза этого и могли возникнуть проблемы в работе с созданием счета

В чем вы просите помощи?

Добрый день!

В БП  CreateInvoiceFromOrder есть метод

public virtual void CreateInvoice() {
	OrderInvoiceHelper helper = Factories.ClassFactory.Get<OrderInvoiceHelper>(new Factories.ConstructorArgument("userConnection", UserConnection));
CreatedInvoiceId = helper.CreateEntity("Order", "Invoice", CurrentOrder, new Dictionary<string, string> {
	{"Currency", "Currency"},
	{"CurrencyRate", "CurrencyRate"},
	{"Contact", "Contact"},
	{"Account", "Account"},
	{"Owner", "Owner"},
	{"Amount", "Amount"},
	{"Opportunity", "Opportunity"}
}, new Dictionary<string, object> { { "Order", CurrentOrder } });
}

который создает Invoice по Order. 3им параметром идет словарь-маппинг полей Invoice по Order, 4ым параметром (new Dictionary<string, object> { { "Order", CurrentOrder } }) предустановленные параметры. Вот ваш Supplier надо добавить туда

Григорий Чех пишет:

В чем вы просите помощи?

Победить глюк с незаполнением Supplier в новом счете.

Сидоров Александр В.,

Александр, мой вариант сейчас выглядит так:

public virtual void CreateInvoice() {
	OrderInvoiceHelper helper = Factories.ClassFactory.Get&lt;OrderInvoiceHelper&gt;(new Factories.ConstructorArgument("userConnection", UserConnection));
	var createdInvoiceId = helper.CreateEntity(
		"Contract", "Invoice", Get&lt;Guid&gt;("CurrentContract"), new Dictionary&lt;string, string&gt; {
			{"Currency", "Currency"},
			{"CurrencyRate", "CurrencyRate"},
			{"Contact", "Contact"},
			{"Account", "Account"},
			{"CustomerBillingInfo","CustomerBillingInfo"},
			{"OurCompany", "Supplier"},
			{"SupplierBillingInfo", "SupplierBillingInfo"},
			{"Owner", "Owner"},
			{"Amount", "Amount"},
			{"Order","Order"},
			{"Opportunity", "Opportunity"}
		},
		new Dictionary&lt;string, object&gt; {
			{"Contract", Get&lt;Guid&gt;("CurrentContract")},
			{"ZLPaymentType", Get&lt;Guid&gt;("PaymentType")}
		});
	Set("CreatedInvoiceId", createdInvoiceId);
}

 

Про левый Guid в значении по умолчанию для Supplier в Invoice имею в виду это:

я переопределил это безобразие на "не устанавливать значение по умолчанию" в своем пакете, CreateInvoiceFromOrder заработал, но лишь потому, что  в Заказе нет полей с нашей компанией (поставщиком), нечем в счете заполнять.

откуда лезет этот e308b781-3c5b-4ecb-89ef-5c1ed4da488e, причем у объектов в залоченных фирменных террасофтовских пакетах?

Борис Леонов,

namespace Terrasoft.Configuration

{

    public static class AccountConsts

    {

        public static readonly Guid OurCompanyAccountId = new Guid("E308B781-3C5B-4ECB-89EF-5C1ED4DA488E");

    }

}

OurCompanyAccountId  это Id Нашей компании, рекомендуется при начале внедрения эту запись переименовать в название вашей компании, возможно вы ее удалили изза этого и могли возникнуть проблемы в работе с созданием счета

Борис Леонов,

{"OurCompany", "Supplier"}, - это значит значение из поля OurCompany объекта Contract скопировать в поле Supplier объекта Invoice.
Если вам надо именно одно и то же значение всегда записывать, то вам надо добавить параметр в словарь 
new Dictionary<string, object> {
			{"Contract", Get<Guid>("CurrentContract")},
			{"ZLPaymentType", Get<Guid>("PaymentType")}
		}

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

Григорий Чех,

Владимир Соколов,

удалили, вероятней всего когда когда клиент объединял несколько «нечаянно» созданных компаний.

Если я руками создам Account с нужным Id и объединю его с существующей «нашей компанией», проблема решится?

Да должно

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

Добрый день!

Работаю на локальной среде, которая подключена к SVN.

Была необходимость отменить все изменения, которые были выполнены в текущей конфигурации. Для этого воспользовался действием [Восстановить из хранилища]. После этого заметил следующее: При попытки зафиксировать пакет, в котором нет изменных элементов, система предлагает зафиксировать ресурсы схем, где я делал изменения до восстановления из хранилища. Подскажите, пожалуйста, это нормальное поведение системы? разве действие восстановить из хранилища не должно полностью вернуть систему до последнего зафиксированного состояния в хранилище?

(После восстановления чистил Redis, кэш и очистил папку TerrasoftPackeges)

Спасибо!

Нравится

1 комментарий
Лучший ответ

У меня тоже предлагало, походу ориентируется на время модификации схем.

Оно есть в дескрипторах выгруженных схем, если вы работаете с разработкой в файловой системе,  descriptor.json("ModifiedOnUtc": "\/Date(1547502490000)\/",)

У меня тоже предлагало, походу ориентируется на время модификации схем.

Оно есть в дескрипторах выгруженных схем, если вы работаете с разработкой в файловой системе,  descriptor.json("ModifiedOnUtc": "\/Date(1547502490000)\/",)

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

Добрый день!

В чем может быть проблема?

Настройка системы думаю корректна. Иначе компиляция не проходила бы вообще в системе.

Порядок действий:

Система в режиме разработки в БД

Создаю WS в своем пакете - WS прекрасно работает.

Перевожу систему в режим разработки в файловой системе

Жму Компилировать Все.

Система ругается на WS:

При проверке схемы произошли ошибки: "System.IO.FileNotFoundException: Зависимость пакета не найдена. Путь поиска:

Удаляю WS. Компиляция проходит.

Дальше не получается ранее работающий WS вернуть в систему из-за однотипной стабильной ошибки, которую указал выше.

Это классический случай, который решается мелкой донастройкой или тут что-то более серьезное может быть?

Нравится

2 комментария
Лучший ответ

Попробуйте после перевода BPM в разработку в файловой системе сделать выгрузку в ФС, а затем скомпилируйте конфигурацию

Попробуйте после перевода BPM в разработку в файловой системе сделать выгрузку в ФС, а затем скомпилируйте конфигурацию

Григорий Чех,

Помогло. Спасибо!

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

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

В БП созданы 2 параметра AccountType(справочник) и AccountId(уникальный идентификатор). Создал задание-сценарий с текстом 

AccountType = Guid.Parse(TypeString);

AccountId = Guid.Parse(IdString);

Компиляция проходит без ошибок, но при запуске получаю ошибку "The name 'AccountId' does not exist in the current context", при этом с AccountType все в порядке.

В случае интерпретируемого процесса ошибка аналогичная.

Предполагаю, что это особенность типа, но как исправить?

Нравится

2 комментария
Лучший ответ

Проверьте в параметрах что AccountId это именно не название а код параметра и для интерпритируемых используйте

var accountId = Get<Guid>("AccountId");

Проверьте в параметрах что AccountId это именно не название а код параметра и для интерпритируемых используйте

var accountId = Get<Guid>("AccountId");

Григорий Чех,

Спасибо.

Имена копировал, ошибка оставалась, пока не переименовал параметр.

Просто параметр создавал, потом удалял, потом создал опять с тем же именем, видимо где-то что-то кэшируется.

Сейчас все работает.

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

Друзья, подскажите, как правильно и безболезненно отключить сохранение карточки, при добавлении записей на деталь (которая находится в этой карточке), да так отключить, чтобы ничего не сломать? :)

Изображение удалено.

Нравится

6 комментариев
Лучший ответ

Как по мне не очень логичное решение, т.к. карточка может быть новой. И чтобы добавить запись детали нужно сперва сохранить карточку, чтобы id записи появился в базе.

Но если это действительно необходимо, посмотрите в сторону замещения метода addRecord из BaseGridDetailV2. Замещать его нужно на схеме детали.

В данноме методе идет проверка на: (isNewCard || isCardChanged). В этом случае карточка сперва сохранятся. Можете выпилить условие isCardChanged.

Как по мне не очень логичное решение, т.к. карточка может быть новой. И чтобы добавить запись детали нужно сперва сохранить карточку, чтобы id записи появился в базе.

Но если это действительно необходимо, посмотрите в сторону замещения метода addRecord из BaseGridDetailV2. Замещать его нужно на схеме детали.

В данноме методе идет проверка на: (isNewCard || isCardChanged). В этом случае карточка сперва сохранятся. Можете выпилить условие isCardChanged.

Дмитрий А.,

Посмотрю, спасибо. Но в этом разделе у нас есть миникарточка, так что с этой стороны проблем не возникнет.

Переопределите в детали метод addRecord, примерно так 

addRecord: function(editPageUId) {
	editPageUId = editPageUId || this.getFirstEditPageUId();
	if (!this.getIsCardValid()) {
		return;
	}
	this.set("CardState", enums.CardStateV2.ADD);
	this.set("EditPageUId", editPageUId);
	this.set("PrimaryValueUId", null);
	this.openCardByMode();				
}

 

Григорий Чех,

А вот так можно? Или лучше напрямую как Вы показали?

getIsCardNewRecordState: function() {
    return false;
},
getIsCardChanged: function() {
    return false;
}

 

Alex Zaslavsky,

Да должно и так отработать, протестируйте!

Григорий Чех,

Да, уже потестил, как раз то поведение что и нужно. Спасибо всем, и Дмитрию, и Вам, Григорий :)

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

Добрый день!

Подскажите при создании нового раздела добавлено справочное поле "Ответственный".

Источником для поля выбран объект "Контакт" - выбор сделан по аналогии с аналогичными полями в других разделах.

Существует объект "Сотрудник", но почему то в коробочной версии в полях он не выбран.

Для того чтобы выбирать ответственного из сотрудников - логично использовать раздел "Сотрудники", а в коробке используется раздел "Контакты" и я так понимаю кодом прописано, что выбор только среди контактов имеющих связь с разделом сотрудники.

 

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

Нравится

1 комментарий
Лучший ответ

Потому что в поле 'Ответственный' содержатся значения контактов, а то, что они должны являться, например, сотрудниками или пользователями системы - это уже условия фильтрации этих контактов.

Обратите внимание, что в коробочном методе фильтрации значений в поле 'Ответственный' выполняется проверка является ли контакт пользователем системы, а не сотрудником.

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

Потому что в поле 'Ответственный' содержатся значения контактов, а то, что они должны являться, например, сотрудниками или пользователями системы - это уже условия фильтрации этих контактов.

Обратите внимание, что в коробочном методе фильтрации значений в поле 'Ответственный' выполняется проверка является ли контакт пользователем системы, а не сотрудником.

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

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

Добрый день!

Подскажите, есть ли возможность отобразить идентификатор контрагента (dbo.Account.Id) например на странице контрагента? Почему-то колонка Id в мастере раздела не отображается и в БП в справочнике контрагента её использовать не получается.

Нравится

7 комментариев
Лучший ответ

Добрый день!

Только кодом. Пример замещенной схемы контрагента:

define("AccountPageV2", [], function() {
	return {
		entitySchemaName: "Account",
		attributes: {
			"AccountId": {
				dataValueType: this.Terrasoft.DataValueType.TEXT,
				value: "",
				caption: "Id"
			},
		},
		modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		businessRules: /**SCHEMA_BUSINESS_RULES*/{}/**SCHEMA_BUSINESS_RULES*/,
		methods: {
			onEntityInitialized: function() {
				this.callParent(arguments);
				this.set("AccountId", this.get("Id"));
			},
		},
		dataModels: /**SCHEMA_DATA_MODELS*/{}/**SCHEMA_DATA_MODELS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "AccountId",
				"parentName": "ProfileContainer",
				"propertyName": "items",
				"values": {
					"bindTo": "AccountId",
					"layout": {
						"column": 0,
						"row": 1,
						"colSpan": 24
					},
					"enabled": false
				}
			},
		]/**SCHEMA_DIFF*/
	};
});

Результат:

Добрый день!

Только кодом. Пример замещенной схемы контрагента:

define("AccountPageV2", [], function() {
	return {
		entitySchemaName: "Account",
		attributes: {
			"AccountId": {
				dataValueType: this.Terrasoft.DataValueType.TEXT,
				value: "",
				caption: "Id"
			},
		},
		modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		businessRules: /**SCHEMA_BUSINESS_RULES*/{}/**SCHEMA_BUSINESS_RULES*/,
		methods: {
			onEntityInitialized: function() {
				this.callParent(arguments);
				this.set("AccountId", this.get("Id"));
			},
		},
		dataModels: /**SCHEMA_DATA_MODELS*/{}/**SCHEMA_DATA_MODELS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "AccountId",
				"parentName": "ProfileContainer",
				"propertyName": "items",
				"values": {
					"bindTo": "AccountId",
					"layout": {
						"column": 0,
						"row": 1,
						"colSpan": 24
					},
					"enabled": false
				}
			},
		]/**SCHEMA_DIFF*/
	};
});

Результат:

Спасибо, Александр!

Значение отображается.

А что нужно сделать, чтобы оно отображалось в списке значений справочника Контрагент?

Виталий Егоров пишет:

А что нужно сделать, чтобы оно отображалось в списке значений справочника Контрагент?

А где нужно сделать, чтобы оно отображалось в списке значений и для решения какой задачи? 

Да, неясно выразился. Если точнее - нужно создать переменную в БП (как я понимаю типа справочник), чтобы прочитать значение Id и сравнить с полученным извне.

Виталий Егоров,

Если нужно сравнивать только значения Id, тогда Вам достаточно создать параметр БП с типом уникальный идентификатор.

Элемент БП 'Чтение данных' позволяет выбрать значение поля Id того объекта, из которого Вы вычитываете данные. Точно также значение Id записи можно получить и из сигнала.

А потом в элементе формула Вы можете Вашему параметру БП присвоить это значение.

Если эти элементы БП Вам не подходят для решения Вашей задачи, то вычитать нужное значение Id можно в скрипт-таске и тут же его записать в нужный параметр БП.

Алла Савельева пишет:

Спасибо, Алла! А есть ли возможность задать Id при создании нового контрагента процессом? 

Все, разобрался.

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