Имя: Пароль:
1C
 
Что-то туплю и бьюсь над задачей свдига записей дневника вверх-вниз.
0 Гений 1С
 
гуру
15.05.20
17:16
Написал конфу, где веду дневник.
У меня каждая запись имеет дату и время.
Так вот, есть кнопки сдвинуть вперед и назад, которые сдвигают запись дневника  до/после следующей.
Но что-то не очень аккуратный код получается, некрасивый. Как правильно сформировать?
И главное - иногда не срабатывает...

Нюанс в том, что изначально может быть несколько записей с однинаковым временем.
И после сдвига запись не должна уезжать в другую дату.

Может это рекурсивно можно как-то сделать?

Скриншот дневника тут:

https://fixinchik.ru/v-dnevnike-sdelal-fokus-dnya/


Код по сдвигу:


Функция Сдвинуть(Задача, Направление) Экспорт
    //Направление = 1 или -1
    З = Новый Запрос(
    "ВЫБРАТЬ
    |    Дневник.Дата КАК Дата,
    |    Дневник.Дата КАК ИсхДата,
    |    Дневник.Ссылка КАК Задача,
    |    ВЫБОР
    |        КОГДА Дневник.Ссылка = &Задача
    |            ТОГДА ИСТИНА
    |        ИНАЧЕ ЛОЖЬ
    |    КОНЕЦ КАК СтартоваяЗадача,
    |    Дневник.ТочноеВремя КАК ТочноеВремя,
    |    Дневник.БезВремени КАК БезВремени
    |ИЗ
    |    Справочник.Дневник КАК Дневник
    |ГДЕ
    |    Дневник.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ) И КОНЕЦПЕРИОДА(&Дата, ДЕНЬ)
    |    И НЕ Дневник.БезВремени
    |
    |УПОРЯДОЧИТЬ ПО
    |    Дата"
    );
    ИсхДата = Задача.Дата;
    З.УстановитьПараметр("Дата", ИсхДата);
    З.УстановитьПараметр("Задача", Задача);
    ТЗ = З.Выполнить().Выгрузить();
    ТЗ.Колонки.Добавить("Изменения", Новый ОписаниеТипов("Булево"));
    
    
    //Убираем одинаковое время
    Всего = ТЗ.Количество();
    Инд = 2;
    Для Инд = 2 По Всего Цикл
        ПредСтрока = ТЗ[Инд - 2];
        Строка = ТЗ[Инд - 1];
        Если Строка.ИсхДата = ПредСтрока.ИсхДата И НЕ Строка.ТочноеВремя Тогда
            Строка.Дата = ПредСтрока.Дата + 1;
        КонецЕсли;
        
        //Для стартовой меняем с предыдущей
        Если Направление = - 1 И Строка.СтартоваяЗадача Тогда
            Если Строка.ТочноеВремя Тогда
                Если НЕ Предстрока.ТочноеВремя Тогда
                    ПредСтрока.Дата = Строка.Дата + 1;
                КонецЕсли;
            Иначе
                СтрокаДата = Строка.Дата;
                Строка.Дата = ПредСтрока.Дата;
                ПредСтрока.Дата = СтрокаДата;
            КонецЕсли;
        ИначеЕсли Направление = 1 И ПредСтрока.СтартоваяЗадача  Тогда
            Если ПредСтрока.ТочноеВремя  Тогда
                Если НЕ Строка.ТочноеВремя Тогда
                    Строка.Дата = Строка.Дата - 1;
                КонецЕсли;
            Иначе
                СтрокаДата = Строка.Дата;
                Строка.Дата = ПредСтрока.Дата;
                ПредСтрока.Дата = СтрокаДата;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    Всего = ТЗ.Количество();
    Инд = 2;
    Для Инд = 2 По Всего Цикл
        ПредСтрока = ТЗ[Инд - 2];
        Строка = ТЗ[Инд - 1];
        Если Строка.Дата = ПредСтрока.Дата И НЕ Строка.ТочноеВремя Тогда
            Строка.Дата = ПредСтрока.Дата + 1;
        КонецЕсли;
    КонецЦикла;

    
    
    НачалоДня = НачалоДня(ИсхДата) + 1;
    КонецДня = КонецДня(ИсхДата);
    
    //Определяем минимальную и максимальную дату
    ПерваяСтрока = ТЗ[0];
    МинДата = ПерваяСтрока.Дата;
    МаксДата = ПерваяСтрока.Дата;
    Для Каждого Строка ИЗ ТЗ Цикл
        Если НЕ Строка.Изменения Тогда
            Продолжить;
        КонецЕсли;
        МинДата = Мин(МинДата, Строка.Дата);
        МаксДата = Макс(МаксДата, Строка.Дата);
    КонецЦикла;
    
    //Определяем, не вышли ли мы за границу дня
    Дельта = 0;
    Если МинДата < НачалоДня Тогда
        Дельта = НачалоДня - МинДата;
    КонецЕсли;
    Если МаксДата > КонецДня Тогда
        Дельта = МаксДата - КонецДня;
    КонецЕсли;
    
    Если Дельта <> 0 Тогда
        Для Каждого Строка ИЗ ТЗ Цикл
            Если НЕ Строка.Изменения Тогда
                Продолжить;
            КонецЕсли;
            Строка.Дата = Строка.Дата + Дельта;
            //Проверяем, чтобы дата не изменилась
            Строка.Дата = Мин(Строка.Дата, КонецДня);
            Строка.Дата = Макс(Строка.Дата, НачалоДня);
        КонецЦикла
    КонецЕсли;
    
    Для Каждого Строка ИЗ ТЗ Цикл
        Если Строка.Дата <> Строка.ИсхДата Тогда
            ОО = Строка.Задача.ПолучитьОбъект();
            ОО.Дата = Строка.Дата;
            ОО.Записать();
        КонецЕсли;
    КонецЦикла;
    
КонецФункции

Процедура СдвинутьСлуж(ТЗ, ИсхДата, Направление, НужнаПроверка = истина) Экспорт
    
    РезДата = ИсхДата + Направление;
    
    КИзменению = Новый Массив();
    
    Для Каждого Строка ИЗ ТЗ Цикл
        
        //Пропускаем задачи, которые не надо менять
        Если Строка.БезВремени Тогда
            Строка.Дата = НачалоДня(Строка.ИсхДата); //Без даты - на начало дня
        КонецЕсли;
        Если Строка.ТочноеВремя ИЛИ Строка.БезВремени Тогда
            Продолжить;
        КонецЕсли;
        
        Если Строка.Дата = ИсхДата Тогда
            Если Не Строка.Изменения Тогда
                КИзменению.Добавить(Строка);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    ЗадачаКОбработке = Неопределено;
    Для Каждого Строка ИЗ КИзменению Цикл
        Строка.Дата = РезДата;
        
        
        Если ЗадачаКОбработке = Неопределено
            И (НЕ Строка.СтартоваяЗадача)
        Тогда
            ЗадачаКОбработке = Строка.Задача;
            Строка.Изменения = истина;
        КонецЕсли;
        
    КонецЦикла;
    
    Если ЗадачаКОбработке <> Неопределено Тогда
        СдвинутьСлуж(ТЗ, РезДата, Направление, ИСТИНА);
    КонецЕсли;
    Если ЗадачаКОбработке = Неопределено И НужнаПроверка Тогда
        СдвинутьСлуж(ТЗ, РезДата, Направление, ЛОЖЬ);
    КонецЕсли;
    
            

    

КонецПроцедуры
1 Сияющий в темноте
 
15.05.20
19:26
ты сдвигаешь строку в произвольное место?
если нет,то у тебя функция обмена двух соседних строк - просто,при сдаиге вверх это текущая и предыдущая,а при сдвиге вниз текущая и следующая.

по ид запросом получаешь обе строки и срааниваешь дату и время,если совпали (или если у одной  из них времени нет)то меняешь местами.
2 Гений 1С
 
гуру
15.05.20
19:27
(1) да но там есть нюанс, что у них может быть одинаковое время, а порядок надо сохранить ну или хотя бы там где одинаковое, проставить +1 секунда
3 Гений 1С
 
гуру
15.05.20
19:30
я думал, сперва прогнать, чтобы у всех было разное время, но это тоже непросто.
потому что например
10:00
10:00
10:00
10:01
10:01
10:03

если тупо добавить +1 секунду, не получится.
Должно быть:

10:00
10:01
10:02
10:03
10:04
10:05
4 Вафель
 
15.05.20
20:21
сделай сортировку дата + приортиет
5 Гений 1С
 
гуру
15.05.20
20:46
(4) там нет приоритетов. сортировка по дате и времени. Так задумано
6 breezee
 
15.05.20
22:23
(0) Добрый вечер. Что есть сдвиг? Вы изменяете приоритет задач, не изменяя время или ставите время после последней задачи?
Да, знаю что Вы - Легенда) Но все же прошу объяснения.
Для красоты я бы сделал чуть больший уровень абстракции. Типо:
Процедура Сдвинуть(Задача, ДатаЗадачи, ПриоритетЗадачи, Направление)
  ПредпоследняяЗадача = ПолучитьЗадачуДоТекущей(ДатаЗадачи, ДатаЗадачи, ПриоритетЗадачи, Направление);
КонецПроцедуры

Приоритет, как по мне всё же нужен.
Но, если по задаче нужно получать только время - в функции ПолучитьЗадачуДоТекущей можно получить задачу масимально приближенную по дате в текущей (исходя из направления) и добавить либо 1 сек. либо -1 сек, исходя из направления
Программист всегда исправляет последнюю ошибку.