Я продолжил поиски по теме:
Процедура вызова окна, где заполняются данные о документе.
Код:
procedure TfMain.barbutNewTicketClick(Sender: TObject);
begin
Tickets.Insert;
fNewTicket.ShowModal;
end;
Три процедуры для заполнение подчинённых данных.
1. Insert в Detail таблицу -> Items.Insert;
2. Post в Detail таблицу (есть обработчик BeforePost, в котором проверяется адекватность введённых данных)
3. Cancel изменений в Detail таблице ->Items.Cancel;
Далее код для сохранения документа:
Код:
procedure TfNewTicket.butSaveClick(Sender: TObject);
begin
// ... некое взаимодействие с пользователем
fMain.Tickets.Post; // вносим изменения в билет
fMain.Tickets.UpdateBatch; // отправляем изменения в БД (тем самым получаем ID записи, на которой сейчас стоит курсор (последняя добавленная)
fMain.Items.First; // обработка всех добавленных записей в Detail таблице
while not fMain.Items.Eof do
begin
fMain.Items.Edit;
fMain.Items.FieldByName('IDTicket').AsInteger :=
fMain.Tickets.FieldByName('ID').AsInteger;
fMain.Items.Post;
fMain.Items.Next; // Next вызывает метод Post? я не нашёл в реализации явного вызова, но судя по тому, что строка сохраняется делаю вывод что вызывается
end;
fMain.Items.UpdateBatch; // фиксируем изменения в Items.
end;
В итоге всё супер работает. Только пришлось отказаться от:
Код:
Items.MasterSource := dsTickets;
Items.MasterFields := ID;
Items.IndexFieldNames := IDTicket;
что приводит к тому, что нужно добавлять второй ADOTable для Items, для дальнейшего отображения данных уже на других формах (например на форме, редактирования конкретного билета)
И пришлось добавить:
Код:
procedure TfMain.ItemsAfterOpen(DataSet: TDataSet);
begin
if not Items.Filtered then
begin
Items.FilterGroup := fgAffectedRecords;
Items.Filtered := true;
end;
end;
Собственно фильтрация по "несохранённым" в БД записям из Detail таблицы.
Что скажете?