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

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


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

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

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

1С Программист
Москва
зарплата от 180 000 руб.
Полный день

Программист 1С
Москва
зарплата от 180 000 руб. до 220 000 руб.
Полный день

Аналитик 1С / Бизнес-аналитик
Нижний Новгород
зарплата от 100 000 руб. до 250 000 руб.
Временный (на проект)

Программист 1С
Москва
зарплата от 250 000 руб.
Полный день