Имя: Пароль:
1C
1С v8
Предупредить проблему с датами "до нашей эры"
0 serg-lom89
 
08.12.16
09:30
Добрый день
Возникла проблема с обменом.Выяснилось что кто то кривыми руками указал дату до "нашей эры"))))
Кто делал какие нить "затычки" для этих моментов?или только метод кнута спасет ?)
1 Cool_Profi
 
08.12.16
09:30
Гдле указал?
2 aleks_default
 
08.12.16
09:32
Настройками SQL или сервера приложений
3 serg-lom89
 
08.12.16
09:33
(1) в данном случае в Договоре
(2)  по этому случаю в Скуле указали 2000 смещение дат.Но все таки защиту думаем какую нить поставить.Вопрос как реализовать данный момент?
4 mehfk
 
08.12.16
09:34
(0) 1С:Управление строительством пирамид?
5 Cool_Profi
 
08.12.16
09:34
Проверяй ПриЗаписи() если Дата < Дата(2000, 1, 1) тогда
6 serg-lom89
 
08.12.16
09:35
(5) да придется делать какую  то функцию которая будет перебирать не только реквизиты но и ТЧ части.Вопрос на сколько это скажется на производительности
7 serg-lom89
 
08.12.16
09:35
(4) не,берите мельче)))
8 mehfk
 
08.12.16
09:37
(7) 1С:Управление билетным хозяйством Колизея?
9 mehfk
 
08.12.16
09:38
А не, Колизей это уже наша эра.
10 Fedor-1971
 
08.12.16
09:45
(5) поздно, объект уже записан.
(0) Если универсально, то подписка на ПередЗаписью (проверяй по типу документа, например, одному только дату документа, другому ещё какие-нить даты). Если индивидуально, ПриИзменении у поля даты - сделай единую функцию контроля и всех делов
11 serg-lom89
 
08.12.16
09:47
(10)
Идея была в том что бы перебрать все реквизиты справочника или документа,отобрать те у которох тип дата и проверить на дату(Если она заполнена)
12 serg-lom89
 
08.12.16
09:50
(11) проблема в другом заключается..в том что упадет производительность.реквизиты шапки ладно.а вот реквизиты ТЧ  будет долго
13 serg-lom89
 
08.12.16
09:52
(12) как ускорить данный момент?
14 Fedor-1971
 
08.12.16
09:53
(12) Обрати взор на модуль объекта, сделай ПередЗаписью и проверяй реквизиты конкретные, а не через поиск типа реквизита в метаданных
15 serg-lom89
 
08.12.16
09:55
(14) так перед записью и хочу воткнуть функцию проверки.какую нить универсальную.
Конкретные наверное не всегда получиться,потому что все время что то дорабатывается и усмотреть за этим именно не всегда получиться.((
16 Cool_Profi
 
08.12.16
09:56
(15) Перебирай по метаданным и везде где есть тип дата...
17 тарам пам пам
 
08.12.16
09:56
(12) если у тебя нет таб частей по 10к строк, то производительность не должна упасть. Сделай замер, в конце концов, там кода на 15 мин времени.
18 serg-lom89
 
08.12.16
09:58
(17)  замер сам собой конечно будет)
но есть документы по которым строк больше 10 к.(
19 Fedor-1971
 
08.12.16
10:02
(18) тогда регламентное задание. При записи объекта в РС пишем признак "Проверить", регламентом проверяем, то что не проверено в обмен не включаем.
20 Vladal
 
08.12.16
11:08
(5) Еще бывают даты 2160 вместо 2016.
21 Волшебник
 
модератор
08.12.16
11:14
(0) В григорианском календаре нет дат до нашей (новой) эры. Отсчёт начинается с 0001.01.01

Там только бывает число лет до нашей эры, например, 7000 до н.э.
22 serg-lom89
 
08.12.16
11:23
(20) ну в большую не в меньшую ))
23 serg-lom89
 
08.12.16
15:11
Функция ПроверкаНаКорректнуюДату(СсылкаНаОбъект) Экспорт   //езерский 081216
    
    ОшибкаЗаполненияЛаты = ложь;
    
    КодТекУзла = ОбщегоНазначения.ПолучитьТекущийУзел();
    ДатаСмещения = УправлениеЗаказами.ПолучитьТекущуюНастройкуРИБ("СмещениеДаты", КодТекУзла);
    
    Если   ДатаСмещения = неопределено Тогда
        Возврат   ОшибкаЗаполненияЛаты;
    КонецЕсли;
    
    Если НЕ ЗначениеЗаполнено(ДатаСмещения) Тогда
        Возврат ОшибкаЗаполненияЛаты;
    КонецЕсли;
    
    типДата =   Тип("Дата");
    
    МетаданныеОбъекта = СсылкаНаОбъект.метаданные();
    
    КоллекцияРеквизитовОбъекта  =  МетаданныеОбъекта.реквизиты;
    
    КоллекцияТЧ = МетаданныеОбъекта.ТабличныеЧасти;
    
    
    Для каждого Строка из КоллекцияРеквизитовОбъекта Цикл
        
        РеквизитИмя = Строка.имя;
        РеквизитСиноним =  Строка.синоним;
        
        ЗначениеРеквизита  =  СсылкаНаОбъект[РеквизитИмя];
        
        Если не значениеЗаполнено(ЗначениеРеквизита) Тогда
            продолжить;
        КонецЕсли;
        
        
        Если ТипЗнч(ЗначениеРеквизита)=типДата тогда
            Если ЗначениеРеквизита < ДатаСмещения Тогда
                ИмяРеквизитаДляСообщения  = ?(РеквизитСиноним = "", РеквизитИмя,РеквизитСиноним);
                #Если Клиент Тогда
                    сообщить("У реквизита << "+ ИмяРеквизитаДляСообщения + " >> значение("+ЗначениеРеквизита +") меньше Даты смещения ("+ДатаСмещения+") установленного для узла= "    +КодТекУзла);
                #КонецЕсли    
                Возврат Истина;
            КонецЕсли;
            
        КонецЕсли;    
    КонецЦикла;
    
    
    //проверим ТЧ
    Для каждого Строка из КоллекцияТЧ Цикл
        
        ИмяТЧ = Строка.Имя;
        СинонимТабличнойЧастиОбъекта=Строка.Синоним;
        
        ИмяТЧДляСообщения = ?(СинонимТабличнойЧастиОбъекта="",ИмяТЧ, СинонимТабличнойЧастиОбъекта);
        
        
        ТабличнаяЧастьОбъекта=СсылкаНаОбъект[ИмяТЧ];
        
        //Если ТЧ пустая проверять нету смысла
        Если   ТабличнаяЧастьОбъекта.количество()=0 Тогда
            продолжить;    
        КонецЕсли;
        
        КоллекцияРеквизитовТЧ =  Строка.Реквизиты;
        
        Для каждого СтрокаТЧ из ТабличнаяЧастьОбъекта Цикл
            Для каждого СтрокаЗначенияРеквизита Из   КоллекцияРеквизитовТЧ Цикл
                
                РеквизитСтроки = СтрокаЗначенияРеквизита.Имя;
                РеквизитСтрокиСиноним =  СтрокаЗначенияРеквизита.синоним;
                
                ИмяРеквизитаТЧДляСообщения = ?(РеквизитСтрокиСиноним="",РеквизитСтроки, РеквизитСтрокиСиноним);
                
                ЗначениеРеквизитаСтроки = СтрокаТЧ[РеквизитСтроки] ;
                
                Если не значениеЗаполнено(ЗначениеРеквизитаСтроки) Тогда
                    продолжить;
                КонецЕсли;
                
                Если не ТипЗнч(ЗначениеРеквизитаСтроки)=типДата тогда
                    продолжить;
                КонецЕсли;
                
                
                Если ЗначениеРеквизитаСтроки < ДатаСмещения Тогда
                    #Если Клиент Тогда
                        ТекстСообщения  =     " В табличной части <"+ ИмяТЧДляСообщения+"> в строке {"+  СтрокаТЧ.НомерСтроки + "} у рекивизита {"+ ИмяРеквизитаТЧДляСообщения + "} "+
                        "значение {"+ ЗначениеРеквизитаСтроки+"} меньше Даты смещения ("+ДатаСмещения+") установленного для узла= "    +КодТекУзла ;
                        Сообщить(    ТекстСообщения);
                    #КонецЕсли    
                    Возврат Истина;
                КонецЕсли;
            КонецЦикла;    
        КонецЦикла;
    КонецЦикла;
    
    Возврат ОшибкаЗаполненияЛаты;    
    
КонецФункции
24 serg-lom89
 
08.12.16
15:12
сделал функцию которая проверяем на дату "до нашей эры".
Подскажите как оптимизировать для ТЧ частей?
25 serg-lom89
 
08.12.16
15:12
у кого какие идеи есть?может "тыкнете" где можно лучше))
26 serg-lom89
 
08.12.16
15:31
пугает что то что я получаю каждую строку,и затем перебираю каждый реквизит этой строки.а если это будет 10 000 строк..может кто подкинет идею что бы быстрее сделать?
27 serg-lom89
 
09.12.16
08:59
апну тему,может у кого с утра в пятницу голова свежая)
28 FIXXXL
 
09.12.16
09:17
(27) динамически строить текст запроса и алга
29 Fedor-1971
 
09.12.16
09:20
(27) зря надеешься. Сгенерируй динамически текст запроса по метаданным для ТЧ с условием "Дата не такая", если строки в выборке есть работаешь с объектом, нет просто подтверждаешь его нормальность.
Для одного документа время перебора строк может быть сравнимым с временем генерации динамического текста запроса и его отработки (возможно, что перебор строк будет быстрее).
30 FIXXXL
 
09.12.16
09:25
(29) чет сомневаюсь, что перебор будет быстрее
это ж надо сначала получить от Ссылки Объект, хотя б и неявно, через точку
ставлю на запрос :)
31 Fedor-1971
 
09.12.16
09:32
(30) всё решает количество строк в документе (например, 100 - перебор строк, 1000 - примерно равны, 10 000 - запрос) и количество документов с каждым уровнем строк (2 док по 10 000, 20 док по 1000 и 10 000 док по 100).
Для массового контроля запрос однозначно более выгоден, для одного документа не факт.
Но для исправления дат нужно получить объект и, по сути, опять перебор строк.
32 FIXXXL
 
09.12.16
09:34
(31) тут согласен, частности зарулят статистику :)
хз чего там у ТС в базе

по поводу исправления только: все ж "хороших" документов гораздо больше должно быть, тогда получать Объект "про запас" излишне
33 Dmitrii
 
гуру
09.12.16
09:37
(27) Какой запрос ПередЗаписью?
Данных в базе еще не существует.
Зато Объект (вместе с табличными частями) в этот момент точно в памяти.
34 Fedor-1971
 
09.12.16
09:46
(33) ТС хочет универсальную функцию. Одну на всю конфигурацию что бы сама даты вылавливала и проверяла.
35 Dmitrii
 
гуру
09.12.16
09:46
ИМХО, униврсальность в данном случае - не лучшее решение.
Правильнее создать некую настроечную таблицу (справочник или регистр сведений), где указать только те объекты метаданных и только те реквизиты, которые действительно необходимо контролировать.
Единственный реквизит, который контролировать обязательно и всегда - дата документа.

(23) Зачем перебирать все реквизиты каждой строки табличной части? Для больших табличных частей явно будет быстрее сначала выяснить те реквизиты, которые имеют тип Дата и проверять только их.
36 Dmitrii
 
гуру
09.12.16
09:48
(34) И что дальше? От этого в ПередЗаписью нового объекта данные в базе не появятся.
Запросы работаю только к данным, которые есть в базе.
Ты предлагаешь сначала записать данные, а уже потом проверять?
37 serg-lom89
 
09.12.16
09:50
(34) да..все верно)
38 serg-lom89
 
09.12.16
09:51
(35) не хочется создавать что то в виде набивания данными,через год об этом забудется((((
39 Fedor-1971
 
09.12.16
09:59
(36) у ТС спроси, я его конфигурацию не видел и не знаю какие там документы их состав и распределение по "тяжести информации".
Варианта 2:
а. записать быстро "как есть" и потом проверять корректность массово (для доков, например, с 10к строк)
б. проверять корректность прямо перед записью (для маленьких доков).

Тут ТС решать что и как.
40 dmpl
 
09.12.16
10:02
(6) При обмене? Есть 2 варианта:
1) Анализировать XML промежуточной программой на предмет наличия такой даты
2) При обмене сделать функцию преобразования типа Дата с проверкой.
41 dmpl
 
09.12.16
10:04
(15) Не надо перед записью - проблема же только в обмене, вот только там и делать.
42 dmpl
 
09.12.16
10:08
(23) Зачем объект называть ссылкой на объект?

(29) А это ничего, что объект с кривой датой еще в БД не записан? Так все равно придется таблицу значений во временную таблицу класть и только потом отбирать. А создание временной таблицы не мгновенно.

(30) Объект не записан же еще.
43 dmpl
 
09.12.16
10:09
(33) Ну почему? Может и существует, но его данные другие ;)
44 dmpl
 
09.12.16
10:10
(34) Попытка Исключение - самое оно.
45 dmpl
 
09.12.16
10:11
(36) Ага, сначала попытаться записать, ну а если исключение - проверять. Тоже вариант.
46 bodri
 
09.12.16
10:12
а как выглядит в 1С дата до нашей эры, дата с минусом?
47 dmpl
 
09.12.16
10:12
(39) Записать сработает только с ненулевым смещением дат. Тут и проблемы нет. Проблема вылезает при попытке записи в БД с нулевым смещением - там запись окончится ошибкой.
48 serg-lom89
 
09.12.16
10:13
(46) это я так обозвал ее)))
49 dmpl
 
09.12.16
10:23
Хотя... если делать запрос - то делать его в базе-источнике перед обменом и с отбором по объектам для обмена. Т.е. проверять ограниченный набор объектов. Можно даже динамический запрос генерить.
50 RomaH
 
naïve
09.12.16
10:41
Процедура ПроверкаЗаполненияДатыОбработкаПроверкиЗаполнения(Источник, Отказ, ПроверяемыеРеквизиты) Экспорт
    
    Если Источник.ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;
    
    ТекущаяДата = ТекущаяДата();
    
    МинимальнаяДата = ДобавитьМесяц(ТекущаяДата,-1200);
    МинимальнаяДата = ДобавитьМесяц(МинимальнаяДата,-12*6);
    МаксимальнаяДата = ДобавитьМесяц(ТекущаяДата,120);
    НулеваяДата = '00020101';
    
    МетаданныеИсточника = Источник.Метаданные();
    
    Если Метаданные.Документы.Содержит(МетаданныеИсточника) Тогда
        МассивПроверяемыхРеквизитов = Новый Массив;
        МассивПроверяемыхРеквизитов.Добавить("Дата");        
        
        Для Каждого Реквизит Из МетаданныеИсточника.Реквизиты Цикл
            Если Реквизит.Тип.СодержитТип(Тип("Дата")) Тогда
                МассивПроверяемыхРеквизитов.Добавить(Реквизит.Имя);        
            КонецЕсли;
        КонецЦикла;
        
        Для Каждого ИмяРеквизита Из МассивПроверяемыхРеквизитов Цикл
                
            Если Источник[ИмяРеквизита] > МаксимальнаяДата Тогда
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Указана дата больше чем " + Формат(МаксимальнаяДата,"ДФ=dd.MM.yyyy"),Источник,ИмяРеквизита,,Отказ);     
            ИначеЕсли Источник[ИмяРеквизита] < МинимальнаяДата И Источник[ИмяРеквизита] >= НулеваяДата Тогда
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Указана дата меньше чем " + Формат(МинимальнаяДата,"ДФ=dd.MM.yyyy"),Источник,,,Отказ);     
            КонецЕсли;
            
        КонецЦикла;    
        
        Для Каждого ТабЧасть Из МетаданныеИсточника.ТабличныеЧасти Цикл
            
            МассивПроверяемыхРеквизитов.Очистить();
            
            Для Каждого Реквизит Из ТабЧасть.Реквизиты Цикл
                Если Реквизит.Тип.СодержитТип(Тип("Дата")) Тогда
                    МассивПроверяемыхРеквизитов.Добавить(Реквизит.Имя);        
                КонецЕсли;
            КонецЦикла;
            
            Для Каждого ИмяРеквизита Из МассивПроверяемыхРеквизитов Цикл
                
                Для Каждого СтрокаТЧ Из Источник[ТабЧасть.Имя] Цикл
                    
                    ЗначениеРеквизита = СтрокаТЧ[ИмяРеквизита];
                    
                    Если Не ТипЗнч(ЗначениеРеквизита) = Тип("Дата") Тогда
                        Продолжить;
                    КонецЕсли;
                    
                    Если ЗначениеРеквизита > МаксимальнаяДата Тогда
                        ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Указана дата больше чем " + Формат(МаксимальнаяДата,"ДФ=dd.MM.yyyy"),Источник,,,Отказ);     
                    ИначеЕсли ЗначениеРеквизита < МинимальнаяДата И ЗначениеРеквизита >= НулеваяДата Тогда
                        ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Указана дата меньше чем " + Формат(МинимальнаяДата,"ДФ=dd.MM.yyyy"),Источник,,,Отказ);     
                    КонецЕсли;
                    
                КонецЦикла;
                
            КонецЦикла;    
            
        КонецЦикла;
        
    ИначеЕсли Метаданные.Справочники.Содержит(МетаданныеИсточника) Тогда
        МассивПроверяемыхРеквизитов = Новый Массив;
        Для Каждого Реквизит Из МетаданныеИсточника.Реквизиты Цикл
            Если Реквизит.Тип.СодержитТип(Тип("Дата")) Тогда
                МассивПроверяемыхРеквизитов.Добавить(Реквизит.Имя);        
            КонецЕсли;
        КонецЦикла;
        
        Для Каждого ИмяРеквизита Из МассивПроверяемыхРеквизитов Цикл
                
            Если Источник[ИмяРеквизита] > МаксимальнаяДата Тогда
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Указана дата больше чем " + Формат(МаксимальнаяДата,"ДФ=dd.MM.yyyy"),Источник,ИмяРеквизита,,Отказ);     
            ИначеЕсли Источник[ИмяРеквизита] < МинимальнаяДата И Источник[ИмяРеквизита] >= НулеваяДата Тогда
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Указана дата меньше чем " + Формат(МинимальнаяДата,"ДФ=dd.MM.yyyy"),Источник,,,Отказ);     
            КонецЕсли;
            
        КонецЦикла;    
        
        Для Каждого ТабЧасть Из МетаданныеИсточника.ТабличныеЧасти Цикл
            МассивПроверяемыхРеквизитов.Очистить();
            Для Каждого Реквизит Из ТабЧасть.Реквизиты Цикл
                Если Реквизит.Тип.СодержитТип(Тип("Дата")) Тогда
                    МассивПроверяемыхРеквизитов.Добавить(Реквизит.Имя);        
                КонецЕсли;
            КонецЦикла;
            
            Для Каждого ИмяРеквизита Из МассивПроверяемыхРеквизитов Цикл
                
                Для Каждого СтрокаТЧ Из Источник[ТабЧасть.Имя] Цикл
                    
                    ЗначениеРеквизита = СтрокаТЧ[ИмяРеквизита];
                    
                    Если ТипЗнч(ЗначениеРеквизита) = Тип("Дата") Тогда
                        Если ЗначениеРеквизита > МаксимальнаяДата Тогда
                            ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Указана дата больше чем " + Формат(МаксимальнаяДата,"ДФ=dd.MM.yyyy"),Источник,,,Отказ);     
                        ИначеЕсли ЗначениеРеквизита < МинимальнаяДата И ЗначениеРеквизита >= НулеваяДата Тогда
                            ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Указана дата меньше чем " + Формат(МинимальнаяДата,"ДФ=dd.MM.yyyy"),Источник,,,Отказ);     
                        КонецЕсли;
                    КонецЕсли;
                    
                КонецЦикла;                
            КонецЦикла;    
            
        КонецЦикла;
    ИначеЕсли Метаданные.РегистрыСведений.Содержит(МетаданныеИсточника) Тогда
        
        МассивПроверяемыхРеквизитов = Новый Массив;
        
        Если МетаданныеИсточника.ПериодичностьРегистраСведений <> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический Тогда
            МассивПроверяемыхРеквизитов.Добавить("Период");        
        КонецЕсли;
        
        Для Каждого Реквизит Из МетаданныеИсточника.Измерения Цикл
            Если Реквизит.Тип.СодержитТип(Тип("Дата")) Тогда
                МассивПроверяемыхРеквизитов.Добавить(Реквизит.Имя);        
            КонецЕсли;
        КонецЦикла;
        Для Каждого Реквизит Из МетаданныеИсточника.Реквизиты Цикл
            Если Реквизит.Тип.СодержитТип(Тип("Дата")) Тогда
                МассивПроверяемыхРеквизитов.Добавить(Реквизит.Имя);        
            КонецЕсли;
        КонецЦикла;
        Для Каждого Реквизит Из МетаданныеИсточника.Ресурсы Цикл
            Если Реквизит.Тип.СодержитТип(Тип("Дата")) Тогда
                МассивПроверяемыхРеквизитов.Добавить(Реквизит.Имя);        
            КонецЕсли;
        КонецЦикла;
        
        Для Каждого СтрокаНабора Из Источник Цикл
            
            Для Каждого ИмяРеквизита Из МассивПроверяемыхРеквизитов Цикл
                
                Если СтрокаНабора[ИмяРеквизита] > МаксимальнаяДата Тогда
                    ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Указана дата больше чем " + Формат(МаксимальнаяДата,"ДФ=dd.MM.yyyy"),Источник,,,Отказ);     
                ИначеЕсли СтрокаНабора[ИмяРеквизита] < МинимальнаяДата И СтрокаНабора[ИмяРеквизита] >= НулеваяДата Тогда
                    ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Указана дата меньше чем " + Формат(МинимальнаяДата,"ДФ=dd.MM.yyyy"),Источник,,,Отказ);     
                КонецЕсли;
                
            КонецЦикла;    
            
        КонецЦикла;
        
    КонецЕсли;
    
КонецПроцедуры


подписка - обраотка проверки заполнения