gifts2017

Распределение оплаты по товарам

Опубликовал Трактор Трактор (Трактор) в раздел Программирование - Практика программирования

Учебная задача. Оплата приходит по заказу. Требуется запросом распределить её по товарам.
Практическая задача была сложнее. Упростил специально для иллюстрации.

Сначала собираем в одну таблицу заказы и товары. Затем ОБЪЕДИНТЬ ВСЕ с оплатами. Потом намазываем оплату на товар.
Подобный подход можно использовать для распределения, например,
  • по партиям при списании количества товара
  • оплаты по заказам, если оплата пришла по договору вцелом
Минусом данного решения является ресурсоёмкость запроса. За основу взято классическое решение запроса с нарастающим итогом. К нему добавлен запрос, преобразующий нарастающий итог в текущее сальдо.

// Заказ собираем в одну таблицу с колонками "Заказ", "Товар", "СуммаЗаказано", "СуммаОплачено"
// колонку "СуммаОплачено" в запросе по заказам заполняем нулями
ВЫБРАТЬ
    "Заказ № 1" КАК заказ,
    "сапоги гусарские" КАК товар,
    100 КАК суммаЗаказано,
    0 КАК СуммаОплачено
ПОМЕСТИТЬ табКоличеств

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Заказ № 1",
    "валенки Здоровье",
    50,
    0

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Заказ № 1",
    "туфельки Золушка",
    60,
    0

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Заказ № 222",
    "сапоги гусарские",
    200,
    0

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Заказ № 222",
    "туфельки Золушка",
    20,
    0

ОБЪЕДИНИТЬ ВСЕ

// К запросу по заказам снизу добавляем суммы оплат. При этом колонки Товар и СуммаЗаказано заполняем пустыми значениями.
// но не просто пустыми, а такими, чтобы при сортировке становились ДО значений из таблицы заказов.
// Для колонки Товар в реальном запросе следует использовать Значение(Справочник.Номенклатура.ПустаяСсылка), для колонки Сумма следует использовать 0
ВЫБРАТЬ
    "Заказ № 1",
    "",
    0,
    175

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Заказ № 222",
    "",
    0,
    210
;

////////////////////////////////////////////////////////////////////////////////
// Намазываем оплату на товары. Получаем сальдо нарастающим итогом.
ВЫБРАТЬ РАЗЛИЧНЫЕ
    табКоличеств.заказ,
    табКоличеств.товар,
    МИНИМУМ(табКоличеств.суммаЗаказано) КАК суммаЗаказано,
    СУММА(табКоличеств1.суммаЗаказано) КАК суммаЗаказаноНарастающим,
    МИНИМУМ(табКоличеств.СуммаОплачено) КАК суммаОплачено,
    СУММА(табКоличеств1.суммаЗаказано - табКоличеств1.СуммаОплачено) КАК СальдоОплаченоНарастающим
ПОМЕСТИТЬ СальдоНарастающим
ИЗ
    табКоличеств КАК табКоличеств
        ЛЕВОЕ СОЕДИНЕНИЕ табКоличеств КАК табКоличеств1
        ПО табКоличеств.заказ = табКоличеств1.заказ
            И табКоличеств.товар >= табКоличеств1.товар

СГРУППИРОВАТЬ ПО
    табКоличеств.заказ,
    табКоличеств.товар
;

////////////////////////////////////////////////////////////////////////////////
// Превращаем нарастающее сальдо в простое. При этом получем в колонке СальдоПотовару 0 - нет задолженности, число - сумма задолженности
ВЫБРАТЬ
    СальдоНарастающим.заказ,
    СальдоНарастающим.товар,
    СальдоНарастающим.суммаЗаказано,
    ВЫБОР
        КОГДА СальдоНарастающим.СальдоОплаченоНарастающим > 0
            ТОГДА ВЫБОР
                    КОГДА СальдоНарастающим.СальдоОплаченоНарастающим > СальдоНарастающим.суммаЗаказано
                        ТОГДА СальдоНарастающим.суммаЗаказано
                    ИНАЧЕ СальдоНарастающим.СальдоОплаченоНарастающим
                КОНЕЦ
        ИНАЧЕ 0
    КОНЕЦ КАК СальдоПотовару
ИЗ
    СальдоНарастающим КАК СальдоНарастающим

УПОРЯДОЧИТЬ ПО
    СальдоНарастающим.заказ,
    СальдоНарастающим.товар

О сути времени

См. также

Подписаться Добавить вознаграждение

Комментарии

1. OBEH (OBEH) 06.08.14 00:53
А можно алгоритм наоборот?
Например, на документ реализации брошена сумма. Эту сумму отнять от каждой позиции табличной части пропорционально стоимости в каждой строке.
2. Антон Стеклов (asved.ru) 06.08.14 08:31
О сути времени


Разъясните, пожалуйста, какое отношение к изложенному в статье имеет секта пургеняна и зачем вы ее пиарите?
3. Трактор Трактор (Трактор) 06.08.14 10:56
А можно алгоритм наоборот?

(1) OBEH, не совсем наоборот. Просто немного другой способ намазывания. Вот прикинул как может выглядеть запрос. Ошибки округления в запросе решать не стал, поэтому это заготовка, а не готовый ответ.
// Заказ собираем в одну таблицу с колонками "Заказ", "Товар", "СуммаЗаказано", "СуммаОплачено"
// колонку "СуммаОплачено" в запросе по заказам заполняем нулями
ВЫБРАТЬ
    "Заказ № 1" КАК заказ,
    "сапоги гусарские" КАК товар,
    100 КАК суммаЗаказано,
    0 КАК СуммаОплачено
ПОМЕСТИТЬ табКоличеств

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Заказ № 1",
    "валенки Здоровье",
    50,
    0

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Заказ № 1",
    "туфельки Золушка",
    60,
    0

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Заказ № 222",
    "сапоги гусарские",
    200,
    0

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Заказ № 222",
    "туфельки Золушка",
    20,
    0

ОБЪЕДИНИТЬ ВСЕ

// К запросу по заказам снизу добавляем суммы оплат. При этом колонки Товар и СуммаЗаказано заполняем пустыми значениями.
// но не просто пустыми, а такими, чтобы при сортировке становились ДО значений из таблицы заказов.
// Для колонки Товар в реальном запросе следует использовать Значение(Справочник.Номенклатура.ПустаяСсылка), для колонки Сумма следует использовать 0
ВЫБРАТЬ
    "Заказ № 1",
    "",
    0,
    175

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Заказ № 222",
    "",
    0,
    210
;
// добавляем в начальную таблицу колонку ВсегоСуммаПоЗаказу
// и в каждую строку прописываем ВсегоСуммаЗаказано и суммаОплачено, которая упала на заказ
ВЫБРАТЬ
	табКоличеств.заказ,
	табКоличеств.товар,
	табКоличеств.суммаЗаказано,
	ВсегоЗаказано.суммаОплачено,
	ВсегоЗаказано.ВсегоСуммаЗаказано
Поместить ЗаказыСИтоговымиСуммами
ИЗ
	табКоличеств КАК табКоличеств
		ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
			табКоличеств.заказ КАК заказ,
			СУММА(табКоличеств.суммаОплачено) КАК суммаОплачено,
			СУММА(табКоличеств.суммаЗаказано) КАК ВсегоСуммаЗаказано
		ИЗ
			табКоличеств КАК табКоличеств
		
		СГРУППИРОВАТЬ ПО
			табКоличеств.заказ) КАК ВсегоЗаказано
		ПО (ВсегоЗаказано.заказ = табКоличеств.заказ)
Где табКоличеств.товар <> ""
;
// теперь у нас в каждой строке есть сумма заказно по Товару, сумма оплаты по Заказу и сумма Заказа
Выбрать
	ЗаказыСИтоговымиСуммами.заказ,
	ЗаказыСИтоговымиСуммами.товар,
	ЗаказыСИтоговымиСуммами.суммаЗаказано,
	ЗаказыСИтоговымиСуммами.суммаОплачено,
	ЗаказыСИтоговымиСуммами.ВсегоСуммаЗаказано,
	// сумму заказано по Товару делим на сумму всего заказа получаем долю товара в заказе
	// затем умножаем на сумму оплаты. Получим сумму оплаты по товару, пропорциональную доле стоимости товара в заказе.
	ЗаказыСИтоговымиСуммами.суммаЗаказано / ЗаказыСИтоговымиСуммами.ВсегоСуммаЗаказано *
	// При этом учитываем, что оплата может оказаться больше суммы заказа. В этом случае считаем, что оплачен только заказ
	Выбор Когда ЗаказыСИтоговымиСуммами.суммаОплачено > ЗаказыСИтоговымиСуммами.ВсегоСуммаЗаказано
		Тогда ЗаказыСИтоговымиСуммами.ВсегоСуммаЗаказано
		Иначе ЗаказыСИтоговымиСуммами.суммаОплачено
	Конец КАК ОплаченоЗаТовар
	
ИЗ ЗаказыСИтоговымиСуммами как ЗаказыСИтоговымиСуммами
	
Упорядочить по 
	ЗаказыСИтоговымиСуммами.заказ,
	ЗаказыСИтоговымиСуммами.товар
...Показать Скрыть
4. haz haz (hazd) 12.10.14 01:39
Все подробно написано, по полочкам разложено. Спасибо.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа