Технические вопросы
7.x

Объединить справочники

Задача:
есть два справочника, список Физ.лиц и список Юр.лиц. (справочники простые), как настроить поле со списком, чтобы в нем можно было выбирать Наименования из обоих справочников?

Нравится

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

чтобы отобразить такой составной справочник надо будет создать представление (объект со свойством "представление") и SQL-скрипт а ля
[sql]
create view [dbo].[FizUrLic]
as
select
[Id]
,[Name]
from FizLic
union all
select
[Id]
,[Name]
from UrLic
GO
[/sql]. Это будет так сказать виртуальная таблица, объединяющая два ваших справочника в один. Но возникнут большие сложности с сохранением значения поля. Т.к. поле должно быть справочным и одновременно иметь возможность ссылаться на два разных справочника. Задача уровня разработчика.

другой вариант - объединить физически два справочника в один, добавив поле типа (Физическое/Юридическое), по которому фильтровать там, где это вам надо

Видел вот такой вариант решения совмещения из двух справочников:

да, это продажи в 7.7. Но сделать это не так-то просто

Вот в том то и вопрос. От этого задача не изменяется.) Где-то же есть код, который организовывает подобный диалог? Если да, то подскажите - где искать.
Я догадываюсь, что такое вполне организовали на С#.

похоже, все уже сделано Террасофтом)
версия 7.7 пакет Opportunity схема OpportunityPageV2
не проверял, но вроде достаточно добавить аналогичный код
[javascript]
attributes : {
"Client" : {
"caption" : {
"bindTo" : "Resources.Strings.Client"
},
"dataValueType" : this.Terrasoft.DataValueType.LOOKUP,
"multiLookupColumns" : ["Contact", "Account"],
"isRequired" : true
}
},
diff[{
"operation" : "insert",
"parentName" : "Header",
"propertyName" : "items",
"name" : "Client",
"values" : {
"layout" : {
"column" : 2,
"row" : 1,
"colSpan" : 10
},
"tip" : {
"content" : {
"bindTo" : "Resources.Strings.ClientTip"
}
},
"controlConfig" : {
"enableLeftIcon" : true,
"leftIconConfig" : {
"bindTo" : "getMultiLookupIconConfig"
}
}
}
}
]
[/javascript]

Я видел нечто похожее, в Order 7.7, "OrderPageV2". Я так понимаю, что еще надо лепить проверку.

[javascript]
define("OrderPageV2",
["ProductSalesUtils", "OrderConfigurationConstants", "BusinessRuleModule", "MoneyModule", "VisaHelper", "ConfigurationConstants", "ProductEntryPageUtils", "css!VisaHelper", "MultiCurrencyEdit","MultiCurrencyEditUtilities"],
function(ProductSalesUtils, OrderConfigurationConstants, BusinessRuleModule, MoneyModule, VisaHelper, ConfigurationConstants) {
return {
entitySchemaName: "Order",
messages: { ... },
attributes: {
...
"Client": {
"caption": {"bindTo": "Resources.Strings.Client"},
"dataValueType": this.Terrasoft.DataValueType.LOOKUP,
"multiLookupColumns": ["Contact", "Account"],
"isRequired": true
}
},
details: /**SCHEMA_DETAILS*/{ ... },
mixins: { ... },
methods: {
...
/**
* Выполняет проверку значения модели представления.
* Если присутствуют некорректные значения, выводит сообщение о необходимости заполнения первого.
* @protected
* @overridden
* @param {Function} callback callback-функция
* @param {Terrasoft.BaseSchemaViewModel} scope Контекст выполнения callback-функции
*/
asyncValidate: function(callback, scope) {
this.callParent([function(response) {
var checkResponse = function(context) {
if (!context.response.success) {
context.callback.call(context.scope, context.response);
} else {
context.next();
}
};
var validationChain = [
checkResponse,
function(context) {
context.scope.validateAccountOrContactFilling(function(response) {
context.response = response;
context.next();
}, context.scope);
},
function(context) {
context.callback.call(context.scope, context.response);
}
];
Terrasoft.chain({
scope: scope || this,
response: response,
callback: callback
}, validationChain);
}, this]);
},
...
/**
* Проверяет заполненость полей "Контакт" или "Контрагент" значениями
* @param {Function} callback Функция обратного вызова
* @param {Object} scope Контекст
*/
validateAccountOrContactFilling: function(callback, scope) {
var account = this.get("Account");
var contact = this.get("Contact");
var result = {
success: true
};
if (this.Ext.isEmpty(account) && this.Ext.isEmpty(contact)) {
result.message = this.get("Resources.Strings.RequiredFieldsMessage");
result.success = false;
}
callback.call(scope || this, result);
},
...
},
diff: /**SCHEMA_DIFF*/[
...
{
"operation": "insert",
"parentName": "Header",
"propertyName": "items",
"name": "Client",
"values": {
"layout": {"column": 0, "row": 0, "colSpan": 12},
"tip": {
"content": {"bindTo": "Resources.Strings.ClientTip"}
},
"controlConfig": {
"enableLeftIcon": true,
"leftIconConfig": {"bindTo": "getMultiLookupIconConfig"}
}
}
}
...
]
}
});

[/javascript]

Помимо этого, я так понимаю, что в самой сущности необходимо начилие также соответствующих справочных полей "Contact" и "Account", а поле "Client" - это как виртуальное поле.

Я эти шаги проделал на тестовом разделе: сделал 2 поля и запилил эти добавки, но страница тупо зависла. Может еще что-то нужно? Или где посмотреть причину, логи какие-нибудь..

Если убрать валидаторы, то идея - работоспособна.

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

Продолжаем разговор.)
С сохранением данных - определились, а вот теперь обратная задача: отобразить общее значение из этих двух полей - в одном поле реестра (по сути, там будет или данные из одного поля или из другого).

Здравствуйте, Евгений.

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

Здравствуйте, Павел.
Идея хорошая, сходная с идеей в Карточке редактирования. А есть пример какой-нибудь по реализации этого процесса? Или где создавать эту вирт.колонку и как этот реестр определит, что ее нужно выводить?

Эта колонка может быть просто текстовым полем с проставленным свойством "visible": false. При изменении значения мультилукапного аттрибута, Вы можете получать значение этого аттрибута используя this.get и устанавливать в скрытое поле через this.set. Вывести данное поле в реестр не составит проблем.

"Мотков Илья" написал:

Эта колонка может быть просто текстовым полем с проставленным свойством "visible": false. При изменении значения мультилукапного аттрибута, Вы можете получать значение этого аттрибута используя this.get и устанавливать в скрытое поле через this.set. Вывести данное поле в реестр не составит проблем.

Я думал об этом, только как поведет себя это поле, если данные (например ФИО) в справочние - изменятся? Значение которое сохранено - уже не поменяется же..
Или можно его как-то при выборке динамически обновлять?

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

Возникла идея модифицировать данные на лету, в процессе загрузки, например в методе [code]GridUtilitiesV2.onGridDataLoaded[/code]. Насколько это возможно?

Очень странно, что не дает модифицировать данные в JavaScript, которые загружены с сервера. Т.е. стили модернизировать можно, а данные нельзя? А если мне надо сохранять данные в сжатом формате, а потом их распаковывать для удобства отображения?

А разве не будет самым простым решением - создать новый справочник в объекте. Значения в котором будут заполняться, изменяться и удаляться при помощи триггеров в таблицах на основании которых он строится или при помощи бизнес процессов.

"Мотков Илья" написал:А разве не будет самым простым решением - создать новый справочник в объекте. Значения в котором будут заполняться, изменяться и удаляться при помощи триггеров в таблицах на основании которых он строится или при помощи бизнес процессов.

самое простое не есть самое лучшее
;)

"Фролов Евгений" написал:Я думал об этом, только как поведет себя это поле, если данные (например ФИО) в справочние - изменятся? Значение которое сохранено - уже не поменяется же..

БП, который стартует при изменении поля ФИО в Контакте. И этот БП меняет текстовую колонку во всех нужных объектах, где клиент является физ-лицом.
То же самое с объектом Контрагент

Всем спасибо, пока принято решение не совмещать вывод данных.

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