Дюжина вопросов для программиста 1С




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

99 Comments

  1. EMelihoff

    Как Вы считаете, программист за какое время должен сделать Ваши вопросы?

    Reply
  2. kolya_tlt

    (1) конечно за 30 мин. не успел, можем предложить зп -20% от того что ты попросил 🙂

    Reply
  3. TODD22
    Это не только вопрос — ответ, это ещё шпаргалка для работы с редко встречающимися алгоритмами.

    Если спрашивать у программиста «редко встречающиеся алгоритмы» то искать вы себе программиста будете очень долго…

    Вы себе делаете шпаргалку, а с приходящего программиста спрашиваете умение?

    Reply
  4. ifal

    Посмотрел простенькие задачи и по ним есть вопросы/замечания

    5. Я вот против таких вещей — задача тривиальная, разовая, а запрос смотреть больно. К тому же еще и весь регистр очищается. Если задача показать решение запросом, то тут конечно надолго.

    8. Подскажите, пожалуйста, следующий код для чего нужен?

    СсылкаОб = Источник.ПолучитьСсылкуНового();

    Если СсылкаОб.Пустая() Тогда

    СсылкаОб = Документы.РеализацияТоваровУслуг.ПолучитьСсылку();

    Источник.УстановитьСсылкуНового(СсылкаОб);

    КонецЕсли;

    10. Замените Левое соединение на Внутреннее соединение и уберите объединение, оставь все в одном запросе, будет эффективней.

    Reply
  5. karpik666

    По поводу 10, почему именно так, почему использовали NULL, вместо внутреннего соединения и объединения?

    Reply
  6. karpik666

    8 тоже интересно, а если пользователь откажется от заполнения и закроет документ на записывая, у нас что останется в базе битая ссылка таким образом?

    Reply
  7. alex-l19041

    по вопросу №5:

    я бы не стал городить временную таблицу ВТ, а использовал бы данные регистра Регламентированный производственный календарь (или его аналог), который есть практически во всех типовых конфигурациях.

    И даже если конфигурация написана «с нуля» и там такого регистра еще нет, то я бы его добавил.

    Reply
  8. ediks

    Мда, запрос по номенклатуре с тремя словами в наименовании не выполнился. Ушел в себя и не вернулся. Всего-то 170 тыс. позиций в справочнике «Номенклатура».

    Reply
  9. kolya_tlt

    (4) по задачам можно определить контору и средний уровень знаний уже имеющихся разработчиков.

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

    в запросе они лидирующие нули отсекают …

    Reply
  10. vano-ekt
    спр = Справочники.Номенклатура.НайтиПоКоду(«00000000081»);

    Мы вам перезвоним (с)…

    Reply
  11. hillsnake

    Первые 2 вопроса нормально, но дальше

    какие то редкие находки …

    реализация некоторых, спорна.

    (7)

    5 вопрос баян рваный со времен 8.1. тогда еще не было РПК везде.

    (8) даже себе представить не могу, для чего это надо …

    вообще был список подобный у Гилева. зачем велосипеды изобретать.

    хотя они его не сильно афишируют.

    Reply
  12. Anchoret

    3. Очень уж трудоемко получается в каждую форму списка заходить и 100500 раз. Может мой подход в корне не верный, но для БП 3.0, например, я бы добавлял код в процедуру «ОбработкаНовостейКлиент.КонтекстныеНовости_ПриОткрытии(ЭтаФорма)» во многих формах списках она уже присутствует.

    6. Создается ревизит объекта или реквизит формы и уже он используется, «НайтиПоКоду» в данном случае нет смысла использовать.

    7. По условию надо сказано «на заданную дату» в решении используется текущая дата

    Адрес контрагента выводится при помощи создания пользовательского поля. Код в данном случае лишний.

    А так-то до боли знакомые задачи=)

    Reply
  13. Anchoret

    (1) Когда мне предложили решить эти задачи, отводилось 2 часа

    Reply
  14. tailer2

    критика куда более любопытна, чем вопросы

    на вопросах я сломался на первом же: «ПриЗаписи формы», — наступила ржака-обоссака

    меняй профессию, ваня

    Reply
  15. Поручик

    Ни фига себе вопросики для теста. Я бы оттуда на всех четырёх выскочил.

    Отдайте шляпу и пальто, Манал я ваши именины.

    Reply
  16. fr13

    (13) Тоже доводилось решать эти задачи, мне дали вечер

    Reply
  17. v3rter

    Демотивирует. Глядя на такие способы элементарных, по сути, преобразований данных и действии с интерфейсом совершенно не тянет в программисты-1Сники. Кроме шуток )

    Да, порог вхождения в профессию 1Сника низкий, зато через пару ступеней начинается серьёзный программный альпинизм )

    Reply
  18. dgolovanov

    (7) Если конфигурация пишется с нуля, то она сращивается с БСП, в котором есть в т.ч. подсистема календарей. А если человек не знает про БСП, но пугает меня порождающими запросами и проверками на NULL полей, которые возвращает временная таблица — я бы с ним не стал связываться.

    Reply
  19. TODD22

    (19)

    Ибо имею достаточный уровень, чтобы выбирать

    Ещё бы уровень культуры речи подтянуть что бы в общественном месте матом не ругаться и вы были бы самым завидным соискателем…..

    Reply
  20. MSConfig

    Примерно 1 месяц назад я откликался на вакансию удаленного программиста 1С из одного московского франча. Зарплата и условия достойные.

    Вот мне они отправили тестовое задание со всеми вопросами, которые в топике. По времени никто не торопил — дали три дня на все про все.

    Потом был второй этап — беседа по скайпу.

    ЗЫ: На работу позвали, но сам не пошел — выбрал другое предложение)

    Reply
  21. TreeDogNight

    Плохо, что больше половины вопросов привязаны к конкретным конфигурациям…

    Reply
  22. awk

    Написать обработку, которая для типовой конфигурации Бухгалтерия предприятия 2.0 устанавливает курс валюты Рубль, равный 1, на каждый день 2012 года.

    После решения запросом читать перестал. Выигрыш в производительности крайне сомнителен. Выпендреж и не более. И решившего данным способом человека на работу не взял бы, ибо человек не умеет соотносить сложность и время решения (поддержки), с пользой от решения.

    Reply
  23. vdmkvrshn

    В 9-м зачем рассчитывать на строку длиной 2#k8SjZc9Dxk16 ??? У справочника длина наименования максимум 150 символов. Вот у одного из комментаторов справочник на 170000 и «повесился» на таком запросе… еще бы — для каждого элемента сделать 2#k8SjZc9Dxk16 сравнений. Сам запрос, конечно интересен в плане идеи, но в плане оптимальности — полный мусор и бред, тем более в качестве ожидаемого от соискателя ответа.

    Reply
  24. tarassov

    Не понимаю, почему для пункта 9 такой сложный код?

    Предлагаю свой вариант, проверьте:

    выбрать
    СпрНоменклатура.ссылка
    из справочник.номенклатура как СпрНоменклатура
    где СпрНоменклатура.Наименование Подобно «_% _% _%»
    и не СпрНоменклатура.Наименование Подобно «_% _% _% _%»
    
    Reply
  25. Sashares

    (25) Потому что все эти вопросы, а так же предложенные решения — бред.

    Вместо простого кода в 5-10 строк, алгоритм засовывают в запросы более 100 строк… Ересь.

    Reply
  26. asved.ru

    Какая-то теоретическая наркомания.

    (8)

    Мда, запрос по номенклатуре с тремя словами в наименовании не выполнился. Ушел в себя и не вернулся. Всего-то 170 тыс. позиций в справочнике «Номенклатура».

    Это нормально. Такие задачи вообще требуют под себя отдельное хранение данных.

    По существу:

    1) Гы-гы, поржал

    2) А вот как это сделать, если отладчик недоступен? Справитесь?

    3) Не понял — это быстрее чего? Быстрее вставки экземпляра кода в каждую форму, что ли? А если контекст формы не нужен?

    4) А будет ли считаться неверным контекстный серверный вызов в этом случае? Вопрос на отсев идиотов?

    5) А не лучше ли будет собрать набор прикладным кодом 1С? Операция-то разовая, и смысла в порождающем запросе никакого, а трудозатраты и вероятность ошибки в разы выше.

    6) Вопрос на отсев идиотов?

    7) А зачем в запросе соединение вместо обращения через точку? Платформа построит его сама.

    8) За захардкоженные наименования нужно бить ногами.

    9) Разовая задача гораздо быстрее решается на уровне кода 1С, регулярная — созданием и заполнением дополнительного объекта данных.

    10) По индексации ВТ все ровно с точностью до наоборот. А интересной такая задача станет, когда добавим условие, что это запрос динамического списка.

    11) Вот кто такую структуру данных придумал, тот пусть и пишет. Как раз занят будет, пока Госнаркоконтроль подъедет.

    12) А если пользователь захочет по этому адресу сделать группировку?

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

    А какая-нибудь девочка-HR примет за чистую монету же.

    Reply
  27. dgolovanov

    (23) Мне кажется, сначала некий автор открыл для себя «гениальные» запросы и потом придумывал задачи, которые можно решить. Поэтому такие совершенно идиотические примеры.

    Reply
  28. starik-2005

    (0)

    Одними из методов проверки профессиональных качеств программиста являются его опрос и тестирование.

    Забыли слово «малоэффективных». Опрос, как показывает практика, может выявить большую теоретическую базу, известную программисту, но если он на реальных задачах боится трудностей, то вряд ли сможет эффективно работать. Также и тестирование совершенно ничего не говорит о качестве. Есть те, кто в принципе не помнит, какие галки в каком окошке находятся, но знает, где искать; а есть те, кто выучили для теста все эти галки и прочее, но не могут их найти, т.к. не знают, как вообще эту форму с этими галками открыть. При этом первые получат меньше баллов в тесте, чем вторые.

    Единственным реальным критерием наличия у программиста профессиональных качеств является написанный им код, решающий задачу. Если задача решена и код будет отрабатывать в разумные сроки, написан грамотно и не использует запросы в цикле, разыменовывание реквизитов составных типов, обращение к реквизитам объекта в цикле (что суть запрос в цикле) и прочие характерные косяки, то программист, написавший данный код, годен к труду и обороне. Если же в коде явные косяки, то модно задать вопросы на тему «а почему так?» Если же программист так и не сумел написать код, то зачем такой программист нужен?

    Я бы предложил универсальную задачу для оценки качества программиста — переоценка валютных остатков. Написать подобное можно за час максимум, если не вдаваться в подробности. Пользы от этого кода никакого для компании, так что работодателя нельзя будет заподозрить в попытке нахаляву что-то там поиметь. При этом в коде нужно и остатки получить, и курсы. и потом движения сделать на счета доходов/расходов. Красота!

    Reply
  29. rayastar

    Мое решение) Предложили перед НГ франч задачи. После решения все же кое какие решения оказались кривыми

    Reply
  30. rayastar
    Reply
  31. madonov

    5.

    Чем производственный календарь не угодил? Почему оттуда не взять все дни 2012 года?

    ВЫБРАТЬ
    РегламентированныйПроизводственныйКалендарь.ДатаКалендаря Как период
    ПОМЕСТИТЬ ВТ
    ИЗ
    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
    Где
    РегламентированныйПроизводственныйКалендарь.ДатаКалендаря >= ДатаВремя(2012,1,1)
    и РегламентированныйПроизводственныйКалендарь.ДатаКалендаря <= ДатаВремя(2012,12,31)

    Нет, мне вполне понятно как работает ваш велосипед… но зачем?

    Добавьте тогда

    13. Напишите функцию, которая бы являлась полным аналогом встроенной функции «ЧислоПрописью()».

    займете кандидата на какое-то время.

    Reply
  32. comol

    Ах, корм для троллей :)). Люблю такие статьи.

    Если не распространяться на тему что вопросы НЕ РАСКРЫВАЮТ ПОНИМАНИЯ программистом механизмов платформы. И не испытавают владения типовыми приёмами разработки, ещё и содержат много косяков:

    3) Вы даже не представляете сколько для этого есть способов. Ни один из которых не начинается со слова «прописать»

    5) Сказали уже — мягко говоря «сомнительное» решение

    6) На одну транзакцию записи больше + возможен код при пометке удаления. Самый красивый код — не всегда самый верный.

    7) Есть штатная возможность заполнить бух операцию сторно в бухгалетрии 2.0 + нужно использовать транзакции

    8) «Предупреждение» в коде, на современной конфигурации?… ай ай

    9) Я конечно тут уже могу ошибаться… а чем не понравилось «подобно». 3 разделителя, и не 4 разделителя. Всегда вроде так писал…

    10) ну тут вообще :))) Сколько документов обычно передаётся в ВТ? один? Или миллион? В зависимости от этого «оптимизация» будет разной

    11)

    12) Вычисляемая колонка и функция общего модуля по строчке, не? :)))

    Reply
  33. dvs691

    (32) Именно такую задачу мне задавали на собесодовании

    Reply
  34. nucha

    (4) п.5 Если не запросом, то перебор всех дней в году? Есть решение? — добавлю еще одно решение от Вас.

    п.8 Проверка — присвоена ли ему ссылка нового ранее? Если нет, то присваиваем.

    п.10 красивей — да, быстрей — не уверен…

    Reply
  35. nucha

    (7) для разовой задачи, может не нужно регистр добавлять?

    Reply
  36. Sashares

    (35) п.5 Не запросом — элементарный алгоритм из 2х циклов.

    Если вы не можете сформулировать такой алгоритм, может вам не стоит писать такие статьи?

    Год = «2012»;
    Для ТекМес = 1 По 12 Цикл
    Для ТекДень = 1 По 31 Цикл
    ТекДата = Дата(Год,ТекМес,ТекДень);
    
    //Тут запись в регистр
    
    Если КонецДня(ТекДата) = КонецМесяца(ТекДата) Тогда
    Прервать;
    КонецЕсли;
    КонецЦикла;
    КонецЦикла;

    Показать

    Reply
  37. awk

    (35) Константин,

    Дней = (ДатаНачала — ДатаОкончания)/365;
    
    Набор = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
    
    СтруктураЗаполнения = Новый Структура(«Курс, Кратность, Валюта», 1, 1, Валюта);
    
    Для ит = 0 По Дней Цикл
    
    Запись = Набор.Добавить();
    Запись.Период = Дата Начала + 86400 * ит;
    ЗаполнитьЗначенияСвойств(Запись, СтруктураЗаполнения);
    КонецЦикла;
    
    Набор.Записать();

    Показать

    Если вставите замер времени, то основная проблема будет в последней строке (если вы не заполняете столетие, а один-пять лет)

    Reply
  38. awk

    (37) Что будет 30.02.2012?

    Reply
  39. Sashares

    (39) Не будет 30.02.2012. Если текущая дата конец месяца — цикл прерывается.

    Reply
  40. awk

    (40) Не заметил — извини.

    Reply
  41. m-rv

    тест спорный. на примере шестого вопроса:

    а) предложенное решение имеет избыточность записи корневого элемента (если элементов 100500 — не критично, а если 3 — критично)

    б) предложенное решение имеет побочные явления (отработают обмены, подписки на корневом элементе, при чем дважды)

    в) в предложенном решении не гарантируется консистентность результата (отсутствие транзакции может привести к пометке удаления всех элементов, включая корневой)

    Reply
  42. nucha

    (38) нужна поправка на високосный год. В нем 366 дней.

    Reply
  43. nucha

    (25) в выборку попали наименования состоящие из 5 слов. «Ложка серебряная с дырявой ручкой» -вероятно попали бы. Повторить:

    и не СпрНоменклатура.Наименование Подобно «_% _% _% _% _% и т.д. Даже если повторить 20 раз, будет все равно лучше.

    Reply
  44. Sashares

    (44)Потому что условие в строке Подобно без нижнего подчеркивания.

    Reply
  45. pbazeliuk

    4. Ответ не полностью правильный, для больших баз может привести к падению кластера сервера.

    5. Зачем удалять данные не связанные с 2012 годом и другой валютой?

    6. Реализация ужасная

    8. Реализация требует оптимизации. Не нужно забывать про агрегатные данные

    9-12. Присутствуют проблемы с постановкой задач, а так же реализацией.

    Reply
  46. ifal

    (35)

    5. Выше уже ответили, самый обычный код циклом.

    8. С этим понятно, опять же ваше уже написали, что в случае отмены записи нового документа повиснет запись с неизвестной ссылкой, внутренне лично для меня не приемлемое решение.

    10. Конечно быстрее, хотя бы потому, что у вас через объединение два запроса, а сделать можно в одним запросом через внутреннее соединение. Как вы знаете, соединение и объединение таблиц — это дорогие операции, уменьшение их приведет к хорошему росту производительности.

    Reply
  47. Dzenn

    «Нужен мне работник:

    Повар, конюх и плотник.

    А где найти мне такого

    Служителя не слишком дорогого?»

    Искать по таким тестам долго будете )

    Reply
  48. MaxS

    А не проще ли просто спросить умеешь ли то ли то? Как бы ты делал это? В устном диалоге. Если есть сомнение в честности ответов, попросить подробности реализации. Это будет быстрее и комфортнее для собеседников.

    Когда-то давно ходил на собеседования. Если бы мне предложили решить все вопросы, я бы просто ушел.

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

    Reply
  49. МимохожийОднако

    Статья замечательно провоцирует на комментарии. Для одного техзадания будет столько решений, сколько программистов. У каждого есть свой набор шпаргалок, но не каждый решается вывалить это на рассмотрение. Автор смел.

    Reply
  50. TODD22

    (51)

    Автор смел.

    В чём смелость?

    Reply
  51. andybs

    Меня при выборе программиста интересует эффективность и отсутствие быдлокода.

    Если задача «разовая», да хоть запрос в цикле, если он на это потратил 5 минут и не «повесил» базу.

    Умения в таких задачах использовать «типовые» обработки типа «Групповая обработка справочников и документов» для меня интереснее, чем

    «об = спр.ПолучитьОбъект();

    об.УстановитьПометкуУдаления(Истина,Истина);

    об.УстановитьПометкуУдаления(Ложь,Ложь);»

    который, в общем то «фича» и к системному программированию значения не имеет.

    Но так или иначе — автору спасибо. Что-то взял в «шпаркалку», хоть и понимаю, что вряд ли пригодиться 🙂

    Reply
  52. madonov

    (34) и сколько разрядов по итогу поддерживала функция?

    А дробные числа?

    А склонения единиц измерений?

    А сколько ЯЗЫКОВ?

    =))

    Я не спорю, если задаться целью и иметь достаточное количество времени, это всё можно реализовать на встроенном языке.

    НО ЗАЧЕМ?

    Скажем так, получи я подобную задачу на собеседовании… то я бы сделал соответствующие выводы о адекватности и вменяемости потенциального работодателя.

    Reply
  53. starik-2005

    (53)

    да хоть запрос в цикле, если он на это потратил 5 минут и не «повесил» базу.

    Ага, а потом он в большой базе такое наваяет и документ вместо 10 секунд будет проводиться полчаса? Такого кода в любой типовой хоть опой ешь, но это не значит, что так и нужно делать.

    Reply
  54. МимохожийОднако

    (52) Не всякий решается показывать. А некоторые закрывают комментарии к своим публикациям.Другого не имел в виду, если что

    Reply
  55. Denic_01

    Извините конечно, но первый же вопрос — ответ, не вызывает ничего кроме недоумения

    Можно ли подписаться на событие ПриЗаписи формы элемента справочника?

    Нет. (подписка на событие работает только с объектом.).

    А точнее — где в вопросе акцент, именно на ОБЪЕКТ ? С каких то пор использовать событие ПриЗаписи у формы стало нельзя использовать ? нюанс про объект домыслен и высосан из пальца уже в ответе …

    Такими уловками обычно пользуются преподы которые хотят завалить:

    — Если ответишь ДА, он скажет неправильно потому что объект

    — Ответишь НЕТ, скажет неправильно потому что есть у формы такое событие и оно активно используется во многих случаях, надо заметить

    но мы мы же не на экзамене в коррумпированном универе 😉

    Reply
  56. nucha

    (38) вставил в статью Ваш реально толковый комментарий.

    Reply
  57. h00k

    (53)

    Если задача «разовая», да хоть запрос в цикле, если он на это потратил 5 минут и не «повесил» базу.

    Тут есть маленький нюанс — именно запрос в цикле, обычно, сигнализирует об отсутствии опыта, не знании разработчиком стандартов и типовых приёмов разработки. Если есть необходимый опыт и понимание архитектуры платформы 1С, то даже разовые задачи разработчик пишет нормально, так-как организация правильной структуры функции становится почти рефлексом, а задач которые решаются именно запросом в цикле ничтожно мало.

    Естественно замечание выше не касается случаев когда в цикле создаются неявные запросы из-за разыменовывания поля и случаев когда разыменовывание поля в запросе приводит к появлению дополнительных неявных соединений.

    Reply
  58. Brawler

    (37)

    КонецДня(ТекДата) = КонецМесяца(ТекДата)

    А вы сами не задумывались сколько может быть внутри зашито математик в КонецДня, КонецМесяца?

    Даже если оставлять в такой реализации, то конец месяца (на время 00:00:00) можно было бы вычислить хотя бы до цикла по дням и проверять потом внутри ТекДата = ПоследнееЧислоМесяца

    Reply
  59. Brawler

    (54) За решение таких задач, как по мне, они еще и заплатить должны, так как это немалый труд!

    Reply
  60. Brawler

    тут много чего написали, добавлю и я

    8.



    свойство = ПланыВидовХарактеристик.СвойстваОбъектов.НайтиПоНаименованию(«Номер ИнтернетЗаказа»);

    как-то не надежно не кажется?

    бог с ним с наименованием свойства, но вот то что в плане видов характеристик содержится как правило набор свойств для разных видов объектов и у части из этих видов объектов могут быть схожие по наименованию свойства, то такой поиск выдаст совершенно случайно первое попавшееся свойство

    в своей практике УПП/КА запилил и использую такую функцию

    // Возвращает свойство объекта по имени и назначению свойства
    //
    // Параметры:
    //   ИмяСвойства — Строка — Имя свойства.
    //   НазначенияСвойства — ПланыВидовХарактеристикСсылка.НазначенияСвойствКатегорийОбъектов — Назначения свойств.
    //   ВызватьИсключениеЕслиСвойствоНеНайдено — Булево — Признак того, нужно ли вызывать исключение, если свойство не найдено, по умолчанию Ложь. (опционально)
    //
    // Возвращаемое значение
    //   ПланыВидовХарактеристикСсылка.СвойстваОбъектов — Найденное свойство или Неопределено, если свойство не найдено.
    //
    Функция ПолучитьСвойствоОбъектаПоИмениИНазначениюСвойства(ИмяСвойства, НазначенияСвойства, ВызватьИсключениеЕслиСвойствоНеНайдено = Ложь) Экспорт
    
    Запрос = Новый Запрос;
    Запрос.Текст =
    «ВЫБРАТЬ
    | СвойстваОбъектов.Ссылка
    |ИЗ
    | ПланВидовХарактеристик.СвойстваОбъектов КАК СвойстваОбъектов
    |ГДЕ
    | СвойстваОбъектов.Наименование = &Наименование
    | И СвойстваОбъектов.НазначениеСвойства = &НазначениеСвойства»;
    
    Запрос.УстановитьПараметр(«НазначениеСвойства», НазначенияСвойства);
    Запрос.УстановитьПараметр(«Наименование», ИмяСвойства);
    
    ВыборкаДетальныеЗаписи = Запрос.Выполнить().Выбрать();
    
    Если ВыборкаДетальныеЗаписи.Следующий() Тогда
    Возврат ВыборкаДетальныеЗаписи.Ссылка;
    Иначе
    Если ВызватьИсключениеЕслиСвойствоНеНайдено Тогда
    ВызватьИсключение СтрШаблон(«Не удалось найти дополнительное свойство ‘%1’ у назначения свойств ‘%2’.»,
    ИмяСвойства, НазначенияСвойства);
    Иначе
    Возврат Неопределено;
    КонецЕсли;
    КонецЕсли;
    
    КонецФункции
    

    Показать

    Reply
  61. awk

    (43) Там не на 365 делить надо, а на 86400. ибо разность в секундах.

    Reply
  62. Sashares

    (60) Это пример алгоритма, на замену реализацией запросом.

    Конечно алгоритм можно и немного улучшить, например, предложенным вами способом.

    Но смысла как такового в этом нет.

    Reply
  63. ZOMI

    Не дожидаясь отказа, снимаю свою кандидатуру сам.

    Reply
  64. 1cmax

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

    Reply
  65. DrAku1a

    (6) Вы правы! Такие манипуляции нужно делать при записи (с проверкой на нового и ОбменДанными.Загрузка).

    Reply
  66. Brawler

    (66)

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

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

    На всем этом и делать свои выводы.

    Тут практически все сталкиваются с совершенно разными задачами и некоторые вещи вообще могли не применяться в работе.

    И тут на тебе, на пару вопросов не ответил, при том что в других силен на все 100%, а тебе желтую карточку и прощай…

    Reply
  67. Anchoret

    (25)

    Таким образом и решал.

    Reply
  68. kosmo0

    (66) Поддерживаю.

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

    А автор пытается создать простой шаблон. Да шаблон резко уменьшает время проверки, но отбрасывает в сторону множество факторов.

    Reply
  69. Pawlick
    Как сделать чтобы номер выводился в отчет без лидирующих нулей?

    1. Создать на вкладке СКД «ВычисляемыеПоля» поле «НомерНаПечать»

    2. В выражение записать: «ОбщегоНазначения.ПолучитьНомерНаПечать(Ссылка)» , где «Ссылка» — имя поля в наборе, которым выбирается документ, номер которого нужно очистить от лидирующих нулей, а «ОбщегоНазначения.ПолучитьНомерНаПечать(Ссылка)» — имя экспортной процедуры в одноименном модуле. Справедливо для УТ10, КА1.1, УПП1.3 Заодно и от префиксов очистите. Для остальных конфигураций, уверен, тоже такие процедуры есть.

    и не компилировать никому мозг: если хотели на знание языка запросов проверить — достаточно было вопроса №5, а на знание механизмов СКД мой ответ больше подходит.

    PS Нет, ну вот интересно все таки, а что ж вы предложить то сможете тому, кто на все на это ответит?

    А вообще на память приходит мне одна история:

    был у меня один знакомый: после двух пива начинал рассказывать про оперу венскую, как это все прекрасно и так далее, руками размахивал, глаза закатывал. Пока не нарвался на одного культурного скромняжку, который был фанатом этого дела, проехал пол мира на скромную зарплату ради этого. Сидел и помалкивал, пока этот знакомый не завелся в очередной раз. В итоге оказалось, что знакомый мой оперу два раза по радио слышал, и в википедии про две постановки прочел, и то видимо не доконца, потому как не смог «Турандот» от чего то там отличить… Просто таким образом «девах клеил».

    Мне вот Ваш «вопросник» его напомнил…

    Reply
  70. vano-ekt

    (37)

    из 2х циклов

    Много циклов

    Год = ‘20120101’;
    ТекДень = Год;
    //создаем нз
    Пока Год(Год)=Год(ТекДень) Цикл
    
    // добавляем в нз
    
    ТекДень = ТекДень+86400;
    
    КонецЦикла;
    // записсываем нз

    Показать

    Reply
  71. tkv44

    Автор серьезно думает, что талант программиста проверяется решением подобных задач?

    Reply
  72. Sashares

    (72)

    Пока Год(Год)=Год(ТекДень) Цикл

    Ну 365/366 раз вычислить функцию Год() от переменной, которая не меняется, тоже оригинальное решение =)

    Reply
  73. vano-ekt

    (74) зато памяти сэкономил под целую переменную 😀

    Reply
  74. vicmos

    Зачем это нужно?

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

    Reply
  75. AlX0id

    По 11 вопросу — может уже предлагали, но я бы сначала взял двустволку и пристрелил того, кто эту структуру соорудил, съездил бы в лес, закопал его, а затем перестроил бы регистр к *ям.

    Reply
  76. klinval
    Reply
  77. li5enok

    Посмотрел на задачи, посмотрел на ответы. И вот что я понял: дебильные ответы делают вопросы такими же!

    На 5 задачу никто не дал ответа верного.

    Задача:

    Написать обработку, которая для типовой конфигурации Бухгалтерия предприятия 2.0 устанавливает курс валюты Рубль, равный 1, на каждый день 2012 года.

    Разбор задачи:

    Указание конфигурации даёт нам точный набор необходимых метаданных. В задаче четко указана валюта( значение измерения регистра), четко указан курс (о кратности можно догадаться), указан период для записи.

    Какого ляда все лепят НаборЗаписей без отборов? Требования указаны в задаче! Почему все перетирают данные которые не относятся к вашей задаче?

    1С прекрасно работает с датами (упрощаются школьные изыски с переборами). Для перебора дат нет необходимости собирать их в одну таблицу.

    Процедура УстановитьКурсЗаПериод(Знач Валюта, Знач ДатаНачала, Знач ДатаОкончания, Знач Курс, Знач Кратность)
    
    МЗ = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();
    МЗ.Валюта  = Валюта;
    МЗ.Курс   = Курс;
    МЗ.Кратность = Кратность;
    
    ДеньВСекундах= 86400;
    
    ТекДата = ДатаНачала;
    Пока ТекДата <= ДатаОкончания Цикл
    МЗ.Период = ТекДата;
    МЗ.Записать();
    
    ТекДата = ТекДата + ДеньВСекундах;
    КонецЦикла;
    
    КонецПроцедуры

    Показать

    Reply
  78. v3rter

    (79)

    А вариант набить нужными датами таблицу значений в цикле, перетащить во временную таблицу запроса и соединить?

    Reply
  79. li5enok

    (80) Это породит лишние сущности: таблица значений, Запрос, менеджер временных таблиц, выборка из запроса. При этом пиковое значение использования ресурсов будет выше. Для простой задачки это не повлияет ни на что, но нужно прививать правильный подход к решению поставленных задач сразу. Были случаи когда алгоритмически задачу можно считать решенной, но сервер падает через пару минут после запуска или кластер убивает сеанс по достижению лимита памяти.

    Reply
  80. tarassov
    Reply
  81. vadim1011985

    (79) А ничего что у Вас запись идет в цикле каждый раз ? 365 дней — 365 раз записал. Точнее даже не так — не вижу смысла записывать по одной записи — когда надо заполнить за период , по мне так лучше использовать набор записей

    Reply
  82. li5enok

    (83) Именно — одна запись за раз. Хотите ускорить — оберните в транзакцию, только имейте ввиду, что параллельность работы снизится.

    У набора записей должен устанавливаться отбор. Если его не установить, то затрется вся информация в регистре и запишется только та, что была в наборе. Это грубая ошибка!

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

    Reply
  83. ditp

    (84) Н

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

    или включите мозг фантазию:

    руб  = Константы.ВалютаРегламентированногоУчета.Получить();
    Запрос = Новый Запрос(«ВЫБРАТЬ
    | ЕСТЬNULL(К.ДатаКалендаря, КВ.Период) КАК Период,
    | ИСТИНА КАК Активность,
    | &Валюта,
    | ЕСТЬNULL(КВ.Курс, 1) КАК Курс,
    | ЕСТЬNULL(КВ.Кратность, 1) КАК Кратность
    |ИЗ
    | РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК К
    |  ПОЛНОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КВ
    |  ПО К.ДатаКалендаря = КВ.Период
    |   ГДЕ КВ.Валюта = &Валюта»);
    Запрос.Параметры.Вставить(«Валюта», руб);
    
    рег = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
    рег.Отбор.Валюта.Установить(руб);
    рег.Загрузить(Запрос.Выполнить().Выгрузить());
    рег.Записать(Истина);
    

    Показать

    P.S. При выполнении этого кода ни одна лишняя запись не пострадала.

    Reply
  84. li5enok

    (85) Уже лучше, но это решение другой задачи. Требовалось установить курс только в определенном периоде

    Reply
  85. ditp

    (86) мне откровенно лень было дописывать к

    ГДЕ КВ.Валюта = &Валюта

    еще

    И К.ДатаКалендаря Между &Нач и &Кон

    Извините.

    Reply
  86. li5enok

    (87) Допустим, что производственный календарь заполнен и не будем к этому придираться(хотя следует, т.к. алгоритм становится зависим от другой сущности)

    Ваш запрос снова отберет узкий набор и запись перетрет все курсы рубля кроме указанного диапазона.

    Чтобы не нагнетать напряженности в диалоге публикую свой запрос

    ВЫБРАТЬ
    К.Дата КАК Период,
    &Валюта,
    &Курс КАК Курс,
    &Кратность КАК Кратность
    ИЗ
    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК К
    ГДЕ
    РегламентированныйПроизводственныйКалендарь.Дата МЕЖДУ &Нач И &Кон
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    КВ.Период,
    &Валюта,
    КВ.Курс,
    КВ.Кратность
    ИЗ
    РегистрСведений.КурсыВалют КАК КВ
    ГДЕ
    КВ.Валюта = &Валюта
    И (КВ.Период < &Нач
    ИЛИ КВ.Период > &Кон)
    

    Показать

    Но всё равно я не сторонник перезаписывать весь регистр если нужно только несколько строк, хотя с регистром КурсыВалют это способ не вылетает за пределы оперативной памяти.

    Reply
  87. ditp

    (88)

    Ваш запрос снова отберет узкий набор и запись перетрет все курсы рубля кроме указанного диапазона.

    на что спорим?

    Reply
  88. li5enok

    (89) не знаю как тут заливать $m, придется спорить на рубли. Ставлю 1000 руб на то, что ваш алгоритм дополнит за указанный период курс рубля курсом 1, оставив при этом установленные записи (хотя для рубля в данном случае вряд ли) и удалит все курсы рубля вне указанного диапазона.

    Reply
  89. ditp

    (90) Договорились.

    Reply
  90. ditp

    (90) в общем, писал не проверяя, практика показала, что мою версию нужно слегка отредактировать:

    ВЫБРАТЬ
    ЕСТЬNULL(К.ДатаКалендаря, КВ.Период) КАК Период,
    ИСТИНА КАК Активность,
    &Валюта,
    ЕСТЬNULL(КВ.Курс, 1) КАК Курс,
    ЕСТЬNULL(КВ.Кратность, 1) КАК Кратность
    ИЗ
    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК К
    ПОЛНОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КВ
    ПО К.ДатаКалендаря = КВ.Период
    
    где (КВ.Валюта  is null или КВ.Валюта = &Валюта)
    И ( К.ДатаКалендаря  is null или К.ДатаКалендаря между &нач и &кон)
    УПОРЯДОЧИТЬ ПО
    Период

    Показать

    Если подходить формально — спор за вами.

    В личку сообщите, как выигрыш передать.

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

    Reply
  91. li5enok

    (92) Коллега, Вы первый человек в моей жизни, который не стал сливаться и увиливать в споре, уважаю! Отписался в личку.

    Чтобы не было обидно за спор, оставляю за вами право обратится ко мне за консультацией если прижмет ситуация.

    С помощь запроса конечно же можно получить правильный набор (свой вариант я уже давал).

    Reply
  92. ditp

    (93)

    оставляю за вами право обратится ко мне за консультацией если прижмет ситуация

    А вот щаз обидно было.

    Reply
  93. li5enok

    (94)Извините, если обидел, но запрос так и остался неверный.

    Reply
  94. ditp

    Воистину, поспешишь — людей насмешишь.

    Reply
  95. li5enok

    (96) Коллега, выигрыш получил, благодарю!

    Если вы найдете ошибку в моем первоначальном алгоритме, я верну вам половину суммы. Как вам такой Challenge?

    Reply
  96. ditp

    (97) в этом-то

    Процедура УстановитьКурсЗаПериод(Знач Валюта, Знач ДатаНачала, Знач ДатаОкончания, Знач Курс, Знач Кратность)
    
    МЗ = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();
    МЗ.Валюта     = Валюта;
    МЗ.Курс         = Курс;
    МЗ.Кратность = Кратность;
    
    ДеньВСекундах= 86400;
    
    ТекДата = ДатаНачала;
    Пока ТекДата <= ДатаОкончания Цикл
    МЗ.Период = ТекДата;
    МЗ.Записать();
    
    ТекДата = ТекДата + ДеньВСекундах;
    КонецЦикла;
    
    КонецПроцедуры

    Показать

    ?

    Да тут и искать нечего, МЗ.Записать() без МЗ.Прочитать() бессмысленно и беспощадно.

    P.S. Возвращать ничего не надо, тыща,в конце концов, не бутерброд, что б ее туда-сюда передавать…

    Reply
  97. li5enok

    (98) Можно использовать Прочитать(), но тратится время на чтение. Лучше так:

    Процедура УстановитьКурсЗаПериод(Знач Валюта, Знач ДатаНачала, Знач ДатаОкончания, Знач Курс, Знач Кратность)
    
    ДеньВСекундах= 86400;
    
    ТекДата = ДатаНачала;
    Пока ТекДата <= ДатаОкончания Цикл
    
    МЗ = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();
    МЗ.Период     = ТекДата;
    МЗ.Валюта     = Валюта;
    МЗ.Курс          = Курс;
    МЗ.Кратность = Кратность;
    
    МЗ.Записать();
    
    ТекДата = ТекДата + ДеньВСекундах;
    КонецЦикла;
    
    КонецПроцедуры

    Показать

    Reply
  98. AhanSere

    (53)

    Если задача «разовая», да хоть запрос в цикле, если он на это потратил 5 минут и не «повесил» базу.

    Я бы так не сказал…

    Сегодня программист пишет какую-нибудь обработку для одного-нескольких документов, чтобы использовать ее только один раз и думает, что можно написать как угодно, все-равно задача разовая…

    Потом, может через год или больше он уже не помнит деталей. Вдруг сталкивается с такой же задачей, но обработать нужно уже много документов, или вообще внедрить механизм в конфигурацию базы для постоянного использования. Он вспоминает, что «где-то у меня как раз была такая обработка… А вот же она, здорово!», берет ее и вставляет.

    А клиент потом считает, что «Если обработка работает несколько часов — это нормально, там же много документов!»

    Reply
  99. Shmell

    Для 10 вопроса ответ не верен. В комментариях так же не совсем корректный вариант.

    В исходной статье решение подразумевает список из 1 поля со всем перечнем документов. Но нужно найти связку связанных документов — то есть пара полей в любом случае.

    В комментариях вариант уже получше — но есть ньюанс — вы целиком таблицу регистра помещаете во временную таблицу. У вас tempdb просто напросто нагнется. Если по бизнес логике этот запрос часто используется, то нужно рассмотреть вариант с добавлением индекса по измерению Документ2.

    ВЫБРАТЬ
    Регистр.Документ1
    Регистр.Документ2
    ИЗ
    РегистрСведений.СвязанныеДокументы КАК Регистр
    ГДЕ
    Регистр.Документ1 В (&СписокДоков)
    
    Объединить все
    
    ВЫБРАТЬ
    Регистр.Документ1
    Регистр.Документ2
    ИЗ
    РегистрСведений.СвязанныеДокументы КАК Регистр
    ГДЕ
    Регистр.Документ2 В (&СписокДоков)

    Показать

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *