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

Нравится

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

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

Используя Террасофт Администратор, Вам необходимо в сервисе окна нужного Вам раздела, добавить новый Page, и внутрь этого Page добавить также WindowContainer. Этому контейнеру установить свойство Window как окно реестра связанного раздела. После этого, Вам останется лишь добавить логику фильтрации данных этого раздела в зависимости от выделенной записи основного раздела. Пример Вы можете посмотреть в любом из скриптов раздела - функция RefreshDetails();.

Дмитрий, спасибо за комментарий. Сделали как написано, добавили в скрипт scr_InvoiceWorkspace следующий код

function InitializeInventoryDetail() {
	var DetailWindow = wndInventoryDetail.Window;
	InvoiceWorkspace.InventoryWindow = DetailWindow;
	SetAttribute(DetailWindow, 'DatasetUSI', 'ds_Inventory');
	SetAttribute(DetailWindow, 'ParentItemFieldName', 'InvoiceID');
	SetAttribute(DetailWindow, 'EditWindowUSI', 'wnd_InventoryEdit');
 
	DetailWindow.Prepare();
	var DetailDataset = DetailWindow.ComponentsByName('dlData').Dataset;
	InvoiceWorkspace.InventoryDataset = DetailDataset;
}
 function RefreshInventoryDetail() {
	if (InvoiceWorkspace.InitializeInventoryFlag != true) {
		InitializeInventoryDetail();
		InvoiceWorkspace.InitializeInventoryFlag = true;
	}
	var InvoiceID = BaseWorkspace.GridDataset.ValAsGUID('ID');
	if (InvoiceID == InvoiceWorkspace.InventoryOldInvoiceID) {
		return;
	} else {
		InvoiceWorkspace.InventoryOldInvoiceID = InvoiceID;
	}
	SetAttribute(InvoiceWorkspace.InventoryWindow, 'ParentItemID', InvoiceID);
	RefreshDetailData(BaseWorkspace.GridDataset, 'ID',
		InvoiceWorkspace.InventoryDataset, 'InvoiceID');
}
if (pcDetails.ActivePage.Name == pgSclad.Name){
		RefreshInventoryDetail();
	} else 

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

Датасет связанного раздела ds_Inventory, InvoiceID поле типа справочник для связи с разделом Счет. Название окна детали wndInventoryDetail.

Может где-то упустили что-то.

Вероятно нету фильтра сравнения в сервисе SelectQuery "подчиненного" раздела.

У меня получилось реализовать данный функционал следующим образом:

1. Создаем раздел "Test" через "Мастер создания разделов".
2. В администраторе добавляем колонку InvoiceID в сервисе tbl_Test.
3. В sq_Test добавляем JOIN - tbl_Test.InvoiceID = tbl_Invoice.ID
3.1. Тут же добавляем выборку поля tbl_Test.InvoiceID, tbl_Invoice.InvoiceNumber.
3.2. Тут же добавляем параметр InvoiceID и фильтр сравнения InvoiceID - tbl_Test.InvoiceID = Parameter:InvoiceID.
4. В ds_Test добавляем LookupDataField: колонка InvoiceID, источник данныз - ds_Invoice, колонка для отображения - InvoiceNumber.
5. В окно wnd_TestEdit добавляем LookupDataControl. DatasetLink = dlData, DataField = InvoiceID.
6. Идем в сервис wnd_InvoicesWorkspace. Добавляем новый Page, Window. Устанавливаем свойство Window как wnd_TestGridArea.
7. Переходим в событие OnChangeActivePage для pcDetails. Видим там функцию RefreshDetails(); - переходим в нее и в конец добавляем:

if (pcDetails.ActivePage.Name == pgTest.Name) {
 
		RefreshCommonDetail(BaseWorkspace, wndTestDetail, 
			'InvoiceID', 'InvoiceID');
}

где pgTest - имя контрола Page, wndTestDetail - имя контрола Window.

Сохраняемся.

Результат - деталь корректно фильтруется.

Сервисы раздела Test, а также модифицированный сервис scr_InvoiceWorkspace, wnd_InvoicesWorkspace во вложении.

1

2

Дмитрий, все получилось, спасибо за помощь. Действительно не было фильтра

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

в скрипт GridArea целевого раздела вставил функцию

function InitializeGridMenu(Window) {
	if (!IsEmptyValue(Window.Attributes('ParentItemFieldName'))) {
		SetAttribute(Window, 'AddSelfReference', true);
		SetAttribute(Window, 'SelfReferenceCaption', "Склад");
	}
}

в scr_WindowUtil вставил

RefDictionary.Add('ds_Inventory', 'wnd_InventoryWorkspace');

Александр, здравствуйте.

Прочтите, пожалуйста, вот эту тему. Если ен получится реализовать, напишите что именно не получилось.

В function Initialize(Window) скрипта scr_InventoryGridArea вставил только параметры

   SetAttribute(Window, 'AddSelfReference', true);
   SetAttribute(Window, 'SelfReferenceCaption', "Склад");

Все получилось, спасибо.

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

Еще одна полезная штука.

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

Откройте wnd_ContactsWorkspace и добавьте в него контейнер страницы pgContactContractsDetail а в нее контейнер окна wndContactContractsDetail. Унаследуйте wndContactContractsDetail от wnd_ContractsGridArea.

Откройте wnd_ContactsWorkspaceScript и добавьте в него следующий программный код:

В функцию function RefreshDetails:
Необходимо добавить следующий программный код:

 if (pcDetails.ActivePage.Name == pgContactContractsDetail.Name){
                   RefreshContactContractsDetail();
         } else

В конец скрипта:

function InitializeContactContractsDetail() {
         ContactsWorkspace.ContactContractsWindow = wndContactContractsDetail.Window;
         var DetailWindow = ContractsWorkspace.ContactContractsWindow;
         SetAttribute(DetailWindow, 'DatasetUSI', 'ds_Trained');
         SetAttribute(DetailWindow, 'EditWindowUSI', 'wnd_TrainedEdit');
         SetAttribute(DetailWindow, 'ParentItemFieldName', 'ContactID');
         DetailWindow.Prepare();
         ContactsWorkspace.ContactContractsDataset =
                   DetailWindow.ComponentsByName('dlData').Dataset;
}

function RefreshContactContractsDetail() {
         if (ContactsWorkspace.InitializeContactContractsFlag != true) {
                   InitializeContactContractsDetail();
                   ContactsWorkspace.InitializeContactContractsFlag = true;
         }
         var ContactID = BaseWorkspace.GridDataset.ValAsGUID('ContactID');
         if (ContactID == ContactsWorkspace.ContactContractsOldContactID) {
                   return;
         } else {
                   ContactsWorkspace.ContactContractsOldContactID = ContactID;  
         }
         RefreshDetailData(BaseWorkspace.GridDataset, 'ContactID',
         ContactsWorkspace.ContactContractsDataset, 'ContactID');
}

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

Для устранения данной проблемы можно в конце функции RefreshContactContractsDetail() добавить следующий дополнительный фильтр:

ApplyDatasetFilter(ContactsWorkspace.ContactContractsDataset, 'NotID', BaseWorkspace.GridDataset.ValAsGUID('ID'), true);
    ContactsWorkspace.ContactContractsDataset.Close();
    ContactsWorkspace.ContactContractsDataset.Open();

Приятной работы!

С уважением,
Белецкий Арсений
Группа компаний Terrasoft

Нравится

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

а почему у вас везде ContractsWorkspace, хотя речь идет о разделе контактов?

Спасибо, Дмитрий!

Изменения внесены!

Может кому понадобится, на основе первого поста.
Создание вкладки "Договоры" в карточке контрагента:

В wnd_AccountEdit:

  • добавить Page pgContracts
  • добавить форму frmContracts
  • добавить контейнер cntContracts
  • Контейнеру cntContractsпрописал атрибут Window wnd_ContractsGridArea

К скрипту scr_AccountEdit:

  • Добавил используемый скрипт scr_WorkspaceUtils - это я сделал в рамках другой задачи и не проверял результат без него.
  • Добавил в функцию wnd_AccountEditOnPrepare(Window)
    InitializeAccountContractsDetail();
    	RefreshContractsDetail();
  • Добавил функцию
    function InitializeAccountContractsDetail(){
    	AccountEdit.AccountContractsWindow = cntContracts.Window;
    	var DetailWindow = AccountEdit.AccountContractsWindow;
    	SetAttribute(DetailWindow, 'DatasetUSI', 'ds_Contract');
    	SetAttribute(DetailWindow, 'EditWindowUSI', 'wnd_ContractsGridArea');
    	SetAttribute(DetailWindow, 'ParentItemFieldName', 'ID');
    	SetAttribute(DetailWindow, 'ChildFilterName', 'CustomerID');
    	SetAttribute(DetailWindow,'AddSelfReference',true);
    	DetailWindow.Prepare(); 
    	AccountEdit.AccountContractsDataset = DetailWindow.ComponentsByName('dlData').Dataset;
     
    }
  • Добавил функцию
    function RefreshContractsDetail() {
    	if (AccountEdit.InitializeContactContractsFlag != true) {
    		InitializeAccountContractsDetail(); 
    		AccountEdit.InitializeContactContractsFlag = true;
    	}
    	var BaseWorkspace  = {GridDataset: dlData.Dataset};
    	var CustomerID = BaseWorkspace.GridDataset.ValAsGUID('ID');
    	if (CustomerID == AccountEdit.ContactContractsOldContactID) {
    		return;
    	} else {
    		AccountEdit.ContactContractsOldContactID = CustomerID;  
    	}
    	RefreshDetailData(BaseWorkspace.GridDataset, 'ID', AccountEdit.AccountContractsDataset, 'CustomerID');
    }

Андрей, спасибо за полезную реализацию!

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