Задачка на вход-выход - сломал себе мозг

1. CheBurator 3121 15.10.08 02:36 Сейчас в теме
(копию запостил на Т1С http://www.kuban.ru/forum_new/forum9/files/315317.html)
.
Прошу помощи у сообщества...
.
на свою беду наваял в 1сине себе же простенький "пропускной пункт" - в котором идет простая регистрация простых событий входа/выхода сотрудников...
.
Регистрация пишется в плоскую таблицу из 3-х полей вида "Сотрудник, Событие, TimeStamp", например:
Петров ВХОД 20081013 11:34:15
Петров ВЫХОД 20081013 11:44:45
и т.д.
.
интервал от входа до выхода (присутствие на работе) может быть произвольно большой (например, пришел в понедельник, вышел в четверг - охрана так работает, я могу долго сидеть на работе и т.д.); интервал отстутствия на работе ("расстояние" от выхода до входа)- также может быть произвольно большой.
.
для обобщения задачи добавим условие: работа учитывается "посменно", для упрощения считаем что "рабочие" сутки начинаются в 8 часов утра текущего дня и заканчиваются в 8 часов следующего дня, "рабочие" сутки состоят из 2-х смен: дневной смены ДС (8:00-20:00) и ночной смены НС (20:00-8:00). Работник может оработать время, зацепив сразу две (три, а то и 4 смены) смены, например:
а) я пришел в 9:00 и ушел в 23:00 - на меня "учтется" в "рабочих" сутках ДС 9:00-20:00 и НС 20:00-23:00
б) я пришел в 7-30 утром и ушел 23:00 вечером того же дня: на меня учтется ДС 08:00-20:00 и НС 20:00-23:00; интервал 7:30-8:00 - зачитвается в "предыдущие" рабочие сутки.
.
требуется: составить "лист присутствия" сотрудников на работе, в котором должны быть для указанных "рабочих" суток зафиксированы время начала и окончания дневных и ночных смен; при этом входы-выходы "внутри" смены неактуальны, то есть, например:
а) я пришел в 9:00, вышел на обед в 13:00, вернулся с обеда в 14:00 и ушел с работы 21:00 - в "листе присутствия" получатся такие данные: ДС=9:00-20:00, НС=20:00-21:00
б) но если я не обедал, а выбежал на ужин в 19:30 и вернулся в 20:30, то будет в листе присутствия зафиксировано: ДС=9:00-19:30, НС=20:30-21:00
..
ПЕРВАЯ ТРИВИАЛЬНАЯ ЗАДАЧА:
Получить "лист присутсвия" для указанных "рабочих" суток для отдельно взятого сотрудника... (+ работать должен достаточно быстро - таких строчек обсчитываться может большое колво - но это условие не сильно актуально)
..
Сорри, за длительное вступление...
несмотря на кажущуюся простоту задачи - я над ней уже мозг сломал... Алгоритм есть, считает вроде правильно, но смотреть на него я без содрогания не могу... показать людям стыдно... не удовлетворяет он меня... недели через две - не "подыму"... реальный тупняк.. где-то здесь может надо схему данных или хитрый математический ход провернуть...
..
для кого-то это наверняка пройденный этап (для "зарплатников" всяких?), но я забодался реально.. ;-) спать эта задача спокойно не дает...
..
кому интересно/востребовано - подключайтесь...
..
при ломоте "работать забесплатно" - вопрос обсуждаем при качественном красивом и поянтно-читабельном алгоритме ;-)
..
Вдогонку, для поднятия интереса (в случае решения частной вышеизложенной задачи):
- интересует и общее решение, т.е. что две смены, которые закрывают сутки, что три смены, которые закрывают сутки; ясен пень, что смены идут "паравозиком", то есть разрывов между сменами - нет...
- вторую "вдагонялку" озвучу позже, когда с этой разберемся (если разберемся ;-)
..
я так думаю, что настоящие программисты быстро щелкнут эту задачку... (и хитро так по ленински прищурился)
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. ssp_ 153 15.10.08 12:34 Сейчас в теме
Все просто.
Регистр остатков.
Измерения: Сотрудник, Смена
Ресурсы: НаРаботе, Был

Когда приходит:
Код
   Рег.ДвижениеПриход(Сотрудник, Смена, 1,1); // остаток: НаРаботе=1, Был=1
Показать полностью


Когда уходит:
Код
   Рег.ДвижениеРасход(Сотрудник, Смена, 1,0); // остаток: НаРаботе=0, Был=1
Показать полностью


При приходе нужна проверка, может человек уже приходил в этой смене:
Код
Если Рег.Остаток(Сотрудник, Смена,"Был")>0 Тогда
    НайтиИУдалитьПрошлыйУходВЭтойСмене(); // считаем, что не уходил
    СтаусВозврата(0); // и не приходил
Иначе
    Рег.ДвижениеПриход(Сотрудник, Смена, 1,1);
КонецЕсли;
Показать полностью


И, наконец, при завершении смены обнуляем остатко по НаРаботе и Был по законченной смене, и переносим остатки в новую смену по сотрудникам, у которых НаРаботе=1

Вроде всё. И смен может быть сколько угодно.
3. lefthander 15.10.08 14:14 Сейчас в теме
**Все просто.
Регистр остатков.
------------------------------
но тогда нужен документ который этот регистр двинет... на каждый вход/выход по документику ...
На вскидку, не размышляя - завести периодический реквизит в спр пользователи и по принципу выше отслеживать состояние, изменять состояние по внешнему событию. обработкой считывать инфу с реквизита за период и принимать решение. За эталон можно взять известные состояния. (табель, расписание смен с привязкой по времени)
ИМХО реквизитов может быть больше и разрядность может быть больше 2 :-)

Немного подумал....
Пример реквизит имеет вид 00000
1 разр: 0 - вышел 1-вошел
2,3 разряд 00- не работает или в отпуске или уволен, 01 график с 8.00 до 17.00 перерыв 12.00 13.00 ну и так далее 02, 03 до 99 график работы
4 разряд на обеде 1 не на обеде 0
5 разряд корректировка - для возможных смещений по некоторым графикам 0 - не допускается корректировка человек должен строго приходить и уходить для сменных графиков 1 - возможна корректировка времени типа ушел на обед в 11.50 и с обеда должен вернуться в 12.50 ну и так далее по фантазии
итого имеем на 11.00 значение 10100 на работе по графику 01
на 12.30 00110 вышел на обед
на 19.30 00100 ушел с работы
т.о. для каждого графика работы, на каждый момент времени имеем определенное значение реквизита его и сравниваем с записанными в справочник совпало - хорошо, нет в отчете видно что именно есть и что должно быть:-)
4. Pavlovsky 56 15.10.08 14:42 Сейчас в теме
Вижу это так.
Нужно два документа:
Документ "График". Документ задает время когда работник должен находиться на работе
Документ "Пропуск". Фиксирует время прихода ухода

Таблица №1
Регистратор время Статус
Пропуск(вход) 00:00 не рабочее
График (начало) 00:15 рабочее
Пропуск(выход) 01:30 рабочее
Пропуск(вход) 02:30 рабочее
Пропуск(выход) 05:45 рабочее
График (конец) 06:00 не рабочее

По данным из таблицы №1 строим таблицу №2
Начало Конец Статус
00:00 00:15 пришел на работу заранее
00:15 01:30 работает
01:30 02:30 отсутствовал на работе
02:30 05:45 работает
05:45 06:00 преждевременный уход с работы
06:00 --:-- отдыхает

Стаусов в таблице №2 может быть много

По этим таблицам можно собрать любой отчет



5. Pavlovsky 56 15.10.08 14:52 Сейчас в теме
Как это реализовать на платформе 7.7 Фиг его знает. Первое, что приходит в голову - справочники.
6. ssp_ 153 15.10.08 17:46 Сейчас в теме
2 lefthander
А что даст периодический реквизит? Двигать без документа мы его можем только на начало дня, а на определенное время - только документом.
Задача поставлена так, чтобы мы видели события прихода и ухода. Что у нас предназначено для отражения событий? Документы.
Справочники тут как-то не очень подходит.
А хранить инфу о присутствии в регистрах выглядит красивее. и работать с ними удобнее на мой взгляд.
7. CheBurator 3121 15.10.08 19:21 Сейчас в теме
2 ssp_
.
некузяво...
+ вчитайтесь в сабж.
во время работы _РЕГИСТРАЦИИ СОБЫТИЙ_ - минимум вычислений! никаких блокировок, никаких документов, никаких регистров. Никаких смен/графиков. Работник может прийти и выйти в любое время.
низачот, так как описано совсем не то, что я предложил "порешать".
.
.
2 lefthander
.
вся периодика хранится в одном файле - потенциальные проблемы с блокировками.
во время регистрации - никаких графиков и смен нет! все успешно регистрируется и так.
Задача - красиво разложить решение ЗАДАННОГО в сабже.
.
.
2 Pavlovsky
не то!
мне всего-то надо:
- все время когда работник на работе = рабочее!
- нужен как раз _алгорим_ построения таблицы №2, причем таблица 2 должна В ДАННОМ Примере получится такой (при ночной смене с 0-15 до 6-00 и дневной смене с 6-00 до 0-15, ночная смена относится к предыдущему дню!)
Петров, Дневная смена: 00-00(вход) 00-15(выход) (при этом еще нужно знать, что сотрудник не входил в дневной смене раньше или вошел в предыдущую ночную смену и трудится как стахановец!!!! - из-за этого время входа в ДС - другое будет!, для упрощения примем - это первый рабочий день сотрудника.), Ночная смена 00-15 (вход), 5-45 (выход)
..
2 ssp
>Задача поставлена так, чтобы мы видели события прихода и ухода.
задача поставлена так, что нужно знать (в отчете): чтобы мы видели события прихода и ухода _В СМЕНУ_, т.е. время начала работы в смене и время окончания работы в смене...
итого: все предложения - бяка
8. vovan519 276 16.10.08 01:13 Сейчас в теме
Che не совсем понимаю в чем проблема. Поэтому может не в тему.
Если ты все же остановился на справочниках...
Время и дату события удобней регистрировать в формате похожим на DateTime. Т.е. количество секунд (или минут, если точность не важна) от какого-то дня.
Любая смена - это период между двумя датами с временем. Преобразовываем в наш формат и делаем запрос , НашеВремя > начало И НашеВремя < конец
Ну например в минутах от 1 января 2008г
Хотим посмотреть что делал наш Вася с 15 октября 22:35 по 16 октября 0:57
Начало = 288*24*60+22*60+35=415283
Конец = 289*24*60+0*60+57=416217
Пишем запрос Имя = Вася НашеВремя > 415283 НашеВремя < 416217
Получаем Все события за смену с 15 октября 22:35 по 16 октября 0:57
Вроде это должно работать быстро.
9. CheBurator 3121 16.10.08 01:32 Сейчас в теме
2 vovan519
да! примерно так и делаю!!!
но одним запросом не обойтись!!
за период отчета - может быть НЕ ЗАРЕГИСТРИРОВАНО НИ ОДНОГО СОБЫТИЯ!!!! но оно - есть!!!!!
пример: охрана пришла в понедельник, ушла в пятницу, отчет снимаем за среду - должно проставиться вход-выход дневная смена и вход-выход ночная смена!!!! а для этого надо _получить_ событие ДО моего периода!!!
10. vovan519 276 16.10.08 01:48 Сейчас в теме
Да, Че, регистровых итогов у справочников нет.
Я так понимаю - это единственная проблема, когда в выбранном периоде нет ни одного события?
11. CheBurator 3121 16.10.08 02:58 Сейчас в теме
ну, в принципе - да...
необходимость обращаться к событиям вне периода (как спереди периода, так и сзади) - ломает на! всю красоту...
12. Altair777 644 16.10.08 04:09 Сейчас в теме
Навскидку, среди ночи попробую предложить :-)

1) Нужен механизм закрытия/открытия смены. Ищется, кто еще не вышел, ему ставится выход и в следующей смене сразу же ставится вход. Когда смена закрыта, все телодвижения сотрудников попадают в следующие смены.
2) когда сотрудник приходит, проверка был ли выход в ненезакрытой смене? Если да, то запись уничтожается, если нет, то делается новая о входе.
3) Когда сотрудник выходит, просто делается запись о выходе.
13. Altair777 644 16.10.08 04:38 Сейчас в теме
Физически можно сделать так.

1) Основная таблица с закрытыми сменами

2) На каждого сотрудника маленькие таблички по текущей смене. Например, документы или дбф-файлы.
Проблемы с блокировками быть не может, т.к. один сотрудник не может одновременно совершить 2 действия и, тем более, на разных КПП.

3) При закрытии смены анализируются только "персональные" таблицы сотрудников.
Если там 2 записи, значит он ушел, их просто нужно объединить с общей таблицей.
Если 1 запись, перенести ее в сновную таблицу, добавить в основной запись о выходе концом смены, а в табличке заменить дату и время входа началом смены.

4) В случае хранения персональных таблиц во внешних файлах, алгоритм чуть-чуть модифицируется.
Перед обработкой персональных таблиц их нужно перенести в другое место, не менять 1 запись, а создавать новый файл в "штатном" месте с одной записью о входе.
14. AVARY 175 16.10.08 05:00 Сейчас в теме
Отчетик получился вот такой:
Код
Перем СобытиеПриход;

///////////////////////////////////////////////////////////////////////////////
// Функция ПолучитьВремяНачалаСмены(ГрафикСмен, НомерСмены)
//
// Параметры:
//   ГрафикСмен   - ТаблицаЗначений. Таблица значений, содержащая информацию о
//              графике смен предприятия. Структура таблицы:
//              1. ВремяНачалаСмены      - Число, время начала смены в секундах;
//              2. ВремяОкончанияСмены   - Число, время окончания смены в секундах;
//              Время начала и окончания n-й смены находятся в (n-1)-й строке
//   НомерСмены   - Число. Номер смены, время начала в секундах которой необходимо
//              получить.
//
// Описание:
//   Функция рассчитывает время начала смены "НомерСмены".
//   
// Возвращаемое значение:
//   ВремяНачалаСмены - Число, время начала смены "НомерСмены" по грфику "ГрафикСмен" в
//                   секундах от начала дня.
Функция ПолучитьВремяНачалаСмены(ГрафикСмен, НомерСмены)

   ВремяНачалаСмены = 0;
   
   // Алгоритм получения времени начала смены в секундах от начала дня по графику
   // смен и номеру смены
   
   Возврат ВремяНачалаСмены;

КонецФункции // ПолучитьВремяНачалаСмены(ГрафикСмен, НомерСмены)

///////////////////////////////////////////////////////////////////////////////
// Функция ПолучитьВремяОкончанияСмены(ГрафикСмен, НомерСмены)
//
// Параметры:
//   ГрафикСмен   - ТаблицаЗначений. Таблица значений, содержащая информацию о
//              графике смен предприятия. Структура таблицы:
//              1. ВремяНачалаСмены      - Число, время начала смены в секундах;
//              2. ВремяОкончанияСмены   - Число, время окончания смены в секундах;
//              Время начала и окончания n-й смены находятся в (n-1)-й строке;
//   НомерСмены   - Число. Номер смены, время окончания в секундах которой необходимо
//              получить.
//
// Описание:
//   Функция рассчитывает время окончания смены "НомерСмены".
//   
// Возвращаемое значение:
//   ВремяОкончанияСмены - Число, время окончания смены "НомерСмены" по грфику "ГрафикСмен" в
//                     секундах от начала дня.
Функция ПолучитьВремяОкончанияСмены(ГрафикСмен, НомерСмены)

   ВремяОкончанияСмены = 0;
   
   // Алгоритм получения времени окончания смены в секундах от начала дня по графику
   // смен и номеру смены
   
   Возврат ВремяОкончанияСмены;

КонецФункции // ПолучитьВремяОкончанияСмены(ГрафикСмен, НомерСмены)

///////////////////////////////////////////////////////////////////////////////
// Функция ПолучитьДатуСобытия(ДатаВремяСобытия)
//
// Параметры:
//   ДатаВремяСобытия - Строка. Строка, содержащая информацию о дате и времени события.
//
// Описание:
//   Функция получает дату из строки, содержащей информацию о дате и времени события.
//   
// Возвращаемое значение:
//   ДатаСобытия - Дата. Дата события.
Функция ПолучитьДатуСобытия(ДатаВремяСобытия)

   ДатаСобытия = 0;
   
   // Алгоритм получения даты события из даты-времени события
   
   Возврат ДатаСобытия;

КонецФункции // ПолучитьДатуСобытия(ДатаВремяСобытия)

///////////////////////////////////////////////////////////////////////////////
// Функция ПолучитьВремяСобытия(ДатаВремяСобытия)
//
// Параметры:
//   ДатаВремяСобытия - Строка. Строка, содержащая информацию о дате и времени события.
//
// Описание:
//   Функция получает время из строки, содержащей информацию о дате и времени события.
//   
// Возвращаемое значение:
//   ВремяСобытия - Число. Время события в секундах от начала дня.
Функция ПолучитьВремяСобытия(ДатаВремяСобытия)

   ВремяСобытия = 0;
   
   // Алгоритм получения времени события в секундах от начала дня из даты-времени события
   
   Возврат ВремяСобытия;

КонецФункции // ПолучитьВремяСобытия(ДатаВремяСобытия)

///////////////////////////////////////////////////////////////////////////////
// Функция ПолучитьНомерСмены(ГрафикСмен, ВремяСобытия)
//
// Параметры:
//   ГрафикСмен      - ТаблицаЗначений. Таблица значений, содержащая информацию о
//                 графике смен предприятия. Структура таблицы:
//                 1. ВремяНачалаСмены      - Число, время начала смены в секундах;
//                 2. ВремяОкончанияСмены   - Число, время окончания смены в секундах;
//                 Время начала и окончания n-й смены находятся в (n-1)-й строке;
//   ВремяСобытия   - Число. Время события в секундах от начала дня.
//
// Описание:
//   Функция определяет номер смены в которую входит время события.
//   
// Возвращаемое значение:
//   НомерСмены - Число. Номер смены, который соответствуют времени события "ВремяСобытия".
Функция ПолучитьНомерСмены(ГрафикСмен, ВремяСобытия)

   НомерСмены = 0;
   
   // Алгоритм определения номера смены по графику смен и времени события
   
   Возврат НомерСмены;

КонецФункции // ПолучитьНомерСмены(ГрафикСмен, ВремяСобытия)

///////////////////////////////////////////////////////////////////////////////
// Процедура ЗафиксироватьСобытиеВЛистеПрисутствия(ЛистПрисутствия, ГрафикСмен, Событие, ВремяСобытия)
//
// Параметры:
//   ЛистПрисутствия   - ТаблицаЗначений. Таблица значений, содержащая информацию о времени
//                 прихода и ухода в разрезе смен. Структура таблицы:
//                 1. ВремяПрихода   - Число. Время прихода на смену;
//                 2. ВремяУхода      - Число. Время ухода со смены;
//                 Время прихода и ухода на/с n-й смены находятся в (n-1)-й строке;
//   ГрафикСмен      - ТаблицаЗначений. Таблица значений, содержащая информацию о
//                 графике смен предприятия. Структура таблицы:
//                 1. ВремяНачалаСмены      - Число, время начала смены в секундах;
//                 2. ВремяОкончанияСмены   - Число, время окончания смены в секундах;
//                 Время начала и окончания n-й смены находятся в (n-1)-й строке;
//   Событие         - Строка. Вид события: "Вход", "Выход";
//   ВремяСобытия   - Число. Время события в секундах от начала дня.
//   
// Описание:
//   Процедура фиксирует события в листе присутствия.
Процедура ЗафиксироватьСобытиеВЛистеПрисутствия(ЛистПрисутствия, ГрафикСмен, Событие, ВремяСобытия)

   НомерСмены = ПолучитьНомерСмены(ГрафикСмен, ВремяСобытия);
   
   // Если фиксируемое событие это приход и ранее в эту смену приход не фиксировался
   // или время этого события меньше чем время прихода в эту смену уже проставленного
   // в листе присутствия, то проставляем новое время прихода в листе присутствия
   // Если фиксируемое событие это уход и ранее в эту смену уход не фиксировался
   // или время зафиксированного ухода меньше чем время фиксируемого события, то
   // проставляем новое время ухода в листе присутствия
   Если Событие = СобытиеПриход Тогда 
      
      ВремяПрихода = ЛистПрисутствия[НомерСмены - 1].ВремяПрихода;
      
      Если ВремяПрихода = Неопределено Тогда 
         
         ЛистПрисутствия[НомерСмены - 1].ВремяПрихода = ВремяСобытия;
         
      Иначе 
         
         Если ВремяСобытия < ВремяПрихода Тогда 
            
            ЛистПрисутствия[НомерСмены - 1].ВремяПрихода = ВремяСобытия;
            
         КонецЕсли;
         
      КонецЕсли;
      
   Иначе 
      
      ВремяУхода = ЛистПрисутствия[НомерСмены - 1].ВремяУхода;
      
      Если ВремяУхода = Неопределено Тогда 
         
         ЛистПрисутствия[НомерСмены - 1].ВремяУхода = ВремяСобытия;
         
      Иначе 
         
         Если ВремяСобытия > ВремяУхода Тогда 
            
            ЛистПрисутствия[НомерСмены - 1].ВремяУхода = ВремяСобытия;
            
         КонецЕсли;
         
      КонецЕсли;
      
   КонецЕсли; // Конец проверки вида события
   
КонецПроцедуры // ЗафиксироватьСобытиеВЛистеПрисутствия(ЛистПрисутствия, ГрафикСмен, Событие, ВремяСобытия)

///////////////////////////////////////////////////////////////////////////////
// Функция СформироватьЛистПрисутствия(ГрафикСмен,
//                              ТаблицаСобытий,
//                              Сотрудник,
//                              ДатаРабочихСуток)
//
// Параметры:
//   ГрафикСмен         - ТаблицаЗначений. Таблица значений, содержащая информацию о
//                    графике смен предприятия. Структура таблицы:
//                    1. ВремяНачалаСмены      - Число, время начала смены в секундах;
//                    2. ВремяОкончанияСмены   - Число, время окончания смены в секундах;
//                    Время начала и окончания n-й смены находятся в (n-1)-й строке;
//   ТаблицаСобытий      - ТаблицаЗначений. Таблица значений, содержащая информацию о событиях
//                    входа/выхода в разрезе сотрудников. Структура таблицы:
//                    1. Сотрудник   - Справочник.ХХХ, сотрудник по которому зафиксировано событие;
//                    2. Событие   - Строка, вид события "Вход", "Выход";
//                    3. TimeStamp   - Строка, дата и время события;
//   Сотрудник         - Справочник.ХХХ. Сотрудник по которому необходимо сформировать лист присутствия;
//   ДатаРабочихСуток   - Дата. Дата рабочих суток, по которой необходимо сформировать отчет.
//
// Описание:
//   Функция формирует лист присутствия по заданному сотруднику, на указанную рабочую дату.
//   
// Возвращаемое значение:
//   ЛистПрисутствия   - ТаблицаЗначений. Структура таблицы:
//                 1. ВремяПрихода   - Число. Время прихода на смену в секундах от начала дня;
//                 2. ВремяУхода      - Число. Время ухода со смены в секундах от начала дня.
//                 Время прихода и ухода на/с n-й смены находятся в (n-1)-й строке;
Функция СформироватьЛистПрисутствия(ГрафикСмен,
                           ТаблицаСобытий,
                           Сотрудник,
                           ДатаРабочихСуток)
                           
   ЛистПрисутствия = Новый ТаблицаЗначений;
   ЛистПрисутствия.Колонки.Добавить("ВремяПрихода");
   ЛистПрисутствия.Колонки.Добавить("ВремяУхода");
   
   // Сформируем строки листа присутствия согласно количества смен в графике смен
   КоличествоСмен = ГрафикСмен.Количество();
   
   Для НомерСмены = 1 По КоличествоСмен Цикл
      
      ЛистПрисутствияСтрока = ЛистПрисутствия.Добавить();
      ЛистПрисутствияСтрока.ВремяПрихода    = Неопределено;
      ЛистПрисутствияСтрока.ВремяУхода   = Неопределено;
      
   КонецЦикла;
   
   // Определим дату и время начала первой смены, а также дату и время окончания
   // последней смены, для отсева событий по дате смены листа присутствия
   ДатаНачалаПервойСмены          = ДатаРабочихСуток;
   ВремяНачалаПервойСмены          = ГрафикСмен[0].ВремяНачалаСмены;
   ВремяОкончанияПоследнейСмены   = ГрафикСмен[КоличествоСмен - 1].ВремяОкончанияСмены;
   
   // Если время окончания последней смены меньше времени начала первой смены, то
   // считаем, что дата окончания последней смены это дата, следующая за датой
   // начала первой смены иначе она равна дате начала первой смены
   ДатаОкончанияПоследнейСмены = ДатаНачалаПервойСмены;
   
   Если ВремяОкончанияПоследнейСмены < ВремяНачалаПервойСмены Тогда 
      
      ДатаОкончанияПоследнейСмены = ДатаНачалаПервойСмены + 1;
      
   КонецЕсли;
   
   // Зафиксируем наличие незакрытого прихода сотрудника до начала рабочих суток на 
   // дату "ДатаРабочихСуток", это необходимо если в течении рабочих суток сотрудником 
   // не производилось событие входа, т. е. он начал работу в предыдущие рабочие сутки
   ДатаПоследнегоПриходаДоРабочихСутокОтчета    = Дата("00010101");
   ВремяПоследнегоПриходаДоРабочихСутокОтчета   = 0;
   ДатаПоследнегоУходаДоРабочихСутокОтчета      = Дата("00010101");
   ВремяПоследнегоУходаДоРабочихСутокОтчета   = 0;
   
   // Просеиваем таблицу событий по сотруднику, дате и вемени события
   Для Каждого ТаблицаСобытийСтрока Из ТаблицаСобытий Цикл
      
      СотрудникСобытия    = ТаблицаСобытийСтрока.Сотрудник;
      Событие            = ТаблицаСобытийСтрока.Событие;
      ДатаВремяСобытия   = ТаблицаСобытийСтрока.TimeStamp;
      
      Если СотрудникСобытия <> Сотрудник Тогда
         
         Продолжить;
         
      КонецЕсли;
      
      ДатаСобытия    = ПолучитьДатуСобытия(ДатаВремяСобытия);
      ВремяСобытия   = ПолучитьВремяСобытия(ДатаВремяСобытия);
      
      // Если событие попадает в рабочие сутки по которым строится отчет, то заносим
      // его в лист присутствия
      Если 
         (
            (ДатаНачалаПервойСмены = ДатаОкончанияПоследнейСмены)
         И   (ДатаСобытия = ДатаНачалаПервойСмены)
         И   (ВремяСобытия >= ВремяНачалаПервойСмены)
         И   (ВремяСобытия <= ВремяОкончанияПоследнейСмены)
         )
      Или 
         (
            (ДатаНачалаПервойСмены <> ДатаОкончанияПоследнейСмены)
         И   (ДатаСобытия = ДатаНачалаПервойСмены)
         И   (ВремяСобытия >= ВремяНачалаПервойСмены)
         )
      Или 
         (
            (ДатаНачалаПервойСмены <> ДатаОкончанияПоследнейСмены)
         И   (ДатаСобытия = ДатаОкончанияПоследнейСмены)
         И   (ВремяСобытия <= ВремяОкончанияПоследнейСмены)
         )
      Тогда 
      
         // Событие входит в рабочие сутки, по котрым строится отчет
         
         // Фиксируем событие в листе присутствия
         ЗафиксироватьСобытиеВЛистеПрисутствия(ЛистПрисутствия, ГрафикСмен, Событие, ВремяСобытия);
         
      // Фиксируем последний незакрытый приход жо начала рабочих суток,
      // по котрым строится отчет         
      ИначеЕсли    
         (
            (ДатаСобытия = ДатаНачалаПервойСмены)
         И   (ВремяСобытия < ВремяНачалаПервойСмены)
         )
      Или 
         (ДатаСобытия < ДатаНачалаПервойСмены)
      Тогда
      
         Если Событие = СобытиеПриход Тогда 
            
            Если 
               (ДатаСобытия > ДатаПоследнегоПриходаДоРабочихСутокОтчета)
            И   (ВремяСобытия > ВремяПоследнегоПриходаДоРабочихСутокОтчета)
            Тогда 
            
               ДатаПоследнегоПриходаДоРабочихСутокОтчета    = ДатаСобытия;
               ВремяПоследнегоПриходаДоРабочихСутокОтчета    = ВремяСобытия;
               
            КонецЕсли;
            
         Иначе // Событие ухода
            
            Если 
               (ДатаСобытия > ДатаПоследнегоУходаДоРабочихСутокОтчета)
            И   (ВремяСобытия > ВремяПоследнегоУходаДоРабочихСутокОтчета)
            Тогда 
            
               ДатаПоследнегоУходаДоРабочихСутокОтчета    = ДатаСобытия;
               ВремяПоследнегоУходаДоРабочихСутокОтчета    = ВремяСобытия;
               
            КонецЕсли;
            
         КонецЕсли; // Конец проверки вида события
                  
      КонецЕсли; // Конец проверки вхождения события в рабочие сутки отчета
      
   КонецЦикла; // Конец цикла по таблице событий
   
   // Производим обработку полученного листа присутствия:
   // 1. Обрабатываем незакрытое время прихода до начала рабочих суток отчета
   // 2. Посменно обрабатываем незакрытые времена прихода в течение рабочих суток отчета
   
   // Обрабатываем незакрытое время прихода до начала рабочих суток отчета, если есть
   // нехакрытое время прихода в предыдущие рабочие сутки, то время начала работы в первую
   // смену равно времени начала первой смены
   Если 
      (ДатаПоследнегоУходаДоРабочихСутокОтчета < ДатаПоследнегоПриходаДоРабочихСутокОтчета)
   Или 
      (
         (ДатаПоследнегоПриходаДоРабочихСутокОтчета = ДатаПоследнегоУходаДоРабочихСутокОтчета)
      И   (ВремяПоследнегоУходаДоРабочихСутокОтчета < ВремяПоследнегоПриходаДоРабочихСутокОтчета)
      )
   Тогда 
   
      ЛистПрисутствия[0].ВремяПрихода = ПолучитьВремяНачалаСмены(ГрафикСмен, 1);
   
   КонецЕсли; // Конец проверки наличия незакрытого прихода до начала рабочих суток отчета
   
   // Обрабатываем незакрытые времена прихода в течение рабочих суток:
   // Если время прихода есть, а времени ухода нет, то время ухода равно времени
   // окончания рабочей смены, время прихода на следующую рабочую смену равно
   // времени начала следующей рабочей смены
   Для НомерСмены = 1 По КоличествоСмен Цикл 
      
      ВремяПрихода    = ЛистПрисутствия[НомерСмены - 1].ВремяПрихода;
      ВремяУхода      = ЛистПрисутствия[НомерСмены - 1].ВремяУхода;
      
      Если 
         (ВремяУхода = Неопределено)
      И   (ВремяПрихода <> Неопределено)
      Тогда 
      
         ВремяУхода = ПолучитьВремяОкончанияСмены(ГрафикСмен, НомерСмены);
         
         ЛистПрисутствия[НомерСмены - 1].ВремяУхода = ВремяУхода;
         
         // Если это не последняя смена, то время прихода на следующую смену
         // будет равно началу этой смены
         Если НомерСмены <> КоличествоСмен Тогда 
            
            ЛистПрисутствия[НомерСмены].ВремяПрихода = ПолучитьВремяНачалаСмены(ГрафикСмен, НомерСмены + 1);
            
         КонецЕсли;
         
      КонецЕсли; // Конец проверки наличия времени ухода при наличии времени прихода
      
   КонецЦикла; // Конец цикла по сменам листа присутствия
      
   Возврат ЛистПрисутствия;

КонецФункции // СформироватьЛистПрисутствия(ГрафикСмен,
          //                           ТаблицаСобытий,
          //                           Сотрудник,
          //                           ДатаРабочихСуток)
Показать полностью

Для оптимизации получения незакрытого входа или неоткрытого выхода в разрезе рабочих суток можно ввести дополнительные таблички: Дата, ВремяНезакрытогоВхода и Дата, ВремяНеоткрытогоВыхода.
15. ssp_ 153 16.10.08 08:59 Сейчас в теме
> во время работы _РЕГИСТРАЦИИ СОБЫТИЙ_ - минимум вычислений!
Ну так и не надо ничего вычислять при самом событии. Писать инфу куда угодно, хоть в текстовый файл. А потом, при появлении свободного момента, делать попытку провести это документом. И так пока не получится.
16. Altair777 644 16.10.08 09:03 Сейчас в теме
Зачем привязываться к сменам? Рассчитывать их номера и время начала?
Закрыли смену и забыли. Работаем с текущей.
17. Душелов 4018 16.10.08 09:18 Сейчас в теме
(0) Посмотри у меня в системе учета рабочего времени - работа со скользящими графиками ;)
18. ineoosaki 16.10.08 20:04 Сейчас в теме
Che, глянь внизу страницы, может, это то, что ты ищешь:
http://warenic.narod.ru/work.html
19. vovan519 276 16.10.08 23:16 Сейчас в теме
Че, если ты еще не отказался от справочников, то продолжим
"необходимость обращаться к событиям вне периода (как спереди периода, так и сзади) - ломает на! всю красоту... "
В справочнике "Клиент" добавить периодический реквизит "СобытиеКлиента".
В случае возникновения события:
1 как положено создаем элемент в справочнике "События"
2 кроме этого записываем этот элемент в реквизит СобытиеКлиента справочника Клиент на дату возникновения события.
В результате клиент Вася пришел 1 числа и не уходил до 5 (напился скатина и уснул).
1 числа сделали запись о событии и засунули его в пер.реквизит на 1 число.
Делаем отчет со 2 по 3. Событий нет. Смотрим в справочнике "Клиент" реквизит "СобытиеКлиента", на нач. дату нашего отчета ( т.е. 2), и там находим последнюю запись о событии приход, которую мы создали на 1 число, когда он пришел.
Все
О минусах: Как всегда работа задним числом. Хотя в момент записи периодического реквизита не трудно сделать проверку по дате и времени.
20. CheBurator 3121 17.10.08 00:07 Сейчас в теме
2 Altair777
> когда сотрудник приходит, проверка был ли выход в ненезакрытой смене?
я не знаю.. приходит сотрудник иди выходит ВРЕАЛЬНОСТИ! я регистрирую ОЧЕРЕДНОЕ СОБЫТИЕ = NOT.Последнее событие
(для упрощения - сотрудники дисциплинированные и всегда не забывают регистрироовать приход/уход)
21. CheBurator 3121 17.10.08 00:08 Сейчас в теме
> 3) Когда сотрудник выходит, просто делается запись о выходе.
- абсурд, то есть не имеет смысла... см.предыдущий пост.
22. CheBurator 3121 17.10.08 00:09 Сейчас в теме
2 AVARY
спсб, оперативно проанализировать код не имею возможности, будет рассмотрен внимательно позднее
23. CheBurator 3121 17.10.08 00:17 Сейчас в теме
2 vovan519 16.10.2008 23:16:57
> Че, если ты еще не отказался от справочников, то продолжим
..спсб! это - мысль! (надо тщательно обдумать)
проблемы "заднего числа" - НЕТ В ПРИНЦИПЕ, так как СОБЫТИЕ - ЭТО РЕАЛЬНОСТЬ В ТА ;-)
..
всем спсб!
сорри, если оператвино не отпишусь...
24. Altair777 644 17.10.08 08:56 Сейчас в теме
2 Сhe Burashka
Если запись есть, то он уходит. Если нет, то приходит.
Совсем не абсурд :-)
25. CheBurator 3121 17.10.08 14:12 Сейчас в теме
Абсурд!
3) Когда сотрудник выходит, просто делается запись о выходе.

Перевожу на язык программы:
Код
Если  ФизическийСубъект.Действие.Выходит = Истина
Тогда СделатьзаписьВЫХОД();
КонецЕсли; 
Показать полностью


Когда делается запись - неизвестно, входит сотрудник или выходит...
известно его предыдущее состояние, зарегистрированное в системе!
При этом сотрудник можер РЕАЛЬНО ВЫХОДИТЬ, но запись сделается - о входе (если он "сумел" войти мимо регистратора)
..
ТекущееСобытие = НЕ ПредыдущееСобытие;
- никакого сотрудника здесь нет, есть лишь его предыдущее состояние...
26. vovan519 276 17.10.08 14:20 Сейчас в теме
"ТекущееСобытие = НЕ ПредыдущееСобытие"
Вот и сюда удобнее прекрутить периодический реквизит, не так ли?
27. hogik 443 17.10.08 19:10 Сейчас в теме
Удалил своё сообщение, т.к. написал явно не в тему.
28. CheBurator 3121 18.10.08 00:40 Сейчас в теме
> "ТекущееСобытие = НЕ ПредыдущееСобытие"
Вот и сюда удобнее прекрутить периодический реквизит,
- не удобнее! вся периодика - хранится в одном файле! при активной работе с нескольких точек - имхо возможны потенциальные проблемы...
29. hogik 443 18.10.08 02:23 Сейчас в теме
Сергей.
Я посмотрел внимательно на то как у меня сделана аналогичная задача в части хранения информации. Это справочник подчиненный справочнику "Сотрудники". В наименовании хранится ГГГГММДДЧЧММ. И еще один реквизит - "Направление". Он принимает значение 0 - вход на предприятие, 1 - выход с предприятия. Отчеты формируются простым циклом просмотра этого справочника в порядке наименования. Для ускорения просмотра используется аналог функции Scope (операция #30) из моих разработок (DBEng32 для Advantage 8.1/CodeBase 6.5). За неимением этой возможности (функции), думаю, придётся периодически удалять записи этого справочника потерявшие актуальность. Или сделать еще один реквизит отбора - "актуальность учетной записи" и управлять его значением, по мере необходимости, специальной утилитой. Т.е. иметь возможность "скрывать"/"открывать" старые записи.
А что еще можно придумать в 1С 7.7? Сомневаюсь.
30. CheBurator 3121 18.10.08 02:56 Сейчас в теме
2 hogik:
у меня практически так же (см. http://infostart.ru/profile/174/projects/2614/image.php?img=2079)
> Отчеты формируются простым циклом просмотра этого справочника в порядке наименования.
- вот как раз эту задачу хочется решить "красиво"
31. hogik 443 18.10.08 03:47 Сейчас в теме
"Красиво" в части скорости - можно значение реквизита "актуальности учетной записи" вести автоматически. Например, при формировании очередного отчета расставлять признак "устаревшей записи" в записи двухмесячной давности.
И отбор через:
ИспользоватьВладельца()
ПорядокНаименований()
ВыбратьЭлементыПоЗначениюРеквизита("СтараяЗапись",0)
будет работать быстрее.
А в части самого анализа записей - какие там могут быть красоты? При том, что в 1С 7.7 нет никакой возможности построить нормальную схему базы данных. :-((( Меня в таких задачах только и спасают мои расширения из DBEng32 (ДУСы да РУСы всякие).
32. redgad 80 18.10.08 09:17 Сейчас в теме
А может помотреть в сторону 8.1 и сделать на регистрах сведений.
Тихо - тихо. Сильно не ругаться!
33. AVARY 175 18.10.08 11:45 Сейчас в теме
А может правильней сказать так: "Смерть клюшкам! Смерть клюшкам!" :)))))))))))
34. frolov.dns 9 20.10.08 09:51 Сейчас в теме
Мне кажется на 7.7 нужно делать на основе справочника, который с какой нибудь периодичностью потом чистить. Сделать поля: ФизическоеЛицо, ДатаВремяВхода, ДатаВремяВыхода. При входе добавляется новый элемент с заполненым значением ДатаВремяВхода, но не заполненным значение ДатаВремяВыхода. При выходе делается запрос к справочнику с фильтром по физическому лицу и пустому значению ДатаВремяВыхода, При этом перезаписывается этот элемент и "закрывается" запись. Потом простейщим запросом можно получить отработанное время и т.п. Можно написать обработку которая закрывает период, т.е. удаляет записи о входах и выходах и формирует график отработанного времени и т.п....
35. Altair777 644 20.10.08 11:45 Сейчас в теме
2 Сhe Burashka
Я уточнил - Если запись есть, то он уходит. Если нет, то приходит.

Если записи нет, делаем новую о входе
если 1 запись, делаем вторую о выходе
если 2 записи, удаляем вторую
36. CheBurator 3121 20.10.08 18:46 Сейчас в теме
2 frolov.dns
и иже с ними
запрос - бяка! проще и быстрее открыть выборку и получить последний элемент.
задача - не в этом...
37. O-Planet 6432 20.10.08 20:02 Сейчас в теме
Долго читал. Так до конца и не понял, в чем же все-таки проблема? Отличить выходы "покурить" от ухода с работы и разбить это по сменам, так? Если так, то я бы решал вопрос через переосмысление событий прихода и ухода с работы. Сейчас они, просто события на временной шкале. Сделай их событиями на шкале смен, и вот оно - счастье. Т.е., вводим понятие открытой смены (справочник Смены).

Поясню.

В контексте открытой смены у каждого сотрудника может быть только одно начало смены и только один конец смены (два реквизита в сотруднике). С приходом на работу у сотра начинается смена: фиксируется первый момент. Если кто-то вышел помочиться с порадного крыльца, то фиксируем, что он ушел (второй момент). Если сотр вернулся через 5 минут (1, 2 и т.д. часов, но еще в этой смене), то уход анулируется: он с работы не уходил, просто выходил помочиться. Если не вернулся в текущей смене, то все ок, ведь факт ухода остался записанным.

Но что делать, если он пришел в одну смену, а ушел в другую?

Все просто. Делаем Закрытие смены (документ / процедуру в глобальнике / обработку), которое выполняется либо автоматом, либо оператором. Закрытие смотрит, кто еще на работе, и записывает им всем по открытой смене конец смены: 20.00, а потом открывает новую смену и ставит начало новой смены: 20.00. Делает новую смену текущей.

Два реквизита времени в сотре - это данные по открытой смене. При закрытии смены их переносим в регистр по сменам. При регистрации прихода/ухода работать будет мгновенно, как это и требуется.

Таким образом, при формировании графика присутствия вообще ничего считать не нужно: тупо читаешь для конкретной смены подчиненный справочник (регистр) с данными прихода и ухода по сотрам.

_______________

Структура данных этого решения:

1. Два реквизита временни в справочнике Сотров: Начало, Конец

2. Справочник "Смены"
Реквизиты
Дата, Начало, Конец

3. Константа ТекущаяСмена, тип Справочник.Смены

Переключается закрытием смены.

4. Регистр (подчиненный справочник) "Присутствие"
Реквизиты
Сотрудник, Смена, Начало, Конец

Заполняется в моент закрытия смены

5. Обработка (процедура, документ) ЗакрытиеСмены

- Просматривает сотров, если они на работе, то проставляет им дату конца текущей смены
- Заполняет регистр "Присутствие" по данным сотров для текущей смены
- Создает новый элемент в справочнике "Смены", записывает ссылку на него в константу "ТекущаяСмена"
- Просматривает сотров, если они на работе, до проставляет им дату начала текущей смены (новой)

Воть...


_______________
Кстати, можно решить и более интересную проблему, сделать вот это неактуальным: "б) но если я не обедал, а выбежал на ужин в 19:30 и вернулся в 20:30, то будет в листе присутствия зафиксировано: ДС=9:00-19:30, НС=20:30-21:00"

Просто для этого нужно определить некоторое время Х, после которого считается, что сотр слинял, и закрытие-переключение смены делать по прошествии него. Если за это время сотр вернулся, то считаем, что он также не уходил, а выходил.
38. hogik 443 20.10.08 21:46 Сейчас в теме
Олег.
При таком решении надо добавить в пятый пункт еще одну обработку типа "Пересчет задним числом графика работы сотрудников из-за ошибочного указания интервала времени рабочих смен".
Если при проектировании схемы базы данных можно не хранить производные (расчетные) данные, то лучше этого не делать. В данной задаче "укладка" времен присутствия сотрудника на работе в график смен легко делается в момент формирования отчетов.
39. O-Planet 6432 20.10.08 22:02 Сейчас в теме
За такие ошибки надо иметь операторш конкретно. По идеи, график рабочих смен дожен определяться не ими, а кем-то вышестоящим, в начале квартала (года) и заноситься заранее. Я сказал про формирование новой смены чисто абстрактно. Справочник смен уже долеж быть заполнен!
40. O-Planet 6432 20.10.08 22:10 Сейчас в теме
> В данной задаче "укладка" времен присутствия сотрудника на работе в график смен легко делается в момент формирования отчетов
Может быть, это - более лучшее решение, хотя я все-таки хранил бы. Будем мыслить глобально: хотим автоматизировать работу проходной промышленного комплекса с сотней-другой тысяч сотров. Укладка в момент вывода не будет слишком тормозной? Я предлагаю простое чтение регистра, а Ваш вариант - пересчеты.
41. hogik 443 20.10.08 22:26 Сейчас в теме
"Иметь операторш конкретно" не отменяет и не заменяет вопроса исправления ошибки. И "вышестоящий" в этом вопросе не помощник. ;-)))) Просто есть такое "правило": то что можно посчитать - хранить не надо. И если этого правила придерживаться, то систему проще эксплуатировать. Да и программировать - проще. Но это дело вкуса. Посмотрим, чего скажет автор темы.
Мой вариант не пересчеты. Укладка не будет слишком тормозной т.к. количество исходных записей не больше, чем в Вашей схеме. Я тут проверил расчет своей базы - отчет по всем (100-150 человек) сотрудникам с января 2006 года с выдачей подробной информации. Меньше минуты (в локальном режиме).
42. CheBurator 3121 21.10.08 01:53 Сейчас в теме
Олег правильно написал, но выморочно..
Какие НА ПРОХОДНОЙ на! смены и документы? На проходной - люди ходят туда-сюда - и ВСЕ! все что может быть посчитано потом - должно быть посчитано потом - Ходжик совершенно верно заметил.
...у меня на временной оси есть события входов/выходов = это уже зарегено + в качестве "констант" есть "график смен" как вырожденный вариант : 1 смена с 00 до 24:00, как второй крайний вариант - цепочка из N смен, стыкующихся друг с другом и покрывающих "рабочие" сутки, причем "рабочие сутки" могут не совпадать с календарными сутками. все...
смотрим на рисунок: http://infostart.ru/profile/174/projects/2614/image.php?img=2079 - вот по такому "табелю" надо в отчете сделать "раскладку" по сменам...
У МНУ УЖЕ ЕСТЬ ПРОГРАММУЛИНА - но она мне не нравится!!!
Ходжик вообщем-то ближе к тому что я хочу излагает...
43. O-Planet 6432 21.10.08 02:18 Сейчас в теме
Итить! Ну дык повесь закрытие смены в глобальник на таймер, и о нем на проходной даже знать не будут, но твоя мудрая программа будет все закрывать магически-таинственным для всех образом сама! Вместо регистра используй подчиненный справочник, вместо документов - процедуру. Твой отчет станет формироваться элементарнейшим запросом:

Код
ТЗ="
|Сотрудник=Справочники.Присутствие.Сотрудник;
|ДатаСмены=Справочники.Присутствие.ДатаСмены;
|НачалоСмены=Справочники.Присутствие.НачалоСмены;
|ОкончаниеСмены=Справочники.Присутствие.ОкончаниеСмены;
|Группировка Сотрудник;
|Группировка ДатаСмены;
|";
Показать полностью

44. hogik 443 21.10.08 02:29 Сейчас в теме
Сергей.
Излагать то я излагаю, но честно сказать - не понимаю в чем загвоздка при решении данной задачи.
Собираем очередную пару событий - вход, выход. Просматриваем массив смен - сравниваем диапазоны. Разбиваем или вписываем диапазон времен событий в диапазон графика смен. И одна функция вычисления разницы между временем событий с учетом даты. Мне как то неудобно приводить исходный текст - два цикла и несколько сравнений. Чего то Вы недоговариваете...

Пришла мне глупая мысль в голову. Может быть загвоздка в самом укладывании времен прихода/ухода в график смен? Если так, то самый наглядный алгоритм это создание временного графика смен в массиве с учетом дат приход/ухода для каждой очередной полученной пары событий вход, выход. Т.е. если смены ДС (8:00-20:00) и НС (20:00-8:00), а даты прихода - 16.03.08, ухода - 18.03.08, то массив будет иметь примерно такой вид:
15.03.08 20:00 16.03.08 08:00 НС
16.03.08 08:00 16.03.08 20:00 ДС
16.03.08 20:00 17.03.08 08:00 НС
17.03.08 08:00 17.03.08 20:00 ДС
17.03.08 20:00 18.03.08 08:00 НС
18.03.08 08:00 18.03.08 20:00 ДС
18.03.08 20:00 19.03.08 08:00 НС
Имея функцию вычисление разницы двух переменных в формате ГГГГММДДЧЧСС, алгоритм, думаю, будет не сложным. Формат хранения (регистрации) входов/выхода описан выше по теме.
Или я, опять, чего-то не понял?


45. PeRom 51 21.10.08 10:51 Сейчас в теме
Или проблемма в определении конкретного момента начала/конца смены? т.е. если смена до 8:00 - то когда она кончится сегодня или завтра? относится и должна регистрироваться сегодняшним числом, а реально закончится завтра, и как точно определить, что она завтра закончится - простое сравнение начало больше конца. :)
У меня такой затык был с годами, при расчёте отопительного периода.
А насчёт предложения Планета, лучше всего исходные данные сохранять сразу, а расчётные сразу после расчёта, уже столкнулся с таким гемором(расчёт на лету), чуть где-то данные изменились и уже концов не найдёшь...
46. sillver 21.10.08 14:13 Сейчас в теме
хм... не пинайте тока, а если сделать документы "Вход" и "Выход"
с проведением какого то состояния сотрудника. Провел доккумент "Вход" в результате пишем куда нить состояние "на работе" )))
47. CheBurator 3121 22.10.08 02:03 Сейчас в теме
2 Ходжик:
> но честно сказать - не понимаю в чем загвоздка при решении
> данной задачи.
> Собираем очередную пару событий - вход, выход.
вот-вот.. вы попробуйте соберите... причем красиво... ;-)
сабрать надо не просто "пару", а пару событий, выкину при этом промежуточные незначимые события... + например:
снимаем отчет за 21 число - за этот "рабочий" день - событий не зарегистрировано... - начинаем определять: сотрудник безвылазно сидел на работе...? (такое тоже возможно) и тогда его "работа" бкдет выглядеть так: ДС=вход в 8-00, выход в 20-00, НС=вход в 20-00, выход в 8-00... Или же имеет место ситуация когда сотрудник вышел с работы 17 числа и больше не появлялся... и т.д.
я тоже сначала думал, что в 2 цикла и пару строк кода уложусь... ;-)
48. CheBurator 3121 22.10.08 02:06 Сейчас в теме
Вообще, конечно надо бы внутриинфостартовские "олимпиады" проводить по таким "мелким" задачкам - все какой-то оживляж будет... ;-) а то все мегапроектами заняты...
49. O-Planet 6432 22.10.08 03:13 Сейчас в теме
Не, не прокатит. Тут народ кичится написанием ВК, формализовать предметную область для таковых будет тяжко...
50. CheBurator 3121 22.10.08 04:01 Сейчас в теме
ВК - это ВК, пусть оно ВКой и остнется...
51. O-Planet 6432 22.10.08 04:52 Сейчас в теме
Блин, ща украду твою идею :)
52. O-Planet 6432 22.10.08 05:32 Сейчас в теме
53. hogik 443 22.10.08 05:41 Сейчас в теме
У меня нет мегапроектов. И, похоже, уже не будет :-((( А т.к. я зануда, то привожу текст "в 2 цикла и пару строк". Разноску писать будем?

Код
Перем НачалоОтчета,КонецОтчета;
//--------------------------------------
Процедура Ошибка(КодОшибки)
   Сообщить(Строка(КодОшибки),"!");
КонецПроцедуры
//--------------------------------------
Процедура Разноска(НачалоРаботы,КонецРаботы)
   Если НачалоРаботы>КонецОтчета Тогда Возврат; КонецЕсли;
   Если КонецРаботы<НачалоОтчета Тогда Возврат; КонецЕсли;
   //Сообщить(НачалоРаботы+" "+КонецРаботы); 
   // Укладка в график смен   
КонецПроцедуры
//--------------------------------------
Процедура Сформировать()
   Люд=СоздатьОбъект("Справочник.Сотрудники");
   Рег=СоздатьОбъект("Справочник.СотрудникиУчет");
   Люд.ПорядокНаименований();
   Люд.ВыбратьЭлементы(0);
   Пока Люд.ПолучитьЭлемент()=1 Цикл
      Если Люд.ПометкаУдаления()=1 Тогда Продолжить; КонецЕсли;
      Если Люд.ЭтоГруппа()=1 Тогда Продолжить; КонецЕсли;
      Сообщить(Люд.Наименование);
      Нач=""; Кон="";
      Рег.ПорядокНаименований();
      Рег.ИспользоватьВладельца(Люд.ТекущийЭлемент());
      Рег.ВыбратьЭлементы();
      Пока Рег.ПолучитьЭлемент()=1 Цикл
         Если Рег.ПометкаУдаления()=1 Тогда Продолжить; КонецЕсли;
         Если ПустоеЗначение(Рег.Наименование)=1 Тогда Ошибка(1); Продолжить; КонецЕсли;
         Если Рег.Направление=0 Тогда // Вход
            Если ПустоеЗначение(Нач)=0 Тогда Ошибка(2); КонецЕсли;                        
            Если ПустоеЗначение(Кон)=0 Тогда Ошибка(3); КонецЕсли;                        
            Если Рег.Наименование>КонецОтчета Тогда Прервать; КонецЕсли;
            Нач=Рег.Наименование; Кон="";
            Продолжить;
         Иначе                        // Выход 
            Если ПустоеЗначение(Нач)=1 Тогда Ошибка(4); Продолжить; КонецЕсли;
            Если ПустоеЗначение(Кон)=0 Тогда Ошибка(5); КонецЕсли;
            Кон=Рег.Наименование;
         КонецЕсли;
         Разноска(Нач,Кон);
         Нач=""; Кон="";
      КонецЦикла;
      Если (ПустоеЗначение(Нач)=0) И (ПустоеЗначение(Кон)=1) Тогда // Еше на работе 
         Кон=Формат(ТекущаяДата(),"ДГГГГММДД")+Сред(СтрЗаменить(ТекущееВремя(),":",""),1,4);         
         Разноска(Нач,Кон);      
      КонецЕсли;
   КонецЦикла;   
КонецПроцедуры
//--------------------------------------
НачалоОтчета="200803160000";
КонецОтчета= "200803182400";
Показать полностью


54. O-Planet 6432 22.10.08 05:56 Сейчас в теме
НизачоД за "И, похоже, уже не будет :-((("
55. AVARY 175 22.10.08 07:40 Сейчас в теме
Вообще в начале темы вопрос был по алгоритму, а по большей части обсуждается реализация. Требуется уточнение темы.
56. hogik 443 22.10.08 17:45 Сейчас в теме
(AVARY)
С моей стороны представлена "реализация" потому, что алгоритм представлен выше по теме. И мы не сошлись в мнениях - "два цикла и два оператора" требуется для реализации моего алгоритма или больше ;-)))
57. CheBurator 3121 22.10.08 19:06 Сейчас в теме
2 Ходжик: седня вечером буду осмысливать... стопудово у тебя где-то что-то не так!
;-)
58. CheBurator 3121 22.10.08 19:08 Сейчас в теме
а куда заначена //укладка в график смен?
59. CheBurator 3121 22.10.08 19:09 Сейчас в теме
а куда заначена укладка в график смен?
60. hogik 443 22.10.08 19:33 Сейчас в теме
Сергей.
Ошибки возможно есть, т.к. мне пришлось вытаскивать эту логику из моей работающей системы - убирал все лишнее для наглядности представления самой сути. Но вся суть - здесь "в двух циклах и двух операторах".
Укладки у меня в промышленной системе нет - надо писать с нуля. Но если взять идею из сообщения от 21.10.2008 02:29:30 (Блин! Почему нет номеров сообщений в форуме и дат в "прямом эфире"?), то это тоже два цикла. Но уже три оператора. Правда, более простых. Напишу, если Вы признаете первую часть верной. ;-)))
61. hogik 443 23.10.08 02:06 Сейчас в теме
;-)
Последняя, полная версия.
Только для Сергея (Сhe Burashka).
Прикрепленные файлы:
CheBur.zip
62. CheBurator 3121 23.10.08 02:22 Сейчас в теме
Спсб!
будет изучено и код будет точно мой переточен...
+есть еще одна реализация - но тма на скуле и поганять - негде..
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот