Имя: Пароль:
1C
1С v8
Документ провожу, а он не проводится...
,
0 EvgeniuXP
 
13.06.13
20:24
Создал новый документ. В модуле объекта написал:

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
   НачатьТранзакцию();
   ОтменитьТранзакцию();
КонецПроцедуры

Запускаю пользовательский режим, нажимаю кнопку "Провести" и система пишет: "В данной транзакции уже происходили ошибки!" и документ не проводится.

Процедура "ПередЗаписью" ведь расположена вне транзакции...
1 Зойч
 
13.06.13
20:26
не прав
2 PR
 
13.06.13
20:26
Да разве?
Попробуй в ПередЗаписью создай номенклатуру "А вот и я!", запиши, напиши, что Отказ = Истина и поищи номенклатуру :))
3 PR
 
13.06.13
20:27
+(2) Это к (0) ессно
4 PR
 
13.06.13
20:29
Было бы неплохо иметь событие в объектах ПередЗаписьюДоНачалаТранзакции, кстати :))
Там можно делать всякие хрени, которые занимают много времени, но не хотелось бы на это время блокировать таблицы.
5 EvgeniuXP
 
13.06.13
20:30
(2) это понятно, но в 0 отказ = истина я не писал... но повлияла таки ОтменитьТранзакцию() :(
6 EvgeniuXP
 
13.06.13
20:39
(4) этот эффект и хотел получить, очистить регистр, прочитать последние записи без учета этого документа и отменить, чтобы записи восстановились в регистре... снова придется кучу наворотов делать...
7 Defender aka LINN
 
13.06.13
20:50
(6) О_о
Нахрена тебе это хотеть?
8 shuhard
 
13.06.13
20:54
(6) мсье знает толк в извращениях
9 EvgeniuXP
 
13.06.13
20:56
(7) документ провели, потом его снова открывают и меняют дату (будущую, например, ставят), на момент времени нужно прочитать предыдущие значения - вот он (документ) и прочитает свои снова значения :)
10 EvgeniuXP
 
13.06.13
20:58
(10) а мне проверить надо, правильно ли ввели документ, если значения с регистров предыдущие и текущие разные - то правильно, если одинаковые - то не нужно вводить такой документ.
11 EvgeniuXP
 
13.06.13
21:03
но последовательность тоже собъет - что тоже не очень...
12 Defender aka LINN
 
13.06.13
21:44
(9) Не удалять движения - предлагали?
13 EvgeniuXP
 
13.06.13
21:48
(9) не удалишь, предыдущие этого же документа прочитаешь, если дату поменяешь на будущую и его же перепроводишь. С активностью еще можно поиграть, кстати.
14 EvgeniuXP
 
13.06.13
21:52
но тоже не гуд, будет последовательность сбивать, т.к. пойдет запись в регистр.
15 NcSteel
 
13.06.13
21:54
маразм крепчал.
16 EvgeniuXP
 
13.06.13
21:56
(15) в чем именно? это пользователи такие, проведут документ, потом перепроводят будущими-прошлыми или этой же датой - надо и отслеживать, что они делают и в регистрах данные иметь хорошие, а не наляпанные.
17 NcSteel
 
13.06.13
21:57
(16) Меняй структуру регистра.
18 EvgeniuXP
 
13.06.13
21:59
(17) а регистр не причем, цех - свои даты, у таб - свои даты, у фио - свои даты, у должности - свои даты, у категории - свои даты - всё это разные регистры и это всё правильно.
19 NcSteel
 
13.06.13
22:01
(18) Если бы было правильно, то не пришлось головой об стену стучать. Меняй архитектуру решения, она ********
20 EvgeniuXP
 
13.06.13
22:01
в регистрах просто не хочу держать повторные значения на разные даты - отсюда и требования. Чтобы потом можно легко считать и узнать, когда сотрудник действительно получил.
21 EvgeniuXP
 
13.06.13
22:02
(19) например?
22 EvgeniuXP
 
13.06.13
22:04
(19) да механизм уже был написан только на периодичность в день, теперь надо на периодичность "регистратор" - вот и переделываю. Потом в списке физлица все отображаются документы и метятся красным, если последовательность сбита и нужно перепровести - одной кнопкой нажмет всё перепроведет :)
23 NcSteel
 
13.06.13
22:05
Если прям очень хочется, то сравнивай данные объекта и ссылки.  

Но решение не должно падать при заднем провведении документов.
24 NcSteel
 
13.06.13
22:06
Так же раз изменение интерактивное, то на форме есть перед записью событие, которое работает до транзакции
25 EvgeniuXP
 
13.06.13
22:08
(23) объект и ссылка ничего не дает, поменяли на цех, запишут в регистр этот цех (с объекта), а он уже был в этом цехе, зачем еще раз записывать туда и новую еще к тому же дату - это не правильно.

(24) при загрузке из одной платформы в другую тоже хочется по всем этим проверкам пройтись и выявить пробелы и не проводить документы.
26 NcSteel
 
13.06.13
22:09
(25) Пи загрузке опиши свой код в правилах обмена.
27 EvgeniuXP
 
13.06.13
22:10
(26) вот-вот, и корректирую и там и там - не удобно.
28 EvgeniuXP
 
13.06.13
22:11
(27) *корректируй
29 NcSteel
 
13.06.13
22:11
Нут так опиши в общем модуле. .....
30 EvgeniuXP
 
13.06.13
22:13
(29) это к документу относится

загрузка разовая.
31 NcSteel
 
13.06.13
22:14
(30) Ради разовой загрузки такой сыр бор....

рукалицо.
32 Reaper_1c
 
13.06.13
22:16
Перед записью новая дата и новый момент времени для объекта еще не записаны в базу. Подними ссылку и через нее вытащи момент документа из базы, читай данные на момент документа до изменения. Главное, чтоб у тебя режим блокировок стоял управляемый...
33 EvgeniuXP
 
13.06.13
22:19
(31) загрузка разовая (на момент загрузки всё проверить и сдать в эксплуатацию), а проводить пользователи будут под этими же алгоритмами, что и при загрузке проводились.
34 EvgeniuXP
 
13.06.13
22:21
(32) тоже не гуд, между этими двумя документами могут находиться другие документы - и смысл читать до изменения, если надо на момент измененного времени без учета прошлого этого же документа.
35 EvgeniuXP
 
13.06.13
22:23
можно насильно пользователя заставить отменить проведение и потом провести - но тоже плохо, будет влиять постоянно на последовательность, может он номер хотел исправить - а таким образом повлияем на регистр пустыми движениями.
36 Classic
 
13.06.13
22:24
(35)
Я не могу понять твоей задачи. Что мешает собрать движения в структуру таблиц, записать пустые, посмотреть что и как, а потом вернуть с структуры?
37 EvgeniuXP
 
13.06.13
22:26
(36) собьется последовательность, которая потом заставит перепровести все будущие документы по сотруднику заново (тот регистр который задел записав пустыми).
38 Reaper_1c
 
13.06.13
22:28
(37) Сху... почему это? Или у тебя последовательность с автоматической регистрацией?
39 Classic
 
13.06.13
22:30
(37)
Так не сбивай:)
Работа с последовательностью в программном режиме вполне возможна :)
40 EvgeniuXP
 
13.06.13
22:31
да я и не ищу ответа как это сделать, просто в (0) думал можно будет проще отменить транзакцию, которая и не повлияла бы на границу последовательности.

(38) да, автоматически перемещает границу.

(39) тогда везде кодить эту последовательность, где-куда переносить.
41 Classic
 
13.06.13
22:32
(40)
ПолучитьГраницу.....
чето там поделать....
УстановитьГраницу...

Отменять транзакцию, не получив ошибки - вообще-то дурной тон
42 EvgeniuXP
 
13.06.13
22:33
(43) ну не буду, буду просто читать из регистра данные, которые не равны текущему документу взяв первые и отсортировав по периоду и регистратору по убыванию - делов-то...
43 EvgeniuXP
 
13.06.13
22:34
и меньше текущего момента времени
44 EvgeniuXP
 
13.06.13
22:35
с фильтром по физлицу
45 azo1992
 
13.06.13
22:39
EvgeniuXP, а вообще автор предыдущего сообщения прав. так дал толковый совет
48 EvgeniuXP
 
13.06.13
23:06
(45) решение простое:

перед записью:
49 EvgeniuXP
 
13.06.13
23:06
Если Проведен И РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда // Проведен хранит прежнее состояние документа, т.е. таким образом условие срабатывает, если перепроводят данный документ:
       // Узнаем, был ли проведен документ до записи и заодно узнаем изменяли ли документ:
       Запрос = Новый Запрос;
       Запрос.Текст =
       "ВЫБРАТЬ
       |    ПриемНаРаботу.Подразделение,
       |    ПриемНаРаботу.ТабельныйНомер,
       |    ПриемНаРаботу.Фамилия,
       |    ПриемНаРаботу.Имя,
       |    ПриемНаРаботу.Отчество,
       |    ПриемНаРаботу.Должность,
       |    ПриемНаРаботу.Категория,
       |    ПриемНаРаботу.Разряд
       |ИЗ
       |    Документ.ПриемНаРаботу КАК ПриемНаРаботу
       |ГДЕ
       |    ПриемНаРаботу.МоментВремени = &МоментВремени";
       Запрос.УстановитьПараметр("Ссылка", Ссылка);
       Запрос.УстановитьПараметр("МоментВремени", МоментВремени());
       РезультатЗапроса = Запрос.Выполнить();
       Если НЕ РезультатЗапроса.Пустой() Тогда
           Выборка = РезультатЗапроса.Выбрать();
           // Результат запроса (предполагаем), что содержит одну строку:
           Выборка.Следующий();
           // Сравниваем текущие значения с прежними, если они все одинаковы, то заносим в "ДополнительныеСвойства", чтобы потом при проведении анализировать
           РезультатСравнения = Подразделение = Выборка.Подразделение И ТабельныйНомер = Выборка.ТабельныйНомер И Фамилия = Выборка.Фамилия  И Имя = Выборка.Имя  И Отчество = Выборка.Отчество;
           РезультатСравнения = РезультатСравнения И Должность = Выборка.Должность И Категория = Выборка.Категория И Разряд = Выборка.Разряд;
           ДополнительныеСвойства.Вставить("ДокументПерепроводитсяНеИзмененным", РезультатСравнения); // Истина или Ложь
       КонецЕсли;
   КонецЕсли;
50 EvgeniuXP
 
13.06.13
23:07
// II ЭТАП. УСТАНАВЛИВАЕМ ЗНАЧЕНИЯ ПО УМОЛЧАНИЮ:    
   // Перед записью при проведении, если момент времени одинаковый и все (влияющие на регистры) реквизиты одинаковы между старым проведенным и новым проводимым, то значение Истина, иначе - Ложь
   ДокументПерепроведенНеИзмененным = ДокументПерепроводитсяНеИзмененным(ЭтотОбъект);
   
   // III ЭТАП. Создаем движения, которые не влияют на последовательность:
   СоздатьДвижениеВРегистрСведенийСотрудникФизЛица(ДатаПриема, Сотрудник);
   СоздатьДвижениеВРегистрСведенийСостояниеСотрудников(ДатаПриема, Сотрудник);
   
   // IV ЭТАП. Делаем анализ данных, т.е. как будем делать движения: 0 - ничего не делаем, 1 - очищаем и создаем движения на "ДатаПриема":
   СтруктураТекущихЗначений = ПолучитьСтруктуруТекущихЗначений();        
   Если НЕ ДокументПерепроведенНеИзмененным Тогда
       // 1. Пользователь создал новый документ и его проводит
       // 2. Пользователь открыл непроведенный документ и его проводит
       // 3. Пользователь открыл проведенный документ и поменял "ДатаПриема"
       // Во всех этих случаях мы всегда создаем движения на дату "ДатаПриема"
       РезультатАнализаДанных = 1; // РезультатАнализаДанных = 1 или 2
   Иначе // Документ перепроводится, момент времени одинаковый (ДатаПриема), все реквизиты (которые делают движения по регистрам) одинаковые - пользователь их не менял
       Если ДокументПерепроведенНеИзмененным Тогда
           // 2. Пользователь перепроводит этот документ интерактивно, при этом на форме (влияющие на регистры) он ничего не менял - необходимо анализировать границу:
           ГраницаПоследовательности = УчетДвиженияКадров.ПолучитьГраницуПоследовательности(Сотрудник);
           МоментВремени = МоментВремени();
           Если ГраницаПоследовательности <> Неопределено И МоментВремени.Сравнить(ГраницаПоследовательности) = -1 Тогда // Если МоментВремени < Границы - ничего не делаем
               РезультатАнализаДанных = 0; // Ничего не делаем: не очищаем регистры от старых значений, не создаем новые значения в регистрах
           Иначе    // Если МоментВремени >= Границы
               РезультатАнализаДанных = 1; // РезультатАнализаДанных = 1
           КонецЕсли;
       Иначе
           // 3. Пользователь перепроводит этот документ интерактивно, при этом на форме (влияющие на регистры) он изменил значения
           РезультатАнализаДанных = 1; // РезультатАнализаДанных = 1
       КонецЕсли;
   КонецЕсли;
   
   // V ЭТАП. Делаем очистику и движение на "ДатаПриема":
   Если РезультатАнализаДанных > 0 Тогда // Очищаем регистры, перед тем как делать движения:
       СделатьОчисткуИЗаписатьРегистрСведений("Подразделения");
       СделатьОчисткуИЗаписатьРегистрСведений("ТабельныеНомера");
       СделатьОчисткуИЗаписатьРегистрСведений("ФИОСотрудников");
       СделатьОчисткуИЗаписатьРегистрСведений("Должности");
       СделатьОчисткуИЗаписатьРегистрСведений("Категории");
       СделатьОчисткуИЗаписатьРегистрСведений("Разряды");
   КонецЕсли;
   Если РезультатАнализаДанных > 0 Тогда // Делаем движения на дату "ДатаПриема", если значения разные
       // делаем движения
       СделатьДвижениеПоРегиструСведений(ДатаПриема, СтруктураТекущихЗначений, "Подразделение");
       СделатьДвижениеПоРегиструСведений(ДатаПриема, СтруктураТекущихЗначений, "ТабельныйНомер");
       СделатьДвижениеПоРегиструСведений(ДатаПриема, СтруктураТекущихЗначений, "ФИО");
       СделатьДвижениеПоРегиструСведений(ДатаПриема, СтруктураТекущихЗначений, "Должность");
       СделатьДвижениеПоРегиструСведений(ДатаПриема, СтруктураТекущихЗначений, "Категория");
       СделатьДвижениеПоРегиструСведений(ДатаПриема, СтруктураТекущихЗначений, "Разряд");
   КонецЕсли;
51 EvgeniuXP
 
13.06.13
23:07
всё идеально работает.
52 EvgeniuXP
 
13.06.13
23:09
+ еще документы будущие залезают в прошлые и перепроводят их  и восстанавливают последовательность, т.к. два подряд документа проводятся. Убирают движения на дату окончания, если  выходят за пределы.
53 EvgeniuXP
 
13.06.13
23:10
(50) модуль вытащил из события при проведении.
54 EvgeniuXP
 
13.06.13
23:19
(45) а смысл? там также надо анализировать момент времени и при этом еще устанавливать вручную эту дату. Здесь не надо, всё делает автоматика - сама сместит когда надо. Просто движения нужно сделать тогда, когда это действительно требуется - остальные случаи отфильтровать, типа документ проведен и значения его не менялись.

Там ты также будешь анализировать и делать/не делать движения.
55 EvgeniuXP
 
13.06.13
23:39
(41) установить границу - надо еще проверять, есть ли между этой границей и установленной другие документы :), если нет - то устанавливать, есть есть - то не ставить - один геморой только.
56 EvgeniuXP
 
13.06.13
23:42
тем более, что ручная установка - это очень тонко (ювелирно) подходить к работе, и не дай бог где в алгоритме ошибешься - ошибку можешь сразу не определить - нет уж :)
57 goleaff2006
 
14.06.13
05:17
А сделать подписку перед записью в которой удалять старые  данные из регистра.Затем подписку проведение в которой записывать новые данные.И подписку удаление проведения в которой удалять  данные из регистра?
58 hhhh
 
14.06.13
07:35
(56) посмотри ака в типовых сделано. Чего ты велосипед изобретаешь?
59 EvgeniuXP
 
14.06.13
16:53
(58) типовая какая?
60 EvgeniuXP
 
14.06.13
18:50
(57) опробую завтра. :)
61 EvgeniuXP
 
14.06.13
20:57
кому интересно про что тут вообще было вот видео: http://video.yandex.ru/users/evgeniuxp/view/4/.
62 EvgeniuXP
 
14.06.13
21:02
внизу это история, первая строка всегда заполняется значениями, вторая только теми, которые изменены, если пустые - это см. ниже строчку. Когда последовательность сбивается, верхние документы перепроводятся и тем самым убирают грязь из регистра.