Имя: Пароль:
1C
1С v8
Сложная сортировка в регистре сведений.
,
0 Crimscon
 
05.03.19
11:28
Пишу свою конфигурацию, где будет использован планировщик для отображения работы сотрудника и/или доступности данного сотрудника для приема.

Есть у меня справочник "графики работы". Где все данные раскиданы аккуратно и понятно. В ней я указываю сотруднику график работы. 2/2, 3/2, 5/2, будни. В справочнике указывается время и день по порядку, а дата уже в регистр пишется.

Возникает проблема, при записи этих данных из справочника в регистр и происходит неведомое, и график из пользовательского варианта:
Понедельник - с 9 до 15
Вторник - с 9 до 12
Среда - с 15 до 18.

После вытаскивания данных запросом по двум таблицам превращается в:
Понедельник с 9 до 15, номер дня 1
Понедельник с 9 до 12, номер дня 2
Понедельник с 15 до 18, номер дня 3
Вторник с 9 до 15, номер дня 1
Вторник с 9 до 12, номер дня 2
Вторник с 15 до 18, номер дня 3
...

Я выставляю дату, допустим 27 февраля. Это среда. И я не знаю какой этот день по порядку. Первый, второй или третий, а может и вовсе пятый. Я знаю только сколько всего дней в периоде графика. А за счёт регистра я могу узнать рабочий этот день в принципе или нет.

Мне нужно из этих данных найти первый день в периоде и узнать сколько дней прошло относительно первого дня, чтоб узнать выбранный день. Проблема возникает тогда, когда мне нужно найти период более 1 дня. Допустим, с 27 по 28 число. Или с 25 февраля по 1 марта.
И может быть так, что допустим, 27 не рабочий день вообще у конкретного сотрудника.

И если период у меня работает, хоть и с костылем, то если на неделе появляется праздник - вся работа функции плывет на количество дней. Если 3 выходных в рабочие дни, то в понедельник будет записан график за четверг и т.д.

В общем-то проблема именно в сортировке данных. Или я что-то накосячил с запросом, но честно говоря, я так и не пойму где ошибка. Код, если нужно, приложу отдельным сообщением.
1 Crimscon
 
05.03.19
11:28
Функция ПолучитьВремяРаботыСотрудника(Сотрудник, Период) Экспорт
    ТабГрафика = Новый ТаблицаЗначений;
    ТабГрафика.Колонки.Добавить("ДатаНачала");
    ТабГрафика.Колонки.Добавить("ДатаОкончания");
    ТабГрафика.Колонки.Добавить("ДатаГрафика");
    
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |    КалендариРасписаниеРаботы.НомерДня КАК НомерДня
    |ИЗ
    |    Справочник.Календари.РасписаниеРаботы КАК КалендариРасписаниеРаботы
    |ГДЕ
    |    КалендариРасписаниеРаботы.Ссылка.Сотрудник = &Сотрудник";
    
    Запрос.УстановитьПараметр("Сотрудник", Сотрудник);
    ДниВРасписании = Запрос.Выполнить().Выгрузить();
    КоличествоДнейГрафика = ДниВРасписании.Количество();
    КоличествоДнейПериода = Окр((Период.ДатаОкончания - Период.ДатаНачала) / 86400);
    
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    |    КалендарныеГрафики.ДатаГрафика КАК ДатаГрафика,
    |    КалендариРасписаниеРаботы.НомерДня КАК НомерДня,
    |    КалендариРасписаниеРаботы.ВремяНачала КАК ВремяНачала,
    |    КалендариРасписаниеРаботы.ВремяОкончания КАК ВремяОкончания,
    |    КалендарныеГрафики.ДеньВключенВГрафик КАК ДеньВключенВГрафик
    |ИЗ
    |    Справочник.Календари.РасписаниеРаботы КАК КалендариРасписаниеРаботы
    |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КалендарныеГрафики КАК КалендарныеГрафики
    |        ПО КалендарныеГрафики.Календарь = КалендариРасписаниеРаботы.Ссылка
    |ГДЕ
    |    КалендарныеГрафики.ДатаГрафика МЕЖДУ &ДатаНачала И &ДатаОкончания
    |    И КалендариРасписаниеРаботы.Ссылка.Сотрудник = &Сотрудник";
    
    Запрос.УстановитьПараметр("Сотрудник", Сотрудник);
    Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(Период.ДатаНачала - (86400    * Окр(КоличествоДнейГрафика / 2, 0, 1))));
    Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(Период.ДатаОкончания + (86400    * Окр(КоличествоДнейГрафика / 2, 0, 1))));
    
    Результат = Запрос.Выполнить().Выгрузить();
    Результат.Сортировать("ДатаГрафика Возр, НомерДня Возр");
    
    РезультатДляНомераДня = Запрос.Выполнить().Выгрузить();
    РезультатДляНомераДня.Сортировать("ДатаГрафика Возр, НомерДня Возр");    
    РезультатДляНомераДня.Свернуть("ДатаГрафика, ДеньВключенВГрафик");
    Итератор = 0;
    
    НомерДня = 1;
    НомерДняНачала = 0;
    НомерДняОкончания = 0;
    
    Пока КоличествоДнейГрафика <> 0 Цикл    
        Для Каждого Стр Из РезультатДляНомераДня Цикл        
            Если Период.ДатаНачала - (86400    * Окр(КоличествоДнейГрафика / 2, 0, 1)) = Стр.ДатаГрафика И НЕ Стр.ДеньВключенВГрафик Тогда
                Если КоличествоДнейГрафика = 0 Тогда
                    Прервать;
                КонецЕсли;
                КоличествоДнейГрафика = КоличествоДнейГрафика - 1;
            ИначеЕсли Период.ДатаНачала - (86400 * Окр(КоличествоДнейГрафика / 2, 0, 1)) = Стр.ДатаГрафика И Стр.ДеньВключенВГрафик Тогда
                Если КоличествоДнейГрафика = 0 Тогда
                    Прервать;
                КонецЕсли;
                НомерДняНачала = НомерДняНачала + 1;
                КоличествоДнейГрафика = КоличествоДнейГрафика - 1;
            КонецЕсли;
        КонецЦикла;            
    КонецЦикла;
    
    КоличествоДнейГрафика = ДниВРасписании.Количество();
    
    ПараметрыОтбора = Новый Структура;
    
    НеРабочийДень = 0;
    
    Для Итератор = 0 По КоличествоДнейПериода - 1 Цикл
        НачалоПериода = Период.ДатаНачала + (86400 * Итератор) + (86400 * НеРабочийДень);
        Если НачалоПериода <= Период.ДатаОкончания Тогда            
            Если Итератор = КоличествоДнейГрафика ИЛИ НомерДняНачала = КоличествоДнейГрафика Тогда
                НомерДняНачала = 1;
            ИначеЕсли Итератор > КоличествоДнейГрафика ИЛИ НомерДняНачала > КоличествоДнейГрафика Тогда
                НомерДняНачала = НомерДняНачала + 1;
            КонецЕсли;
            ПараметрыОтбора.Вставить("НомерДня", ?(Итератор + НомерДняНачала > КоличествоДнейГрафика, ?(Итератор > НомерДняНачала, НомерДняНачала, Итератор), Итератор + НомерДняНачала));
            ПараметрыОтбора.Вставить("ДатаГрафика", НачалоПериода);
            Строки = Результат.НайтиСтроки(ПараметрыОтбора);
            Если Строки.Количество() = 1 Тогда
                Если НЕ Строки[0].ДеньВключенВГрафик Тогда
                    Пока НЕ Строки[0].ДеньВключенВГрафик Цикл                        
                        //Итератор = ?(Итератор > КоличествоДнейГрафика, Итератор + 1, КоличествоДнейГрафика);                        
                        НеРабочийДень = НеРабочийДень + 1;
                        //ПараметрыОтбора.Вставить("НомерДня", ?(Итератор + НомерДняНачала > КоличествоДнейГрафика, ?(Итератор > НомерДняНачала, НомерДняНачала, Итератор), Итератор + НомерДняНачала));                
                        ПараметрыОтбора.Вставить("ДатаГрафика", Период.ДатаНачала + (86400 * Итератор) + (86400 * НеРабочийДень));
                        Строки = Результат.НайтиСтроки(ПараметрыОтбора);
                    КонецЦикла;
                КонецЕсли;                
                
                Строка = ТабГрафика.Добавить();
                Строка.ДатаГрафика = Строки[0].ДатаГрафика;
                Строка.ДатаНачала = Дата(Лев(Строки[0].ДатаГрафика, 11) + Прав(Строки[0].ВремяНачала,8));
                Строка.ДатаОкончания = Дата(Лев(Строки[0].ДатаГрафика, 11) + Прав(Строки[0].ВремяОкончания,8));
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;    
    
    Возврат ТабГрафика;        
КонецФункции
2 sqr4
 
05.03.19
11:31
Много букв, а че надо то
3 sqr4
 
05.03.19
11:33
И я бы вообще не признался что мое, тут люди злые.
4 Crimscon
 
05.03.19
11:33
Как сделать, чтоб график не плыл на выходных? Все написано на БСП 3.0.2, в справочник ГрафикиРаботы добавлено поле сотрудника, которое ссылается на аналогичный справочник. Это все изменения.

Поэтому собственно, либо косяк в запросе, либо данные из справочника так криво пишутся.
5 Йохохо
 
05.03.19
11:36
укради из зупа то, что ты хочешь
6 sqr4
 
05.03.19
11:37
(4) А куда он плывет, хорошо взорвал?)
Мне нужно из этих данных найти первый день в периоде и узнать сколько дней прошло относительно первого дня, чтоб узнать выбранный день. Проблема возникает тогда, когда мне нужно найти период более 1 дня. Допустим, с 27 по 28 число. Или с 25 февраля по 1 марта.
а это зачем?
7 sqr4
 
05.03.19
11:37
(5) ты бы лучше сразу его проклял, чем в ЗУП посылать что то забрать)
8 Йохохо
 
05.03.19
11:37
(7) индивидуальные графики можно и в 2.5 подсмотреть
9 Crimscon
 
05.03.19
11:38
(6) Если график начинается в понедельник, а мне нужно найти среду? Учитывая то, каким образом выводятся данные из регистра, мне приходится узнавать на какую дату приходится первый день. И относительно него уже отсчитывать циклом тот, который мне нужен.
10 Йохохо
 
05.03.19
11:39
(9) есть такая фигня деньгода()
11 Crimscon
 
05.03.19
11:41
(10) Окей. Это если график с пн по пт. А если он 2/2? Первый день по порядку в четверг, потом пятница. А мне нужен понедельник, например. В уме то я могу понять то, что понедельник это 2 день, а программе как это сказать?
12 Crimscon
 
05.03.19
11:41
(11) Ну или 1 день, смотря в какую сторону считать.
13 sqr4
 
05.03.19
11:44
(9) я когда был студентом делал так. День с которого принят сотрудник и от него отсчитывал по графику. В регистр писал все дни напротив каждого указывая рабочий он или нет
14 Crimscon
 
05.03.19
11:46
(13) Ну в общем-то в БСП оно само так и пишется. Только по параметрам, которые в справочнике указываю. Ну и криво пишется, да.
15 los_hooliganos
 
05.03.19
11:48
Чем не устраивает типовой механизм "график работы" из подсистемы "расчеты сотрудников"?
16 Garykom
 
гуру
05.03.19
11:48
А когда запросами 2+2 начнем считать?
17 Crimscon
 
05.03.19
12:10
Отбой. Я немного идиот, потому что, что не смотрел общие модули.
(15) Как раз то, что нужно. В общем модуле "ГрафикиРаботы" уже все написано и работает.
18 VladZ
 
05.03.19
12:15
(0) У тебя должен быть график работы сотрудников по датам. Привязать сотрудника к графику - этого недостаточно.  Сотрудник мог заболеть, или заменить кого-то. Нужен график по датам.
19 VladZ
 
05.03.19
12:17
После вытаскивания данных запросом по двум таблицам превращается в:
Понедельник с 9 до 15, номер дня 1
Понедельник с 9 до 12, номер дня 2
Понедельник с 15 до 18, номер дня 3
Вторник с 9 до 15, номер дня 1
Вторник с 9 до 12, номер дня 2
Вторник с 15 до 18, номер дня 3

- это какой-то информационный шум. Выбросить сразу!
Выдавать глобальные идеи — это удовольствие; искать сволочные маленькие ошибки — вот настоящая работа. Фредерик Брукс-младший