1. TOKAPEB 5 07.11.18 16:35 Сейчас в теме

Задачка по программированию

Добрый день! Вот попалась задачка, и честно говоря, в начале показалась ничего особенного, но попытавшись решить, начал спотыкаться, появились сомнения.
Решил сюда выкинуть, может у кого -то появятся мыслишки по решению. Условие пишу как есть:

Необходимо реализовать универсальную функцию вида: СкорректироватьЗаписи(ИмяРегистра, ИсходныеДвижения, ЦелевыеДвижения).
Где ИмяРегистра - имя регистра накопления (строка);
ИсходныеДвижения - набор исходных движений (тип - Таблица значений)
ЦелевыеДвижения - набор целевых движений (тип - Таблица значений)

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

Например, существует движения регистра "Остатки номенклатуры", Исходные движения (Приходная №2):

Номенк Колво Сум
Kohinor 60 390
Паркер 40 3800

И есть движения регистра "Остатки номенклатуры", Целевые движения (Приходная №1):

Номенк Колво Сум
Kohinor 10 70
Паркер 10 1000

На выходе функция должна вернуть таблицу значений следующего вида:

Номенк Колво Сум
Kohinor -50 -320
Паркер -30 -2800

Функция должна быть универсальной, т.е. на вход могут подаваться записи другого регистра накопления , например, "Продажи",
имеющего другую структуру измерений и ресурсов.
Решение должно содержать примитивный пользовательский интерфейс для проверки, позволяющий задать параметры функции и продемонстрировать результат.
Найденные решения
22. echo77 943 07.11.18 18:25 Сейчас в теме
Я так в свое время решал:
	// Создадим итоговую таблицу, в которой найдем разницу
	ИтоговаяТаблица = СоставПлана.Выгрузить();
	
	// Вычитаем строки исходного плана(добавляем строки с минусом)
	Для Каждого СтрокаТЗ Из ИсходнаяТаблица Цикл
		НоваяСтрока = ИтоговаяТаблица.Добавить();
		ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЗ);
		НоваяСтрока.Количество	= -СтрокаТЗ.Количество;// Тут нужно будет перечислить все ресурсы
		
	КонецЦикла;
	
	// Сформируем перечень полей по которым надо свернуть таблицу
	КолонкиГруппировок = "Период, Подразделение, Номенклатура, ХарактеристикаНоменклатуры, ЕдиницаИзмерения, Коэффициент, Цена, СтавкаНДС, Заказ, Контрагент, Договор, Проект";// Тут все Измерения(Все колонки, кроме ресурсов)
	КолонкиСуммирования = "Количество, СуммаНДС, Сумма";// Тут перечисляем все ресурсы
		
	// Свернем итоговую таблицу, чтобы получить разницу
	ИтоговаяТаблица.Свернуть(КолонкиГруппировок, КолонкиСуммирования);
	
	// Уберем строки, в которых количество = 0 и Сумма = 0, ибо изменение цены, без изменения количества
	// Только 0 количество
	Отбор = Новый Структура("Количество", 0);
	МассивСтрокНаУдаление = ИтоговаяТаблица.НайтиСтроки(Отбор);
	Для Каждого СтрокаТЗ Из МассивСтрокНаУдаление Цикл
		ИтоговаяТаблица.Удалить(СтрокаТЗ);
	КонецЦикла;
	
	// Сортировать не обязательно
	ИтоговаяТаблица.Сортировать("Период, Номенклатура, ХарактеристикаНоменклатуры, Количество");
Показать
TOKAPEB; herfis; +2 Ответить
28. spacecraft 07.11.18 18:42 Сейчас в теме
(26) по запросу: в цикле конкатенацией строк. Это вообще не проблема.
по второму варианту: из метаданных полученные измерения и ресурсы собрать в отдельные массивы. Потом собрать в строку не составит проблем. В чем сложность?

Я привел примеры решений. Я не уговариваю использовать только запрос.
Остальные ответы
Избранное Подписка Сортировка: Древо
6. Boneman 183 07.11.18 16:50 Сейчас в теме
(1) постановка задачи, какая-то дибильная.
Но по факту, как я понял,
интерактивно пользователь вбивает целевые движения, т.е. то, что должно после операции остаться.
А значит, делаем срез остатков, и обычной формулой рассчитывааем Целевое-Исходное= ТоЧтоНужно.

А универсальный запрос сделать просто,

(3)
	 "ВЫБРАТЬ *
	 |ИЗ
	 |	РегистрНакопления.ИмяРегистра.Остатки КАК РегистрОстатки"

Имя регистра, подменяй только методом СтрЗаменить

Потом выполнить выгрузить, и обходишь колонки и строки таблицы значений, как нужно
9. TOKAPEB 5 07.11.18 17:02 Сейчас в теме
(6)
А при чем тут остатки.... На вход может подаваться любой регистр накопления. Оборотов например.
Здесь смысл привести движения одного документа к движениям другого. Сторнировать так сказать под цифры второго документа.
10. Boneman 183 07.11.18 17:06 Сейчас в теме
(9) я и написал, что формулировка задачи не совсем понятная. Как я понял, так и написал.

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

А так задача, сама по себе, проста и незатейлива...
А если параметры движения, это уже движения исходного документа, то и запрос никакой не нужен, просто анализируйте их и все.
11. spacecraft 07.11.18 17:10 Сейчас в теме
(10) в том то и дело. Про регистратор ничего в задании не сказано. Считаем его нет. Да и не нужен он в данном случае. Корректировка регистра. Нет данных про период выборки.
16. TOKAPEB 5 07.11.18 17:22 Сейчас в теме
(11)
Скорее всего, да, задача на сравнивание таблиц без запроса. Могли бы Вы привести пример сравнивания на данной задачке без запроса?
18. spacecraft 07.11.18 17:30 Сейчас в теме
(16) несколько вариантов.
1. Можно через загрузку обеих ТЗ в запрос. Соединение, группировка по измерениям. Вычитание.
2. Можно без запроса. Инвертировать ресурсы первой таблицы (создать локальную ТЗ). Объединить обе ТЗ в одну результирующую. Результирующую свернуть по измерениям и суммированием ресурсов.
TOKAPEB; Boneman; +2 Ответить
26. TOKAPEB 5 07.11.18 18:36 Сейчас в теме
(18)
Возьмём запрос. Структура каждый раз разная, как собрать запрос, как описать поля? В цикле по измерениям и ресурсам? А потом как дать запросу понять какие поля группировать, а какие складывать? Возьмём второй вариант: чтобы свернуть, нужно опять в цикле описывать строку ,состоящая из полей, по которым будем сворачивать, и строку, с теми полями которые будут сворачиваться.
27. herfis 264 07.11.18 18:38 Сейчас в теме
(26) Дело даже не в этом. Исходные данные уже в ОЗУ, доп-данных не требуется. Привлекать СУБД в качестве калькулятора - это... это... у меня нет слов.
29. spacecraft 07.11.18 18:44 Сейчас в теме
(27) и в чем проблема? Выборки из таблиц sql не будет, соответственно блокировок тоже.
30. herfis 264 07.11.18 18:47 Сейчас в теме
(29) А передача ТЗ в СУБД? А получение результата от СУБД? Особенно если таблицы большие? А накладные расходы на вызовы СУБД? Ради чего? Когда уже все вот оно и все можно легко сделать даже не трогая сетку, не говоря уже о цельном сервере баз данных?
Для меня это такой же нонсенс, как если бы всерьез предлагали для сложения двух чисел дергать сиквел, чтобы это сделал он. Да, работать будет. Можно еще веб-сервис для этого написать. Тоже рабочее решение. И очень гибкое. Чем не вариант?
31. spacecraft 07.11.18 18:51 Сейчас в теме
(30) в любом случае будут накладные расходы. ТЗ сама по себе высоконагруженная сущность. Без запроса нужна еще одна ТЗ. Результирующая ТЗ будет удвоена. Если ТЗ большая, то индексировать не помешает.
Что будет менее нагрузочным и быстрым нужно смотреть уже по факту использования. Как правило для sql выделяется больше ресурсов.
32. herfis 264 07.11.18 19:00 Сейчас в теме
(31) Передача в СУБД для экономии ОЗУ на обработке результирующей таблицы? Интересная идея :) Только не взлетит. Для сериализации и передачи в СУБД большой таблицы тоже потребуются дополнительные ресурсы.
В общем, раз консенсуса нет - не вижу смысла продолжать эту тему. Я чувствую себя нелепо, пытаясь доказывать аксиоматичные для меня вещи.
28. spacecraft 07.11.18 18:42 Сейчас в теме
(26) по запросу: в цикле конкатенацией строк. Это вообще не проблема.
по второму варианту: из метаданных полученные измерения и ресурсы собрать в отдельные массивы. Потом собрать в строку не составит проблем. В чем сложность?

Я привел примеры решений. Я не уговариваю использовать только запрос.
33. TOKAPEB 5 07.11.18 19:19 Сейчас в теме
(28)ясно, приму как решение. Поясню, задача предлагалась как тестовый пример на собеседовании. Время на решение не более 30 минут с реализацией интерфейса. Просто показалась, что заниматься на собеседовании за 30 минут собиранием строки не лучшей идей. Вот и выложил сюда. Спасибо
34. spacecraft 07.11.18 19:28 Сейчас в теме
(33) то что это тестовое задание было сразу понятно.
А вот то что его нужно было решить прямо на собеседовании в коде за 30 мин. Лучше не рассматривать как вариант будущей работы там.
На собеседовании можно описать алгоритм и/или потом решить высланное тестовое задание. Это нормально.
36. herfis 264 08.11.18 10:51 Сейчас в теме
(34)
А вот то что его нужно было решить прямо на собеседовании в коде за 30 мин. Лучше не рассматривать как вариант будущей работы там.

Ну почему же? Мне наоборот - очень понравилось. 30 мин на такую задачку - это с запасом на мандраж, тупняк и чаю попить.
А возможность посмотреть на живой код с гарантией авторства и тут же задать вопросы по нему - бесценно.
Задачка с одной стороны - простейшая алгоритмистика, с другой - нужно хотя бы знать про метаданные :)
Если отдать эту примитивную задачку "на потом", то так и не узнаешь, что чувак на месте не смог бы решить ее за полчаса самостоятельно (что сразу бы сказало о крайне ограниченной практике программирования).
Задачи на "домашнее задание" - это уже другой класс задач. Где обычно проверяется не только элементарное умение кодить, но и какое-то элементарное понимание учета.
12. Boneman 183 07.11.18 17:13 Сейчас в теме
(9) да и вообще, если вчитаться...
то параметры функции уже таблицы значений и исходные и целевые..
а значит, нам вообще никакой запрос точно не нужен.
Просто сравниваем 2 таблицы значений,
и создаем набор записей, от нужного регистра по имени, в него и загружаем эту таблицу значений
13. spacecraft 07.11.18 17:16 Сейчас в теме
(12) не нужно создавать движения. Нужно вернуть результирующую таблицу значений.
14. Boneman 183 07.11.18 17:19 Сейчас в теме
(13) нуууу
Функция должна возвращать набор записей соответствующего регистра (в виде таблицы значений)

я х.з. тогда вообще что она вернуть должна ))) набор записей, или таблицу значений ))
17. Boneman 183 07.11.18 17:22 Сейчас в теме
(13) ну а если так, тогда согласен с твоим (8)
регистр нужен только для определения измерений.
8. spacecraft 07.11.18 16:55 Сейчас в теме
(1) Получаем метаданные по "ИмяРегистра". Находим измерения и ресурсы. Далее для уникальных записей по измерениям делаем вычитание ресурсов из второй таблицы первой таблицы.
2. antz 07.11.18 16:41 Сейчас в теме
В чем загвоздка-то? Элементарным запросом решается, кмк. Ну, текст генерить придется.
3. TOKAPEB 5 07.11.18 16:43 Сейчас в теме
Загвоздка как раз и в том, что запрос будет каждый раз разный, т.к. могут подаваться разные регистры. Если решается запросом, то как сделать универсальный запрос?
5. antz 07.11.18 16:48 Сейчас в теме
(3) Если таблицы повторяют структуру регистра, то циклом по колонкам определяем типы, если тип числовой - это ресурс, схему запроса, думаю, привлекать не будем, из имен колонок формируем секцию ВЫБРАТЬ, передаем таблицу целевых движений в параметры запроса, на выходе получаем таблицу необходимых движений.
4. echo77 943 07.11.18 16:44 Сейчас в теме
В качестве параметров нужно передавать, какие колонки таблицы являются ресурсами, или же в функции придется анализировать, обращаясь к метаданным, что в этих колонках ресурсы - их вычитаем, в этих - измерения - по ним группируем.

Задача нахождения разницы решается "вычитание" из одной таблицы в другую. Языком запросов - это объединение с последующей группировкой по ключевым полям - измерениям.
7. SlavaKron 07.11.18 16:50 Сейчас в теме
Зачем тут запрос? Каких данных вам не хватает?
15. acanta 45 07.11.18 17:19 Сейчас в теме
Проблема определить что таблице ресурс а что измерение (оно тоже может быть числовым или датой)
19. SlavaKron 07.11.18 17:35 Сейчас в теме
(15) В регистрах накопления ресурсом может быть только число. В принципе, нам нужны только имена ресурсов для решения задачи.
20. Boneman 183 07.11.18 17:38 Сейчас в теме
(19) а измерение нет, поэтому легко можно спутать измерение с ресурсом (если определяться по типу значений), и начать вычитать то что не надо.
21. caponid 07.11.18 18:16 Сейчас в теме
Что то это мне напоминает - контроль остатков при отмене проведения.
22. echo77 943 07.11.18 18:25 Сейчас в теме
Я так в свое время решал:
	// Создадим итоговую таблицу, в которой найдем разницу
	ИтоговаяТаблица = СоставПлана.Выгрузить();
	
	// Вычитаем строки исходного плана(добавляем строки с минусом)
	Для Каждого СтрокаТЗ Из ИсходнаяТаблица Цикл
		НоваяСтрока = ИтоговаяТаблица.Добавить();
		ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЗ);
		НоваяСтрока.Количество	= -СтрокаТЗ.Количество;// Тут нужно будет перечислить все ресурсы
		
	КонецЦикла;
	
	// Сформируем перечень полей по которым надо свернуть таблицу
	КолонкиГруппировок = "Период, Подразделение, Номенклатура, ХарактеристикаНоменклатуры, ЕдиницаИзмерения, Коэффициент, Цена, СтавкаНДС, Заказ, Контрагент, Договор, Проект";// Тут все Измерения(Все колонки, кроме ресурсов)
	КолонкиСуммирования = "Количество, СуммаНДС, Сумма";// Тут перечисляем все ресурсы
		
	// Свернем итоговую таблицу, чтобы получить разницу
	ИтоговаяТаблица.Свернуть(КолонкиГруппировок, КолонкиСуммирования);
	
	// Уберем строки, в которых количество = 0 и Сумма = 0, ибо изменение цены, без изменения количества
	// Только 0 количество
	Отбор = Новый Структура("Количество", 0);
	МассивСтрокНаУдаление = ИтоговаяТаблица.НайтиСтроки(Отбор);
	Для Каждого СтрокаТЗ Из МассивСтрокНаУдаление Цикл
		ИтоговаяТаблица.Удалить(СтрокаТЗ);
	КонецЦикла;
	
	// Сортировать не обязательно
	ИтоговаяТаблица.Сортировать("Период, Номенклатура, ХарактеристикаНоменклатуры, Количество");
Показать
TOKAPEB; herfis; +2 Ответить
23. echo77 943 07.11.18 18:26 Сейчас в теме
+(22) Никаких запросов - все выполняется с помощью объектов 1С. В данном примере все поля, конечно жестко прописаны, но коли у вас есть имя регистра - поля ресурсов по метаданным определить не сложно.
24. herfis 264 07.11.18 18:29 Сейчас в теме
Я бы делал так (никаких запросов - меня вообще раздражает, когда шурупы забивают молотком, просто потому что уже научились забивать им гвозди):
- определил по метаданным и имени регистра поля ресурсов и измерений
- слил таблицы в одну (исходные движения - с минусом по ресурсам)
- свернул таблицу по измерениям (суммируя по полям ресурсов)
- удалил строки с нулевыми значениями всех ресурсов
- вернул получившуюся таблицу
ЗЫ. Собственно, в (22) именно так и сделано
25. spacecraft 07.11.18 18:36 Сейчас в теме
(24)
никаких запросов - меня вообще раздражает, когда шурупы забивают молотком

Не в контексте темы: некоторые шурупы только молотком и нужно забивать. Дюбель-шуруп :)
35. МихаилМ 07.11.18 20:28 Сейчас в теме
сворачивать тз умеет еще построитель запроса,скд, и анализ данных.
38. acanta 45 09.11.18 10:49 Сейчас в теме
(35) Построитель запроса и СКД - это инструмент делегирования исполнения из среды 1с на уровень СУБД. Если нет обращения к реквизитам объектов базы, то в нем нет смысла, обычные циклы работают объяснимо быстрее.
39. МихаилМ 09.11.18 14:52 Сейчас в теме
(38)нет. Вы ошибаетесь. скд и построитель запроса умеют обрабатывать тз без субд. причем у каждого механизма есть свои преимущества: скд может объединять и сворачивать тз , а ПЗ в некоторых случаях быстрее сворачивает тз чем тз.
37. user970630 08.11.18 15:47 Сейчас в теме
А где нашли такую задачку? А то я хочу в скором времени начать готовиться к экзамену по платформе.
Скиньте ссылку пожалуйста, если не сложно.
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

Программист 1С
Санкт-Петербург
зарплата от 130 000 руб. до 150 000 руб.
Полный день

Программист 1С
Санкт-Петербург
зарплата от 100 000 руб.
Полный день

Руководитель группы сервисов FRM на 1С
Москва
зарплата от 150 000 руб.
Полный день

Руководитель группы сервисов ЭДО, ЭЦП и криптографии
Москва
зарплата от 150 000 руб.
Полный день

Руководитель группы интеграций (1С)
Москва
зарплата от 150 000 руб.
Полный день