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

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

Нравится

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

чтобы отобразить такой составной справочник надо будет создать представление (объект со свойством "представление") и SQL-скрипт а ля

create view [dbo].[FizUrLic]
as
	select 
		[Id]
		,[Name]
	from FizLic
	union all
	select 
		[Id]
		,[Name]
	from UrLic
GO

. Это будет так сказать виртуальная таблица, объединяющая два ваших справочника в один. Но возникнут большие сложности с сохранением значения поля. Т.к. поле должно быть справочным и одновременно иметь возможность ссылаться на два разных справочника. Задача уровня разработчика.

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

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

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

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

похоже, все уже сделано Террасофтом)
версия 7.7 пакет Opportunity схема OpportunityPageV2
не проверял, но вроде достаточно добавить аналогичный код

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"
				}
			}
		}
	}
]

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

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"}
                    }
                }
            }
            ...
        ]
    }
});            
 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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