Имя: Пароль:
1C
1C 7.7
v7: Учёт оплаты по дням
0 Cyr
 
15.03.21
12:03
Есть у нас самописная конфигурация с документами: Договор на аренду места(на несколько месяцев) и "График оплаты" (на месяц по дням).
В табличной части "графика оплаты" десятки мест. Чтобы получить задолженность по договору приходится в цикле перебирать всю табличную часть и каждый день документа "График оплаты". Для 200 договоров это занимает минуту. Можно как-то оптимизировать этот процесс? Может регистр оборотов помочь? Или календарь?
1 HawkEye
 
15.03.21
12:04
(0) а документ ничего не двигает чтоли?
2 Cyr
 
15.03.21
12:05
(1) Нет.
3 HawkEye
 
15.03.21
12:06
(2) а как по твоему, зачем в 1С сделаны регистры? ))
4 Strogg
 
15.03.21
12:09
Вообще, поможет остаточный регистр. график оплаты делает плюс, факт оплаты - минус. Там уже сам по датам разберешь как двигать факт оплаты. Ну и потом просто получаешь остатки по регистру :)
5 Cyr
 
15.03.21
12:09
(3) Конфигурация писалась давно. И программист видимо с регистрами не очень знаком был...
Так сильно ли поможет регистр в плане ускорения работы? Если на порядок, то будем заморачиваться. А если чуть-чуть, то и не стоит...
6 Cyr
 
15.03.21
12:10
(4) У нас факт оплаты по сути просто "галочка" в документе "График оплаты" за нужный день по нужному месту.
7 Strogg
 
15.03.21
12:14
(6) не. так не пойдет. В любом случае документ такого типа должен проводиться, а информация для аналитики должна находиться в остаточном регистре. причем, факт отражения задолженности и оплаты должны отражаться разными документами. А то Вася седня поставил галку, а Петя завтра ее снял. вот тебе и все :)
8 HawkEye
 
15.03.21
12:16
(5) это точно был программист? )))
в плане ускорения - на порядок, а то и на два, если правильно спроектируешь архтектуру....

(6) а должен быть "-" в регистре....
9 Cyr
 
15.03.21
12:16
(7) Ну пользователи и редактируют этот документ по много раз, когда им приносят чеки с оплатой.
Этот документ выглядит как календарь.
10 Strogg
 
15.03.21
12:22
(9) см (8) :)))
И еще глянь как отражение начисления и погашения задолженности происходит в типовых конфах. Если бы ты это сделал до того как создал ветку, тогда ветку бы ты не создал. КонецЕсли;
11 Cyr
 
15.03.21
12:40
(10) Это программа не для бухгалтеров, поэтому так и сделана была. Чтоб побыстрее работало, ткнул мышкой - галка нарисовалась. За 3 минуты сотню мест отметил.
12 Cyr
 
15.03.21
13:17
(7)А почему регистр остатков, а не обороты? Ведь при печати "счётов" нужно указывать и за какие дни не оплачено....
13 HawkEye
 
15.03.21
13:28
(11) программу "не для бухгалтеров" надо делать на порядок тщательнее )))
14 hhhh
 
15.03.21
13:33
(12) у регистра остатков тоже можно получать обороты, прикинь.
15 Cyr
 
15.03.21
14:34
(7) А что помешает Пете изменить документ Васи и перепровести его?
16 Arbuz
 
15.03.21
15:10
(15) Правильно настроенные права
17 Злопчинский
 
15.03.21
15:10
Ускорение примерно на порядок м.б. получено и на текущей конфигурации за счет использования прямых запросов (если вы погромист 1С). скорее всего в рамках и существующей архитектуры конфигурации можно ускорить, просто надо вниматочно посмотреть как отчет строится и оптимизировать его штатными средствами просто тупо переписав получше.
.
Если не справитесь сами - стукайтесь месяца через два (контакты в личке), к тому времени осовобожусь, посмотрим если надо будет
18 Arbuz
 
15.03.21
15:14
(17) Кстати тоже такая мысль появилась. Прямые запросы к таблицам журнала и документов, ускорят даже больше, чем на порядок, а возни может быть меньше, чем дорабатывать логику на регистры.
19 Gucci76
 
15.03.21
15:19
Для ускорения 7.7 еще полезно использовать 1СРР.dll
20 Cyr
 
15.03.21
15:21
(17) (18) Можно ли через запрос найти строку табличной части документа по значению первого столбца?
Можно ли через запрос перебрать все остальные столбцы этой табличной части документа по искомой строке? Столбцов там по количеству дней месяца.
21 Gucci76
 
15.03.21
15:21
В 7.7 долго отрабатывает ПолучитьСтрокуПоНомеру (или что то типа того - уже забыл)
22 Arbuz
 
15.03.21
15:22
(19) Конечно
23 Arbuz
 
15.03.21
15:22
(22) на (20)
24 Cyr
 
15.03.21
15:36
(23) Ну номер строку табличной части мы нашли:
    "//{{ЗАПРОС(Сформировать2)
    |С (Договор.СрокС) по (Договор.СрокПО);
    |ОбрабатыватьДокументы все;
    |Обрабатывать НеПомеченныеНаУдаление;
    |Без итогов;
    |ДокументОплата = Документ.ГрафикОплаты.ТекущийДокумент;
    |НомерСтроки = Документ.ГрафикОплаты.НомерСтроки;
    |Место = Документ.ГрафикОплаты.Место;
    |Группировка ДокументОплата;
    |Группировка НомерСтроки;
    |Условие(Место в Договор.Место);
    |"//}}ЗАПРОС
А вот как перебрать все столбцы табличной части документа "ГрафикОплаты"? У них Идентификатор "Д1"..."Д31"
25 Злопчинский
 
15.03.21
15:50
(24)
СтрокаДокумента - ПРЕДОПРЕДЕЛЕННАЯ ГРУППИРОВКА
поэтому  |НомерСтроки = Документ.ГрафикОплаты.НомерСтроки; - выкниут
написать Группировка СтрокаДокумента
26 Злопчинский
 
15.03.21
15:56
"А вот как перебрать все столбцы табличной части документа "ГрафикОплаты"? У них Идентификатор "Д1"..."Д31" - для чего?
.
|ДокументОплата = Документ.ГрафикОплаты.ТекущийДокумент;
|%ВЫБОРДНЕЙ%
|Место = Документ.ГрафикОплаты.Место;

ВыборДней = ""; Для ы=1 по 31 Цикл ВыборДней = ВыборДней+"д"+ы+";" КонецЦикла;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"%ВЫБОРДНЕЙ%",ВыборДней);
27 Злопчинский
 
15.03.21
15:58
и какой ч(м)удак реквизиты которые однотипные и потом стопудово придется перебирать иобрабатывать программно, в т.ч. вырезая из "дТУТХРЕНПОЛНЯ" номер дня именует криво?!
правильно архитекутрно если так сделано назвать д01,д02..д10....
тогда даже тупая сортировка по номеру дня "дХХ" будет работать правильно, а не так криво как при текущей нумерации.
.
"как дети, чесслово"
28 Djelf
 
15.03.21
16:12
(0) Забей, или нет... Это тебе решать! Это странная база, там все видимо "сделано на коленке" в стиле "сколько заплатили, то и получили".
Но могу предложить оптимизацию в стиле - "сделано на коленке"!
Мне отсюда не видно, но предполагаю - выборка документов с 99% вероятностью перебирает вообще ВСЕ документы.
Добавь в шапку документа Флаг - оплата закрыта (и его заполни!!!) и будет ну... возможно даже на порядок быстрее!
29 Lazy Stranger
 
15.03.21
16:49
Сделать регистр остатков с измерениями "договор" и "дата", может быть ещё "место". Проведение договора аренды вешает по отдельности долг на каждый день действия договора, а график оплаты двигает его в минус. Задолженность будет выниматься из остатков регистра за доли секунды.
30 Злопчинский
 
15.03.21
17:29
(29) затрахаются. ибо стопудово график оплаты вовремя не соблюдается арендаторами. и тогда ЕСЛИ ТАМ ХОТЬ КТОТО ВМЕНЯЕМЫй есть - то оплату регистрируют по факту в день когда была внесена с учетом за неоплаченные предыдущие дни - и тогда сумму оплаты 10 числа надо будет разносить на предыдущие неоплаченные дни. с квалификацией ТС затрахаютсяч возможно (хоть все и просто).

если же просто ставят галочку что "день оплачен" в соответсвующий день и пофиг когда было оплачено (скорее всего это сделано именно так в этом решении "на коленке") - то да, такой регистр простейший, проведение простйешее и данные будут вытягиваться очень быстро.
31 Lazy Stranger
 
15.03.21
17:31
(30) судя по описанию, мне кажется что у них именно галочка "день оплачен", хотя чтобы что-то советовать надо их базу смотреть
32 Злопчинский
 
15.03.21
17:31
(21) "ПолучитьСтрокуПоНомеру" долго отрабатывает - это вряд ли. особой разницы не заметил по сравнению с последовательным ПолучитьСтроку(). Может быть только если колонки нетипизированные есть
33 Злопчинский
 
15.03.21
17:33
(26) тьфу, блин, надеюсь принцип понял
ВыборДней = ""; Для ы=1 по 31 Цикл ВыборДней = ВыборДней+"д"+ы+"= Документ.ГрфикОплаты.д"+ы+";" КонецЦикла;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"%ВЫБОРДНЕЙ%",ВыборДней);
34 Злопчинский
 
15.03.21
17:34
(31) тоже так думаю что просто галочкой. вполне норм решение.
35 Cyr
 
15.03.21
18:36
(31) Там наоборот ведется учёт долгов. Если день не оплатили, ставится буква "Н".
Вот проверка договора:
Функция ПроверитьДоговор(Договор)
    ДолгиЗа="";
    Оплата=СоздатьОбъект("Документ.ГрафикОплаты");
    Оплата.ВыбратьДокументы(НачМесяца(Договор.СрокС),КонМесяца(Договор.СрокПо));
    Пока Оплата.ПолучитьДокумент()=1 Цикл //по документам Оплата
        Оплата_ПериодПо=КонМесяца(Оплата.Период);
        Если (Оплата.Сектор=Договор.Место.Родитель) И (Договор.СрокС<=Оплата_ПериодПо) И (Договор.СрокПо>=Оплата.Период) Тогда //получили документ Оплата по договору
            
            Оплата.ВыбратьСтроки();
            Пока Оплата.ПолучитьСтроку() = 1 Цикл // по местам
                Если Оплата.Место=Договор.Место Тогда //нашли строку по месту
                    //проверить дни
                    НачальноеЧисло=ДатаЧисло(?(Оплата.Период<Договор.СрокС, Договор.СрокС, Оплата.Период));
                    КонечноеЧисло =ДатаЧисло(?(Оплата_ПериодПо>Договор.СрокПо, Договор.СрокПо, Оплата_ПериодПо));
                    //Сообщить(Строка(НачальноеЧисло)+"-"+Строка(КонечноеЧисло));
                    Для День = НачальноеЧисло По КонечноеЧисло Цикл //по столбцам
                        Пометка=Оплата.ПолучитьАтрибут("Д"+строка(День));
                        Если (Пометка="Н") Тогда // нашли метку
                            ДолгиЗа=ДолгиЗа+Формат(Оплата.Период,"ДММММГГГГ")+" ";
                            Прервать; //дальше пометки не нужны
                        КонецЕсли; // нашли метку
                    КонецЦикла; //по дням
                    Прервать; //другие места не нужны
                КонецЕсли; //нашли строку по месту
            КонецЦикла; //по строкам Оплаты
        КонецЕсли; //получили документ Оплата по договору
    КонецЦикла; //по документам Оплата
    Возврат(ДолгиЗа)
КонецФункции
36 Злопчинский
 
15.03.21
19:48
(35) ужоснах ;-) но в той парадигме что есть - норм...
37 Злопчинский
 
15.03.21
19:59
Простая тупая переделка кода без включения мозга - 6-этажная хрень превращается в более менее линейный читаемый код..
.
Функция ПроверитьДоговор(Договор)
    ДолгиЗа = "";
    Оплата = СоздатьОбъект("Документ.ГрафикОплаты");
    Оплата.ВыбратьДокументы(НачМесяца(Договор.СрокС),КонМесяца(Договор.СрокПо));
    Пока Оплата.ПолучитьДокумент() = 1 Цикл //по документам Оплата

        Оплата_ПериодПо = КонМесяца(Оплата.Период);
        Если Оплата.Сектор <> Договор.Место.Родитель Тогда Продолжить; КонецЕсли;
        Если Договор.СрокС > Оплата_ПериодПо Тогда Продолжить; КонецЕсли;
        Если Договор.СрокПо < Оплата.Период Тогда Продолжить; КонецЕсли;

        Оплата.ВыбратьСтроки();
        Пока Оплата.ПолучитьСтроку() = 1 Цикл // Тогда Продолжить; КонецЕсли;
            Если Оплата.Место <> Договор.Место Тогда Продолжить; КонецЕсли;

            //проверить дни
            НачальноеЧисло = ДатаЧисло(?(Оплата.Период<Договор.СрокС, Договор.СрокС, Оплата.Период));
            КонечноеЧисло  = ДатаЧисло(?(Оплата_ПериодПо>Договор.СрокПо, Договор.СрокПо, Оплата_ПериодПо));
            //Сообщить(Строка(НачальноеЧисло)+"-"+Строка(КонечноеЧисло));

            Для День = НачальноеЧисло По КонечноеЧисло Цикл //по столбцам
                Пометка = Оплата.ПолучитьАтрибут("Д"+строка(День));
                Если Пометка <> "Н" Тогда Продолжить; КонецЕсли;
                ДолгиЗа = ДолгиЗа + Формат(Оплата.Период,"ДММММГГГГ")+" ";
                Прервать; //дальше пометки не нужны
            КонецЦикла; // по дням

            Прервать; // другие места не нужны
        КонецЦикла; // по строкам Оплаты
    КонецЦикла; // по документам Оплата

    Возврат(ДолгиЗа)
КонецФункции
38 HawkEye
 
15.03.21
20:35
(37) пошел бы дальше, выгрузил в ТЗ и найти(), еще быстрее было-бы, только смысл ))))
39 Cyr
 
15.03.21
21:47
(37) А можно ли подобное сделать через запрос?
40 Злопчинский
 
15.03.21
22:13
(39) что именно? стукайся в личку в скайп Zlopun если чо
41 Злопчинский
 
15.03.21
22:16
тут понимаешь какая закавыка - в запросе ты минимально к чему можешь адресоваться - это строка документа, отдельно вытянуть строку , в которой в колонках стоит "Н" не получится (это только в прямом запросе скорее всего получится может)
а так. максимум что в чорном запросе можно сделать - вытащить строку в которой хотя бы 1 раз встречается "Н" и тио я сомневаюсь что это будет быстрее чем перебором как у тебя.
42 Злопчинский
 
15.03.21
22:17
"отдельно вытянуть строку , в которой в колонках стоит "Н" не получится"
- читать как "отдельно вытянуть колонки, в которых стоит "Н"
43 Злопчинский
 
15.03.21
22:18
ща подумаю еще...
44 Cthulhu
 
15.03.21
22:19
не циклмтесь на запросах. через ТЗ это все имхо гораздо быстрее (во всех смыслах)
45 Злопчинский
 
15.03.21
22:24
В запросе будет такой текст (код с циклом выше)
Н = "Н";
...
|д1 = Документ.ГрафикОплаты.д1;
|д2 = Документ.ГрафикОплаты.д2;
..
|д31 = Документ.ГрафикОплаты.д31;
|Условие((д1=Н)ИЛИ(Д2=Н)...ИЛИ(Д31=Н));
.
тогда в выборку по запросу у тебя попадут только те строки документов где есть хотя бы одна Н
.
но я не думаю что такой запрос будет быстрее чем выборкой, хотя надо проверять...
и запрос выгрузить в ТЗ и уже по строчкам ТЗ бегать, будет быстрее
но имхо это не стоит усилий
46 Злопчинский
 
15.03.21
22:26
(44) угу
два варианта - простая выборка документов, выгрузка ТЧ документа в ТЗ и там аналогично как исходный код уже по ТЗ ходить.. но опять же я не думаю что это будет существенно быстрее
47 Злопчинский
 
15.03.21
22:28
второй вариант запросом выбрать ТОЛЬКО ПОДХОДЯЩИЕ документы по услвовиям шапки/договора, без учета строк, и уже по полученному списку документов ходить как в варианте исходном или в варианте 1.
48 Злопчинский
 
15.03.21
22:29
(0) "Для 200 договоров это занимает минуту." - и что? документ - на месяц, раз в месяц или раз в неделю пару раз запуститьи в тоге потратить 10 минут счета компа для получения данных -вообще проблем не вижу...
а если такой отчет собираетяс каждый день - тогда вопрос а нафуя вы туда весь месяц тогда запихнули...
49 Cyr
 
16.03.21
06:42
(48) короче, существующий отчёт в целом не плох и только с регистрами ещё попробовать остаётся... при желании
50 Cyr
 
16.03.21
06:45
(38) я пробовал через выгрузку в ТЗ. Не быстрее.
51 Cyr
 
16.03.21
10:52
(50) Хотя, если предварительно все договора рассортировать в ТЗ по датам и местам, то наверное быстрее будет.
52 Cyr
 
18.03.21
11:24
А может не с регистрами заморачиваться, а с "журналом расчётов" или с "Бухгалтерскими счетами"?
53 Харлампий Дымба
 
18.03.21
15:44
Ничего не понял в задаче, но скажу что:
1) регистры, бухитоги и  расчеты в твоём случае вряд ли нужны
2) строки НачальноеЧисло=ДатаЧисло(?(Оплата.Период<Договор.СрокС, Договор.СрокС, Оплата.Период)); и КонечноеЧисло =ДатаЧисло(?(Оплата_ПериодПо>Договор.СрокПо, Договор.СрокПо, Оплата_ПериодПо)); должны стоять перед ВыбратьСтроки() - чуть быстрее будет;
3) если ты гоняешь в отчете список договоров и по каждому запускаешь Функция ПроверитьДоговор(Договор), то есть полную выборку по документам за весь период действия каждого договора - это долго. Тогда уж просто один раз пробегись по всем документам и собери данные о неоплаченных договорах в ТЗ. А функцию оставь если надо получить данные по одному договору.
4) заведи в табличной части документа реквизит "ПервыйНеоплаченныйДень" и при проведении документа пиши туда номер дня с пометкой, если не было оплаты, или 0 если ни в одной дате не будет пометки. Тогда твоя функция избавится от 31 перебора внутри цикла

ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
ПервыйНеоплаченныйДень=0;
Для День = 1 По 31 Цикл
Если Оплата.ПолучитьАтрибут("Д"+День) Тогда
ПервыйНеоплаченныйДень=День
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;

5) Вместо совета (4) - Создай в договоре периодический реквизит "ДоговорНеОплачен" - с запретом изменять руками, только документом, "Число 1.0". При проведении документа пиши туда через УстановитьРеквизитСправочника 1 если есть ПервыйНеоплаченныйДень. Тогда для анализа договора тебе будет достаточно
П=СоздатьОбъект("Периодический");//если  будешь делать цикл по договорам - эту строку надо вынести из цикла, бо создание объекта "Периодический" - процесс относительно долгий
П.ИСпользоватьОбъект(Договор,"ДоговорНеОплачен");
ДолгиЗа="";
П.ВыбратьЗначения();
Пока П.ПолучитьЗначение()=1 Цикл
ДолгиЗа=ДолгиЗа+Формат(П.ТекущийДокумент().Оплата.Период,"ДММММГГГГ")+" ";
КонецЦикла;


Или просто в списке договоров по F5 пользователь увидит список неоплаченных графиков
54 Mikeware
 
18.03.21
16:11
(53) резюмирую:"если вы пытаетесь почесать правое ухо левой ногой, и это не совсем получается - изогните особым образом проволочку, зажмите ее зубами, и раскачивая этой проволокой фикус, медленно подводите правое ухо к нему, пока он не почешет вам ухо. если это не поможет - попытайтесь раскачивать кактус."
55 Харлампий Дымба
 
18.03.21
18:28
(54) Так задача была почесать правое ухо левой ногой?! А я думал, что ТС надо было выдрать кактус, поэтому и посоветовал раскачивание.

А если по делу - для пустой самописки, как у автора, использование периодического реквизита - самое простое. При оплате же бух входит в график платежей и убирает "Н", как я понял?
Хотя если бы это была какая-то конфа на базе Бухии, то самое простое - проводка по забалансовому счету. С учетом того, что любой обороткой можно долги увидеть.
56 Gucci76
 
18.03.21
18:56
(32) ПолучитьСтрокуПОномеру, но для табличной части документа. Я ЗиК убыстрял в несколько раз: компоненту ставил 1СРР и в особо больших базах Получал строку не в документе, а в ТаблицеЗначений (менял модуль).
Это по моим воспоминаниям, т.к. я ЗиК забросил как только все перешли на "восьмерку", а это было очень давно.
57 Cyr
 
19.03.21
10:43
(55) Этим занимаются не бухи, а менеджеры. Они до этого в экселе эту табличку делали. Потом вогнали её в 1С в виде документа "График оплаты". У меня тоже мысль была через проводки сделать проведение документа и потом типа анализ счёта по субконто.