Имя: Пароль:
1C
 
Грамотное Проведение документа (расход)
0 svsource
 
07.02.13
12:48
Добрый день, Уважаемые коллеги!

Возник вопрос по управляемым блокировкам.
Несмотря на многочисленные статьи и публикации,
П.Чистова, Е.Гилева, П.Белоусова, Статьи ИТС,
курсы и т.д. все таки однозначного ответа так и нет
для конкретных примеров 1С 8.2. - все я это читал.
Но просто и кратко нет нигде!

Вот что я уяснил :

1. Классическая схема - блокируем, читаем, принимаем решение потом пишем
2. Сначала пишем - потом блокируем, читаем и принимаем решение

======================================================================

Привожу примеры кода. (Расходная накладная). Движение по одному регистру - остатки
Измерения (Номенклатура), Ресурсы (Количество) - для простоты

далее
- устанавливаю на уровне конфигурации "Управляемая блокировка"
- Документ (закладка движения) - Удалять автоматически при отмене проведения. ( или Не удалять автоматически)
  (оптимально для, большинства задач). "Удалять автоматически" - неоптимальное решение
- В регистре накопления "Остатки" - "Разделение итогов" (закладка ПРОЧИЕ) = ИСТИНА

ДЕЙСТВИЕ - "ПЕРЕПРОВЕДЕНИЕ ПРОВЕДЕННОГО ДОУМЕНТА" - самая интересная операция.

Для схемы 1.

Процедура ОбработкаПроведения(Отказ, Режим)    

   // 1. (ну для подстраховки - Движения.Остатки.Очистить() - хотя набор и так пустой)
          это, чтобы существующие движения документа не мешали п.4
       
   Движения.Остатки.Записать();

   // 2. Сообщаем, что при успешном создании набора записей и Отказ = ЛОЖЬ - сохранить данные на диск.

   Движения.Остатки.Записывать = ИСТИНА;
   

   // 3. Блокируем, только то что нужно !!!! для проведения, а не все подряд
        (могут быть разные комбинации Номенклатура, склад, партии и т.д.) так :

   Блокировка = Новый БлокировкаДанных;
   Блокировка ....... (Источники, режим, данные блокировки и т.д.)
   Блокировка.Заблокировать();

   // 4.
   Читаем данные (ЧИСТОЕ ЧТЕНИЕ !!!) запросом, например
   с ограничением ТабЧасти и Лев.Соединением с регистром остатки,
   &Момент (зависит от режима это или НЕОПРЕДЕЛЕНО или МоментВремени()) - это детали уже

   // 5.
   Обходим выборку и формируем движения ("расход") в "остатки"
   Если Отказ на какой то строке, тогда сообщаем о нехватке количества - тоже детали

   // 6. Специально ничего не записываем, Никаких Движения.Остатки.ЗАПИСАТЬ() т д.
   Т.е. установили флаг записи в п.2 и система сохранит набор записи на диске (FLASH) - САМА
   иначе два раза запишет одно и тоже, что не есть гуд.
   Если Отказ = ИСТИНА, То движения старые естественно сохраняться
   

КонецПроцедуры


Для схемы 2.

Процедура Обработка Проведения(Отказ, Режим)    

   // 1. Пишем Движения в "Остатки". Прямо так вот сразу

   Типа :
   Для Каждого СтрокаТабЧасти Из СписокТоваров Цикл

       НоваяЗапись = Движения.Остатки.ДобавитьРасход();
       ЗаполнитьЗначенияСвойств(НоваяЗапись, СтрокаТабЧасти);  Ну это условно, конечно        

   КонецЦикла;          
   
   // 2.   !!!! Важно

   Движения.Остатки.БлокироватьДляИзменения = Истина;
   Движения.Остатки.Записать(); // БЛОКИРОВКА ИСКЛЮЧИТЕЛЬНАЯ
   
   // 3. Чтение запросом Включая движения, которые только что сделали
   Типа как &Момент = Новый Граница(МоментВремени(), ВидГраницы.Включая);


   // 4. Анализ данных на отрицательные остатки и Отказ = Истина, если есть таковые
         с сообщением пользователю    


   // 5.        
   Если Отказ = Ложь, То Движения.Остатки.Записывать = Истина;

КонецПроцедуры

В связи с этим, вопросы

1. Интересует по порядку пунктов и самим пунктам. ГРУБЫЕ КОСЯКИ схем 1 и 2.

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

Прошу Вашей экспертной помощи.
С уважением, Сергей
1 GANR
 
07.02.13
14:11
(0) Чтобы выяснить что и как блокируется нужно в режиме отладки остановить код после блокировки, а вдругом сеансе попытаться провести другой документ. Если блокировка мешает - вывалится DeadLock.

Вот по этому принципу Вы сможете выяснить что и как работает.

Вот веточка интересная http://devtrainingforum.v8.1c.ru/forum/thread.jsp?id=607032#607032
2 GANR
 
07.02.13
14:20
При втором способе нужно
Движения.Остатки.БлокироватьДляИзменения = Истина;
иначе ничего не заблокируется.

Короче, см. (1) и пробуйте.
3 svsource
 
07.02.13
14:27
Так я с сделал так схема 2 пункт 2.
4 svsource
 
07.02.13
14:28
Но вот только в начале модуля что то не так мне кажется.. Я не знаю блокируются ли движения ДО ПЕРЕПРОВЕДЕНИЯ документом автоматически. Статью я конечно прочитаю. Спасибо Вам.
5 GANR
 
07.02.13
14:44
(4) ДО ПЕРЕПРОВЕДЕНИЯ, то есть после ЗАПИСИ, но ДО ПЕРЕПРОВЕДЕНИЯ. Можно точки останова поставить в конце ПриЗаписи и вначале ОбработкаПроведения. И замер сделать - будут видны строки, выполняемые между этими точками. Хотя, конечно, не всё ловится отладчиком, например, перестроение динамических списков приложения порой висит - и не поймешь по отладке.
6 svsource
 
07.02.13
15:03
Прочитал по ссылке. Павел Белоусов пишет что Движения.Остатки.БлокироватьДляИзменения = Истина; нужно добавить для блокировки существующих движений документа на момент до перепроведения. Вот строки его примера :

// Записываем пустые наборы записей, чтобы читать остатки без учета данных в документе и !!!! устанавливаем блокировки по данным, существовавшим ранее !!!!

Движения.ОстаткиНоменклатуры.БлокироватьДляИзменения = Истина; // учли разделитель итогов (см. ИТС)
Движения.Партии.БлокироватьДляИзменения = Истина;
Движения.ОстаткиНоменклатуры.Записать();
Движения.Партии.Записать();