просмотр всех записей датасета перед редактированием
Необходимо перед добавлением\изменением записи детали проверить - не попадает ли заданный диапазон дат новой записи в один из уже существующих диапазонов записей датасета, а затем еще присвоить новой записи идентификатор таблицы реестра.
Я попытался сделать это на событие dlDataOnDatasetBeforePost в форме редактирования записи детали (wnd_SubContactPeriodsEdit)
...
function dlDataOnDatasetBeforePost(Dataset, DoPost) {
// проверка на пересечение нового периода с существующими
SubContactPeriodsDates.periodFrom = edtPeriodFrom.DataField.ValAsDateTime;
SubContactPeriodsDates.periodTo = edtPeriodTo.DataField.ValAsDateTime;
Dataset.GotoFirst();
while (!Dataset.IsEOF)
{
SubContactPeriodsDates.curFrom = Dataset.DataFields.ItemsByName('PeriodFrom');
SubContactPeriodsDates.curTo = Dataset.DataFields.ItemsByName('PeriodTo');
if (intersectDate() )
{
DoPost.Value = false;
ShowErrorDialog('Заданный период пересекается с существующими!');
return;
}
Dataset.GotoNext();
}
Dataset.DataFields.ItemsByName('ManagerID').Value = SubContactPeriodsEdit.ParentItemID;
}
function intersectDate()
{
return ((SubContactPeriodsDates.curTo > SubContactPeriodsDates.periodFrom) &&
(SubContactPeriodsDates.periodTo > SubContactPeriodsDates.curFrom)) ? true:false;
}
стало ясно что при переборе всех значений датасета, он выходит из режима вставки\редактирования.
Подскажите, как справиться с такой задачей ?
из идей только - воспользоваться dlDataOnDatasetAfterPost + Dataset.cancel()
Нравится
Как-то у вас тут все туманно. Почему даты в функцию не отдаете, а используете контролы как посредника?
И проверка странная...
Так как-то логичнее:
(periodFrom >= curFrom) && (periodTo <= curTo)
Ну вобщем, да на BeforePost не надо ходить по датасету. Как вариант - это создавать еще один экземпляр, но я бы лично делал эту проверку одним sql-запросом типа :
select count(1) .... where StartDate <= :startDate AND DueDate >= :dueDate
если вернет 0 - то можно постить.
напишите поподробней пожалуйста, как получить программно результат запроса в данном случае чтобы его проанализировать
Создайте сервис SelectQuery с необходимым запросом.
потом в коде на BeforePost берите его экземпляр, устанавливаете параметры
sq.Parameters.ItemsByName('StartDate') = periodFrom;
sq.Parameters.ItemsByName('DueDate') = periodFrom;
(Пишу по памяти - проверяйте)
Потом sq.Open() вернет датасет и у него смотрите значения поля, которое собственно и считает количество записей.
Только исправьте: для записи в параметр select query нужно писать SelectQuery.Parameters.ItemsByName('...').Value = ...
спасибо за помощь, у меня получилось вот так:
var SubContactPeriodsEdit= new Object(); ... function dlDataOnDatasetBeforePost(Dataset, DoPost) { SubContactPeriodsEdit.periodFrom = edtPeriodFrom.DataField.ValAsDateTime; SubContactPeriodsEdit.periodTo = edtPeriodTo.DataField.ValAsDateTime; // проверка на пересечение нового периода с существующими if (intersectDate() ) { DoPost.Value = false; ShowErrorDialog('Заданный период пересекается с существующими периодами!'); return; } Dataset.DataFields.ItemsByName('ManagerID').Value = SubContactPeriodsEdit.ParentItemID; } function intersectDate() { var sq = Services.GetSingleItemByUSI('sq_SubContactPeriodsIntersect'); sq.Parameters.ItemsByName('From').Value = SubContactPeriodsEdit.periodFrom; sq.Parameters.ItemsByName('To').Value = SubContactPeriodsEdit.periodTo; var ds = sq.Open(); return (ds.DataFields.ItemsByName('ID').Value > 0)?true:false; }
параметры я передал через глобальный объект SubContactPeriodsEdit, был бы признателен за любые замечания.
"Каукин Владимир Константинович" написал:параметры я передал через глобальный объект SubContactPeriodsEdit, был бы признателен за любые замечания.
А зачем через глобальный объект, если можно вот так:
... if (intersectDate(Dataset.ValAsDateTime('PeriodFrom'), Dataset.ValAsDateTime('PeriodTo'))) ...
и
function intersectDate(StartDate, DueDate) { ... }
Так же как-то логичнее и кода меньше..
Вообще старайтесь меньше использовать глобальные переменные. Если можно, то лучше параметрами функции или же атрибутами, если передача идет за рамки одного скрипта.
Спасибо за советы.
У меня появился еще 1 вопрос, есть запрос вида:
SELECT COUNT(CAST([tbl_SubContactPeriods].[ID] AS VARCHAR(38))) AS [ID] FROM [dbo].[tbl_SubContactPeriods] AS [tbl_SubContactPeriods] LEFT OUTER JOIN [dbo].[tbl_Contact] AS [tbl_Contact] ON [tbl_Contact].[ID] = [tbl_SubContactPeriods].[ManagerID] WHERE(:From BETWEEN [tbl_SubContactPeriods].[PeriodFrom] AND [tbl_SubContactPeriods].[PeriodTo] AND [tbl_SubContactPeriods].[ManagerID] = :ManagerID)
он работал правильно, пока я не добавил фильтр сравнения для выборки данных только для текущей записи в реестре ( вот эта строка [tbl_SubContactPeriods].[ManagerID] = :ManagerID )
Если я подставляю в субд правильные значения, то запрос работает:
WHERE('05.04.2011' BETWEEN [tbl_SubContactPeriods].[PeriodFrom] AND [tbl_SubContactPeriods].[PeriodTo] AND [tbl_SubContactPeriods].[ManagerID] = '8C6AE091-B24D-42B2-BD2B-4AE2B72EDB8E')
,так же он работал в системе без этого фильтра сравнения.
Создаю запрос и передаю ему параметры вот так:
function intersectDateForOne(constFrom,selID) { debugger; var sq = Services.GetSingleItemByUSI('sq_SubContactPeriodsIntersectForOne'); sq.Parameters.ItemsByName('From').Value = constFrom; sq.Parameters.ItemsByName('ManagerID').Value = selID; var ds = sq.Open(); var test = ds.DataFields.ItemsByName('ID'); return (ds.DataFields.ItemsByName('ID').Value > 0)?true:false; }
Проблема в следующем, запрос без добавленного фильтра должен вернуть 2, с фильтром - 1, проверил в субд, на практике же без фильтра - 2, с фильтром 0 :(
Дебаггером я прошелся по каждой строке кода, но ничего странного не нашел, все параметры передаются и устанавливаются в нужные значения, может быть я неверно передаю параметры в запрос и этим все ломаю?
sq.Parameters.ItemsByName('ManagerID').Value = selID;
constFrom (Data), selID (String) - подаются норм
Владимир, прежде всего, замените GetSingleItemByUSI на GetNewItemByUSI:
var sq = Services.GetNewItemByUSI('sq_SubContactPeriodsIntersectForOne');
Если запрос по-прежнему вернет 0, включите профайлер перед вызовом var ds = sq.Open() и проверьте какой запрос идет в БД.