Учебный курс: Подготовка на 1С:Специалист по платформе 1С:Предприятие 8.3

Задачи оперативного учета – тема № 10:
Как реализовать ведение взаиморасчетов в разрезе проектов на экзамене

Ранее для нашей задачи мы уже разработали учетную схему, пояснили некоторые нюансы решения, а также создали все необходимые объекты конфигурации. В данном разделе разработаем алгоритмы проведения документов и протестируем наше решение.

Разработка алгоритмов проведения документов

Проведение документа «Приход денег»

Процедуру ОбработкаПроведения в модуле объекта создадим и заполним вручную. Для создания процедуры можно выбрать ее имя из списка на панели инструментов:

Рисунок 1 – Создание процедура ОбработкаПроведения

Рисунок 1 – Создание процедура ОбработкаПроведения

Готовая процедура ОбработкаПроведения будет выглядеть следующим образом:

Процедура ОбработкаПроведения(Отказ, РежимПроведения) // 1. Установка признака записи движений регистра Взаиморасчеты Движения.Взаиморасчеты.Записывать = Истина; Если ЗначениеЗаполнено(Проект) Тогда // 2. Если проект выбран, погасим долг клиента по проекту в пределах суммы оплаты. // Остаток денег отнесем на аванс // 3. Уменьшение долга контрагента по проекту из документа на всю сумму оплаты Движение = Движения.Взаиморасчеты.ДобавитьРасход(); Движение.Период = Дата; Движение.Контрагент = Контрагент; Движение.Проект = Проект; Движение.Сумма = СуммаПоДокументу; // 4. Установка режима блокировки при записи движений регистра Взаиморасчеты Движения.Взаиморасчеты.БлокироватьДляИзменения = Истина; // 5. Запись данных регистра Взаиморасчеты с установкой управляемой блокировки Движения.Записать(); // 6. Запрос - нет ли переплаты по проекту после оплаты. // Возможно, сумма оплаты была больше, чем долг контрагента по проекту Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | -ВзаиморасчетыОстатки.СуммаОстаток КАК СуммаПереплаты |ИЗ | РегистрНакопления.Взаиморасчеты.Остатки( | &МоментВремениОстатков, | Контрагент = &Контрагент И Проект = &Проект | ) КАК ВзаиморасчетыОстатки |ГДЕ | ВзаиморасчетыОстатки.СуммаОстаток < 0"; Запрос.УстановитьПараметр("Контрагент" , Контрагент); Запрос.УстановитьПараметр("Проект" , Проект); // 7. Определение момента времени для получения остатков Запрос.УстановитьПараметр("МоментВремениОстатков", Новый Граница(МоментВремени(), ВидГраницы.Включая)); РезультатЗапроса = Запрос.Выполнить(); // 8. Если запрос не пустой, значит, есть переплата, которую нужно учесть как аванс Если Не РезультатЗапроса.Пустой() Тогда // 9. Повторная установка признака записи движений регистра Взаиморасчеты Движения.Взаиморасчеты.Записывать = Истина; Выборка = РезультатЗапроса.Выбрать(); Выборка.Следующий(); СуммаПереплаты = Выборка.СуммаПереплаты; // 10. Если у контрагента по проекту была задолженность, // то сумма переплаты будет меньше, чем сумма оплаты. // В этом случае корректируем сумму погашения долга на сумму переплаты // и добавляем новое движение для отнесения переплаты на аванс. // Если же у контрагента не было долга по проекту, то вся сумма // переплаты будет отнесена на аванс. В этом случае движения // по погашению долга по проекту не будет, и для аванса // используем ранее созданное движение, перезаписывая его данные Если СуммаПереплаты < СуммаПоДокументу Тогда Движение.Сумма = СуммаПоДокументу - СуммаПереплаты; // 11. Новое движение - отнесение переплаты на аванс Движение = Движения.Взаиморасчеты.ДобавитьРасход(); КонецЕсли; // 12. Заполнение движения - отнесение переплаты на аванс Движение.Период = Дата; Движение.Контрагент = Контрагент; Движение.Проект = Справочники.Проекты.ПустаяСсылка(); // Аванс Движение.Сумма = СуммаПереплаты; КонецЕсли; Иначе // 13. Проект в документе не указан. // Задолженности контрагента по проектам погашаются в порядке их дат оплаты, // а остаток платежа относится на аванс // 14. Удаление старых движений регистра Взаиморасчеты Движения.Взаиморасчеты.Записать(); // 15. Блокировка регистра Взаиморасчеты по контрагенту (по всем проектам) Блокировка = Новый БлокировкаДанных; ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Взаиморасчеты"); ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный; ЭлементБлокировки.УстановитьЗначение("Контрагент", Контрагент); Блокировка.Заблокировать(); // 16. Текст запроса - получение остатков задолженностей по проектам для контрагента Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | ВзаиморасчетыОстатки.Проект КАК Проект, | ВзаиморасчетыОстатки.СуммаОстаток КАК СуммаОстаток |ИЗ | РегистрНакопления.Взаиморасчеты.Остатки( | &МоментВремениОстатков, | Контрагент = &Контрагент | И Проект <> ЗНАЧЕНИЕ(Справочник.Проекты.ПустаяСсылка) //Аванс |) КАК ВзаиморасчетыОстатки | |УПОРЯДОЧИТЬ ПО | Проект.ДатаОплаты"; Запрос.УстановитьПараметр("Контрагент", Контрагент); // 17. Определение момента времени для получения остатков Запрос.УстановитьПараметр("МоментВремениОстатков", МоментВремени()); РезультатЗапроса = Запрос.Выполнить(); // 18. Распределение суммы из документа по долгам по проектам СуммаКРаспределению = СуммаПоДокументу; Если Не РезультатЗапроса.Пустой() Тогда Выборка = РезультатЗапроса.Выбрать(); Пока Выборка.Следующий() И СуммаКРаспределению > 0 Цикл СуммаКСписанию = Мин(СуммаКРаспределению, Выборка.СуммаОстаток); // 19. Уменьшение долга контрагента по проекту из остатков Движение = Движения.Взаиморасчеты.ДобавитьРасход(); Движение.Период = Дата; Движение.Контрагент = Контрагент; Движение.Проект = Выборка.Проект; Движение.Сумма = СуммаКСписанию; СуммаКРаспределению = СуммаКРаспределению - СуммаКСписанию; КонецЦикла; КонецЕсли; // 20. Если после оплаты долгов остались деньги, их нужно учесть как аванс Если СуммаКРаспределению > 0 Тогда // 21. Отнесение на аванс остатка денег после распределения по проектам // (увеличивает долг предприятия перед контрагентом) Движение = Движения.Взаиморасчеты.ДобавитьРасход(); Движение.Период = Дата; Движение.Контрагент = Контрагент; Движение.Проект = Справочники.Проекты.ПустаяСсылка(); // Аванс Движение.Сумма = СуммаКРаспределению; КонецЕсли; КонецЕсли; КонецПроцедуры

Описание основных действий

В зависимости от того, указан ли проект в документе, проведение будет выполняться по-разному.

Проект в документе указан (пп. 2 – 12)

Если проект в документе указан, то согласно условию нужно погасить задолженность по этому проекту, а остаток денег зачесть как аванс. Проект, на который нужно отнести оплату, заранее известен, поэтому можно обойтись без предварительного запроса к остаткам регистра для получения проектов, по которым имеются задолженности. В данном случае можно использовать «новую» методику проведения: сначала сделать движение по этому проекту, а затем проверить состояние системы и при необходимости внести корректировку (напомним, на экзамене, если есть такая возможность, следует использовать «новую» методику проведения).

Порядок действий следующий.

Формирование движения по оплате по проекту на всю сумму из документа (пп. 3 – 5)

Выполняется оплата по проекту на всю сумму из документа, независимо от того, какая сумма задолженности в действительности числится по данному проекту.

Запись движения с наложением блокировки (пп. 4, 5)

Алгоритм здесь реализует проведение по «новой» методике: сначала выполняется действие, потом выполняется проверка. Причем и проверка (п. 6), и корректировочные действия (пп. 10 – 12) выполняются по тем же объектам аналитики, по которым было сделано движение (п. 3). Поэтому для предотвращения некорректной работы алгоритма требуется блокировать доступ других пользователей к этим объектам до окончания транзакции.

Проверка: не появилась ли переплата (пп. 6 – 8)

Проверяется, не образовалась ли переплата по проекту после оплаты задолженности по проекту. Технически переплата по проекту – это отрицательный остаток регистра «Взаиморасчеты» по выбранным контрагенту и проекту на момент времени непосредственно за моментом времени документа; именно эти данные и выбираются в запросе.

Если есть переплата, корректировка суммы оплаты по проекту и отнесение переплаты на аванс (пп. 8 – 12)

Запрос (п. 6) построен таким образом, чтобы обнаружить ошибочную ситуацию: переплату по проекту. Если запрос вернул какой-то результат, значит, оплата превысила долг по проекту. Сумма переплаты известна – она выбрана в результате запроса. Поэтому в этом случае сумма оплаты по проекту уменьшается на сумму переплаты, а сама сумма переплаты записывается как аванс.

Движение по авансу лишь увеличивает доступную сумму аванса; далее сумма аванса никак в данной процедуре не используется. Поэтому никакой конкуренции за ресурсы тут не будет, и блокировка по авансу не требуется.

Заметим, что в переменной Движение отражается движение, которым изначально была выполнена оплата по проекту (п. 3). Это первый элемент коллекции движений документа по регистру «Взаиморасчеты». После записи движений в базу (п. 5) это движение никуда не делось, и все его данные сохранились. Поэтому для корректировки суммы оплаты по проекту достаточно только изменить сумму у существующего движения (п. 11). При завершении процедуры произойдет повторная запись движений документа (п. 9), и сумма оплаты по проекту станет правильной.

Заметим также, что возможна ситуация, когда по указанному в документе проекту вообще нет задолженности. В этом случае погашать долг по проекту не требуется, так как сумма в движении была бы нулевой; нужно сразу отнести на аванс всю сумму из документа. В этом случае для аванса не добавляется новое движение, а перезаписывается существующее (пп. 10, 11)

Проект в документе не указан (пп. 13 – 21)

Если проект в документе не указан, то согласно условию нужно погасить задолженности по всем проектам контрагента в пределах суммы платежа (причем погашаться задолженности должны в порядке дат оплаты из проектов), а остаток должен быть зачтен как аванс. В этом случае ни проекты, по которым имеются задолженности, ни суммы задолженностей заранее не известны, и без предварительной выборки этих данных из регистра не обойтись. Поэтому в данном случае будет использована «старая» методика проведения, аналогичная той, которая применяется при списании себестоимости при партионном учете (подробнее см. в разделе 17. Использование обработки проведения для документа «Расходная накладная»).

Порядок действий следующий.

Удаление движений документа (п. 14)

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

Блокировка записей регистра «Взаиморасчеты» по контрагенту из документа (п. 15)

Устанавливается блокировка записей регистра «Взаиморасчеты» по контрагенту из документа, то есть фактически по всем проектам, связанным с контрагентом.

Алгоритм здесь реализует проведение по «старой» методике: сначала выбираются остатки, затем происходит распределение по остаткам суммы из документа. Заранее не известно, какие проекты будут участвовать в движениях, поэтому блокируются все проекты для контрагента. Также необходимо обеспечить, чтобы данные по остаткам задолженностей по проектам не были изменены другими пользователями (от момента получения данных об остатках задолженностей до окончания их погашения и отнесения остатка суммы платежа на аванс). Именно поэтому эта блокировка накладывается еще до получения данных запросом (п. 16).

Получение данных о проектах, по которым есть задолженности (пп. 16, 17)

Запросом выбираются все проекты, по которым у контрагента есть задолженности на начало момента времени документа. Причем проекты будут получаться из выборки в порядке возрастания их дат оплаты – так задано в запросе. Пустая ссылка на справочник «Проекты», которая в нашей схеме обозначает аванс, исключена из результатов запроса, так как требуется получить именно долги по проектам для дальнейшего их погашения.

Распределение суммы платежа по проектам с задолженностями (пп. 18, 19)

Пока не закончится сумма платежа из документа, она будет распределяться по тем проектам, по которым у контрагента есть задолженности. Так как в запросе (п. 16) задано упорядочивание проектов по датам оплаты, погашаться задолженности по проектам будут в порядке их дат оплаты.

Отнесение остатка суммы платежа на аванс (п. 20)

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

К сожалению, у Вас недостаточно прав для дальнейшего просмотра.

Если Вы приобрели курс, но еще не активировали токен — пожалуйста, активируйте доступ по инструкциям, высланным на Ваш email после покупки.

Если Вы не залогинены на сайте — залогиньтесь, вернитесь на эту страницу и обновите ее.

Если Вы залогинены, у Вас активирован токен доступа, но Вы все равно видите эту запись — напишите нам на e-mail поддержки.

Комментарии закрыты