Расчеты с контрагентами

1. 19.04.20 03:34 Сейчас в теме
Здравствуйте. В конфигурации есть два документа для расчета с контрагентами. В первом документе ПриходДенег долг клиента уменьшается, так как происходит внесение денежных средств. Если внесено больше суммы долга, то остаток уходит на аванс. Второй документ увеличивает долг клиента и должен списывать деньги с аванса, если они есть. Проблема в том, что я не знаю, как реализовать списание с аванса, сейчас второй документ является зеркальной копией первого, поэтому не происходит расчет с учетом имеющихся в авансе средств. Хотел бы узнать, где именно второй документ будет отличаться от первого. Код первого документа и выгрузка ниже.


 Процедура ОбработкаПроведения(Отказ, РежимПроведения)
	
	Движения.Взаиморасчеты.Записывать = Истина;
	Если ЗначениеЗаполнено(Проект) Тогда
		
		Движение = Движения.Взаиморасчеты.ДобавитьРасход();
		Движение.Период 	= Дата;
		Движение.Контрагент	= Контрагент;
		Движение.Проект 	= Проект;
		Движение.Сумма 		= СуммаПоДокументу;	
		
		Движения.Взаиморасчеты.БлокироватьДляИзменения = Истина;
		
		Движения.Записать();
		
		// Запрос - нет ли переплаты по проекту после оплаты. 
		// Возможно, сумма оплаты была больше, чем долг контрагента по проекту
		Запрос = Новый Запрос;
		Запрос.Текст = 
		"ВЫБРАТЬ
		|	-ВзаиморасчетыОстатки.СуммаОстаток КАК СуммаПереплаты
		|ИЗ
		|	РегистрНакопления.Взаиморасчеты.Остатки(
		|			&МоментВремениОстатков,
		|			Контрагент = &Контрагент
		|				И Проект = &Проект) КАК ВзаиморасчетыОстатки
		|ГДЕ
		|	ВзаиморасчетыОстатки.СуммаОстаток < 0";
		
		Запрос.УстановитьПараметр("Контрагент"	, Контрагент);
		Запрос.УстановитьПараметр("Проект"	, Проект); 
		
		Запрос.УстановитьПараметр("МоментВремениОстатков", 
		Новый Граница(МоментВремени(), ВидГраницы.Включая));
		
		РезультатЗапроса = Запрос.Выполнить();
		
		
		Если Не РезультатЗапроса.Пустой() Тогда
			
			Движения.Взаиморасчеты.Записывать = Истина;
			
			Выборка  = РезультатЗапроса.Выбрать(); 
			Выборка.Следующий();
			
			СуммаПереплаты = Выборка.СуммаПереплаты;
			Если СуммаПереплаты < СуммаПоДокументу Тогда
				Движение.Сумма = СуммаПоДокументу - СуммаПереплаты;
				

				Движение = Движения.Взаиморасчеты.ДобавитьРасход();
			КонецЕсли;
			
			Движение.Период 	= Дата;
			Движение.Контрагент	= Контрагент;
			Движение.Проект 	= Справочники.Проекты.ПустаяСсылка(); // Аванс
			Движение.Сумма		= СуммаПереплаты;
		КонецЕсли;  
	Иначе
		
		Движения.Взаиморасчеты.Записать();
		
		// Блокировка регистра Взаиморасчеты по контрагенту
		Блокировка = Новый БлокировкаДанных;
		ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Взаиморасчеты");
		ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
		ЭлементБлокировки.УстановитьЗначение("Контрагент", Контрагент);
		Блокировка.Заблокировать(); 
		
		Запрос = Новый Запрос;
		Запрос.Текст = 
		"ВЫБРАТЬ
		|	ВзаиморасчетыОстатки.Проект	КАК Проект,
		|	ВзаиморасчетыОстатки.СуммаОстаток	КАК СуммаОстаток
		|ИЗ
		|	РегистрНакопления.Взаиморасчеты.Остатки(
		|			&МоментВремениОстатков,
		|			Контрагент = &Контрагент
		|			И Проект <> ЗНАЧЕНИЕ(Справочник.Проекты.ПустаяСсылка)  //Аванс
		|) КАК ВзаиморасчетыОстатки
		|
		|УПОРЯДОЧИТЬ ПО
		|    Проект.ДатаОплаты";
		
		Запрос.УстановитьПараметр("Контрагент", Контрагент);
		
		Запрос.УстановитьПараметр("МоментВремениОстатков", МоментВремени());
		
		РезультатЗапроса = Запрос.Выполнить();
		
		СуммаКРаспределению = СуммаПоДокументу;
		
		Если Не РезультатЗапроса.Пустой() Тогда
			
			Выборка = РезультатЗапроса.Выбрать();
			Пока Выборка.Следующий() И СуммаКРаспределению > 0 Цикл
				
				СуммаКСписанию = Мин(СуммаКРаспределению, Выборка.СуммаОстаток);
				
				// Уменьшение долга контрагента по проекту из остатков
				Движение = Движения.Взаиморасчеты.ДобавитьРасход();
				Движение.Период 	= Дата;
				Движение.Контрагент	= Контрагент;
				Движение.Проект 	= Выборка.Проект;
				Движение.Сумма		= СуммаКСписанию;
				
				СуммаКРаспределению = СуммаКРаспределению - СуммаКСписанию;
			КонецЦикла;  
		КонецЕсли;
		
		// Если после оплаты долгов остались деньги, их нужно учесть как аванс
		Если СуммаКРаспределению > 0 Тогда
			
			//  Отнесение на аванс остатка денег после распределения по проектам
			// (увеличивает долг предприятия перед контрагентом)
			Движение = Движения.Взаиморасчеты.ДобавитьРасход();
			Движение.Период 	= Дата;
			Движение.Контрагент	= Контрагент;
			Движение.Проект 	= Справочники.Проекты.ПустаяСсылка(); // Аванс
			Движение.Сумма		= СуммаКРаспределению;
		КонецЕсли; 
	КонецЕсли; 
КонецПроцедуры
Показать
Прикрепленные файлы:
st3.dt
Найденные решения
6. karamazoff 63 19.04.20 19:34 Сейчас в теме
(5)А ваш первый док проверяет переплату только по 1-му проекту? ведь может быть как, что оплатили по контрагенту 10000 а него висит долг на 5 разных мелких проектах по 1000, тогда закрыть надо все 5 проектов и еще 5000 повесить на аванс контрагента...
с обратной ситуацией (зачет аванса) проще, там надо взять остатки по контрагенту с пустым проектом (аванс), проверить, хватает ли их для погашения 2-го документа и списать с аванса сумму всю или частично. Либо я что-то не так понял....
	Движения.Взаиморасчеты.Записывать = Истина;
		
		// Запрос - нет ли переплаты по проекту после оплаты. 
		// Возможно, сумма оплаты была больше, чем долг контрагента по проекту
		Запрос = Новый Запрос;
		Запрос.Текст = 
			"ВЫБРАТЬ
			|	ВзаиморасчетыОстатки.Контрагент КАК Контрагент,
			|	ВзаиморасчетыОстатки.Проект КАК Проект,
			|	-ВзаиморасчетыОстатки.СуммаОстаток КАК СуммаОстаток
			|ИЗ
			|	РегистрНакопления.Взаиморасчеты.Остатки(
			|			&МоментВремениОстатков,
			|			Контрагент = &Контрагент
			|				И Проект = &Проект) КАК ВзаиморасчетыОстатки
			|ГДЕ
			|	ВзаиморасчетыОстатки.СуммаОстаток < 0";
		
			Запрос.УстановитьПараметр("Контрагент"	, Контрагент);
			Запрос.УстановитьПараметр("Проект"	, Справочники.Проекты.ПустаяСсылка()); 
			
			Запрос.УстановитьПараметр("МоментВремениОстатков", 
			Новый Граница(МоментВремени(), ВидГраницы.Включая));
			
			РезультатЗапроса = Запрос.Выполнить().Выбрать();
			Если РезультатЗапроса.Следующий() тогда 

				Если  РезультатЗапроса.СуммаОстаток >= СуммаПоДокументу  тогда //сумму расхода закрывет аванс
					Движение = Движения.Взаиморасчеты.ДобавитьПриход(); //добавим задолженность
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Проект;
					Движение.Сумма 		= СуммаПоДокументу;
					
					Движение = Движения.Взаиморасчеты.ДобавитьРасход(); //закроем задолженность авансом
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Проект;
					Движение.Сумма 		= СуммаПоДокументу;					
					
					
					Движение = Движения.Взаиморасчеты.ДобавитьПриход();  //уменьшим аванс на сумму документа
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Справочники.Проекты.ПустаяСсылка();
					Движение.Сумма 		= СуммаПоДокументу;
									
					
				иначеЕсли  РезультатЗапроса.СуммаОстаток < СуммаПоДокументу тогда //сумма расхода больше аванса и частично пойдет на расход
					Движение = Движения.Взаиморасчеты.ДобавитьПриход(); //добавим задолженность
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Проект;
					Движение.Сумма 		= СуммаПоДокументу;
					
					Движение = Движения.Взаиморасчеты.ДобавитьРасход(); //закроем задолженность частично авансом
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Проект;
					Движение.Сумма 		= -РезультатЗапроса.СуммаОстаток;					
					
					
					Движение = Движения.Взаиморасчеты.ДобавитьПриход();  //спишем аванс полностью
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Справочники.Проекты.ПустаяСсылка();
					Движение.Сумма 		= -РезультатЗапроса.СуммаОстаток;
	
				КонецЕсли;	
			иначе	//это полностью задолженнность аванса нет
					Движение = Движения.Взаиморасчеты.ДобавитьПриход();
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Проект;
					Движение.Сумма 		= СуммаПоДокументу;					
			КонецЕсли;	
			Движения.Взаиморасчеты.Записать();
Показать
Остальные ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
2. karamazoff 63 19.04.20 11:55 Сейчас в теме
Я правильно понимаю, что в приходе денег проект может быть не указан (тогда все пойдет на будущие авансы) а в расходной накладной проект обязателен?указан?
3. sample_text 19.04.20 15:35 Сейчас в теме
(2) Да, это так. Дело в том, что в случае неуказанного проекта, этот аванс должен автоматически погашать долг
4. karamazoff 63 19.04.20 16:59 Сейчас в теме
для разброса оплаты по долгам как-то так

		Движения.Взаиморасчеты.Записывать = Истина;		
		// Запрос - нет ли переплаты по проекту после оплаты. 
		// Возможно, сумма оплаты была больше, чем долг контрагента по проекту
		Запрос = Новый Запрос;
		Запрос.Текст = 
			"ВЫБРАТЬ
			|	ВзаиморасчетыОстатки.Контрагент КАК Контрагент,
			|	ВзаиморасчетыОстатки.Проект КАК Проект,
			|	ВзаиморасчетыОстатки.СуммаОстаток КАК СуммаОстаток,
			|	0 КАК СуммаОплаты
			|ИЗ
			|	РегистрНакопления.Взаиморасчеты.Остатки(
			|			&МоментВремениОстатков,
			|			Контрагент = &Контрагент) КАК ВзаиморасчетыОстатки			
			|ГДЕ
			|	ВзаиморасчетыОстатки.СуммаОстаток > 0";
		
			Запрос.УстановитьПараметр("Контрагент"	, Контрагент);
			
			Запрос.УстановитьПараметр("МоментВремениОстатков", 
			Новый Граница(МоментВремени(), ВидГраницы.Включая));
			
			СуммаКпогашению = СуммаПоДокументу;
			//подготовим таблицу оплат
			Табл = Запрос.Выполнить().Выгрузить();
			Если НЕ Проект.Пустая() тогда     //впервую очередь оплатим указанный проект
				отбор = новый структура;
				отбор.Вставить("Проект",Проект);
				масс = Табл.НайтиСтроки(отбор);
				Если не масс.Количество() = 0 тогда
					стр = масс.Получить(0);
					Если стр.СуммаОстаток >= СуммаКпогашению тогда //израсходовали всю сумму
						стр.СуммаОплаты = СуммаКпогашению;
						СуммаКпогашению = 0;
					иначе	 //остался оплата на другие проекты
						стр.СуммаОплаты = стр.СуммаОстаток;
						СуммаКпогашению = СуммаКпогашению - стр.СуммаОстаток;
					КонецЕсли;
				КонецЕсли;	
			КонецЕсли;
			
			Если СуммаКпогашению>0 тогда   //оплачиваем другие проекты
				для каждого стр из Табл цикл
					Если стр.СуммаОплаты > 0 тогда  //это по нашему проекту
						продолжить;
					КонецЕсли;
					
					Если стр.СуммаОстаток >= СуммаКпогашению тогда
						стр.СуммаОплаты = СуммаКпогашению;
						СуммаКпогашению = 0;
						прервать;
					иначе	
						стр.СуммаОплаты = стр.СуммаОстаток;
						СуммаКпогашению = СуммаКпогашению - стр.СуммаОстаток;
					КонецЕсли;					
				КонецЦикла;
			КонецЕсли;	
			
			для каждого стр из Табл цикл
				Если стр.СуммаОплаты>0 тогда
					Движение = Движения.Взаиморасчеты.ДобавитьРасход();
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= стр.Проект;
					Движение.Сумма 		= стр.СуммаОплаты;				
				КонецЕсли;	
			КонецЦикла;	
			
				Если СуммаКпогашению>0 тогда   //остался аванс вешаем его на пустой проект
					Движение = Движения.Взаиморасчеты.ДобавитьРасход(); 
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Справочники.Проекты.ПустаяСсылка();
					Движение.Сумма 		= СуммаКпогашению;						
				КонецЕсли;							
			
			Движения.Взаиморасчеты.Записать();			
			
Показать
5. sample_text 19.04.20 18:45 Сейчас в теме
(4) Может быть я неверно выразился, но суть в том, что первый документ работает корректно, понижает сумму задолженности, и если сумма в документе больше, то выводит ее в аванс, не распределяя деньги, так как долг полностью погашен. В случае аванса появляется пустое значение в поле проект. Но если запустить второй документ, повышающий сумму задолженности, то он не учитывает аванс. Допустим, есть аванс 500 рублей. Сейчас происходит так: Приходит увеличение долга со второго документа на 700 рублей, потом приходит уменьшение долга на 500, а затем на 1000. Расчет игнорирует аванс в 500 рублей, и выводит в аванс 800 рублей из 1500. В нужном виде должно получаться так: Есть аванс 500 рублей, приходит увеличение долга со второго документа на 700 рублей, после чего приходит уменьшение долга на 500, в аванс поступает 300 рублей. Если аванс будет учитываться, то долг при проведении второго документа заберет 500 рублей из аванса и будет равен 200 рублей, а не 700 без его учета. Суть в том, что я не знаю что надо сделать во втором документе, чтобы он проверял авансы и часть долга сразу списывалась.
6. karamazoff 63 19.04.20 19:34 Сейчас в теме
(5)А ваш первый док проверяет переплату только по 1-му проекту? ведь может быть как, что оплатили по контрагенту 10000 а него висит долг на 5 разных мелких проектах по 1000, тогда закрыть надо все 5 проектов и еще 5000 повесить на аванс контрагента...
с обратной ситуацией (зачет аванса) проще, там надо взять остатки по контрагенту с пустым проектом (аванс), проверить, хватает ли их для погашения 2-го документа и списать с аванса сумму всю или частично. Либо я что-то не так понял....
	Движения.Взаиморасчеты.Записывать = Истина;
		
		// Запрос - нет ли переплаты по проекту после оплаты. 
		// Возможно, сумма оплаты была больше, чем долг контрагента по проекту
		Запрос = Новый Запрос;
		Запрос.Текст = 
			"ВЫБРАТЬ
			|	ВзаиморасчетыОстатки.Контрагент КАК Контрагент,
			|	ВзаиморасчетыОстатки.Проект КАК Проект,
			|	-ВзаиморасчетыОстатки.СуммаОстаток КАК СуммаОстаток
			|ИЗ
			|	РегистрНакопления.Взаиморасчеты.Остатки(
			|			&МоментВремениОстатков,
			|			Контрагент = &Контрагент
			|				И Проект = &Проект) КАК ВзаиморасчетыОстатки
			|ГДЕ
			|	ВзаиморасчетыОстатки.СуммаОстаток < 0";
		
			Запрос.УстановитьПараметр("Контрагент"	, Контрагент);
			Запрос.УстановитьПараметр("Проект"	, Справочники.Проекты.ПустаяСсылка()); 
			
			Запрос.УстановитьПараметр("МоментВремениОстатков", 
			Новый Граница(МоментВремени(), ВидГраницы.Включая));
			
			РезультатЗапроса = Запрос.Выполнить().Выбрать();
			Если РезультатЗапроса.Следующий() тогда 

				Если  РезультатЗапроса.СуммаОстаток >= СуммаПоДокументу  тогда //сумму расхода закрывет аванс
					Движение = Движения.Взаиморасчеты.ДобавитьПриход(); //добавим задолженность
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Проект;
					Движение.Сумма 		= СуммаПоДокументу;
					
					Движение = Движения.Взаиморасчеты.ДобавитьРасход(); //закроем задолженность авансом
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Проект;
					Движение.Сумма 		= СуммаПоДокументу;					
					
					
					Движение = Движения.Взаиморасчеты.ДобавитьПриход();  //уменьшим аванс на сумму документа
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Справочники.Проекты.ПустаяСсылка();
					Движение.Сумма 		= СуммаПоДокументу;
									
					
				иначеЕсли  РезультатЗапроса.СуммаОстаток < СуммаПоДокументу тогда //сумма расхода больше аванса и частично пойдет на расход
					Движение = Движения.Взаиморасчеты.ДобавитьПриход(); //добавим задолженность
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Проект;
					Движение.Сумма 		= СуммаПоДокументу;
					
					Движение = Движения.Взаиморасчеты.ДобавитьРасход(); //закроем задолженность частично авансом
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Проект;
					Движение.Сумма 		= -РезультатЗапроса.СуммаОстаток;					
					
					
					Движение = Движения.Взаиморасчеты.ДобавитьПриход();  //спишем аванс полностью
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Справочники.Проекты.ПустаяСсылка();
					Движение.Сумма 		= -РезультатЗапроса.СуммаОстаток;
	
				КонецЕсли;	
			иначе	//это полностью задолженнность аванса нет
					Движение = Движения.Взаиморасчеты.ДобавитьПриход();
					Движение.Период 	= Дата;
					Движение.Контрагент	= Контрагент;
					Движение.Проект 	= Проект;
					Движение.Сумма 		= СуммаПоДокументу;					
			КонецЕсли;	
			Движения.Взаиморасчеты.Записать();
Показать
7. sample_text 19.04.20 20:46 Сейчас в теме
(6) Впринципе, почти полностью подходит. Если что, то на этой основе я уже смогу выровнять результаты. Спасибо большое, вы мне очень помогли
8. sample_text 24.04.20 17:22 Сейчас в теме
(6)Как можно вместо пустого поля вставить ссылку на документ? Допустим, у меня та же расходная накладная и приход денег, но в регистре остатков вместо проекта находится измерение ДокументРасчета, куда должна попадать ссылка на документ. Так, вместо пустого проекта должна подставляться ссылка на текущий документ ПриходДенег. Вопрос в том, какого типа должно быть измерение ДокументРасчета и как установить параметр, работающий аналогично пустой ссылке, но при этом передающий ссылку на документ?
Оставьте свое сообщение
Вопросы с вознаграждением