Все денежные поля заказа (сумма без скидки, сумма к оплате, сумма скидки, оплаченная сумма) и статус доступны только для чтения
через API. Их значения — результат пересчёта, а не ввода пользователя.
Логика
Структура заказа-продажи
Структура строки продажи
Две модели скидок и правило взаимоисключения
В заказе есть два способа снизить цену, и они взаимно исключают друг друга:- Скидка (связь) — процентная скидка на весь заказ.
- Дополнительная скидка — фиксированная сумма, вычитаемая из итога.
Построчные скидки (скидка на строку) работают независимо от этого правила и применяются всегда, вместе с любой из двух скидок
заказа.
Как считаются итоги (пересчёт)
Пересчёт запускается при любом создании, изменении или удалении строк, а также при изменении шапки заказа. При изменении шапки новые значения скидок сначала сохраняются, и только потом идёт пересчёт — поэтому сумма к оплате обновляется в том же ответе, без ожидания следующей операции со строками. Он выполняет следующее. Шаг 1. Цена со скидкой по каждой строке. Для каждой строки считается:цена за единицу × количество × (1 − процент скидки строки) × (1 − процент скидки заказа)То есть скидка строки и процентная скидка заказа применяются последовательно, мультипликативно. Результат записывается в поле «цена со скидкой» строки. Шаг 2. Итоги заказа:
- Сумма без скидки = сумма по всем строкам (цена × количество).
- Сумма к оплате = сумма всех построчных цен со скидкой минус дополнительная скидка, но не ниже нуля.
- Оплаченная сумма = сумма всех успешных платежей заказа, не связанных с банковской выпиской.
- Сумма скидки = сумма без скидки − сумма к оплате.
Нижняя граница нуля у суммы к оплате — последний рубеж на случай, когда строки удалили уже после того, как дополнительную
скидку приняли: сама скидка при заведении проверяется на превышение стоимости строк. Итог никогда не уходит в минус, поэтому
и сумма скидки не может превысить стоимость товаров.
Списание товара со склада
После пересчёта итогов система синхронизирует склад по каждой строке.- Признак полной оплаты проверяется строгим равенством: оплаченная сумма в точности равна сумме к оплате. Только при точном совпадении и только для строк с конкретной единицей инвентаря эта единица помечается на складе как проданная.
- Для каждой строки система находит остаток товара на складе по сочетанию группа + склад + контрагент. Если остаток найден, из него берутся закупочные цены единиц (первые N по количеству; если единиц на складе меньше — недостающие дополняются последней ценой; если цен на складе нет вовсе, поле остаётся пустым) и записываются в строку как «цены по единицам». Затем остаток на складе пересохраняется, что пересчитывает доступное количество.
- Если остатка по такому сочетанию нет — строка просто пропускается.
Работа со строками пачками
Строки продажи создаются, обновляются и удаляются пачками отдельными адресами — по одной строке через основной API не работают. После каждой пачки автоматически запускается пересчёт заказа.- Пакетное создание пропускает дубли: строка не добавляется, если в заказе уже есть строка с тем же сочетанием группа + склад + контрагент + единица инвентаря. При создании построчная «цена со скидкой» временно приравнивается к цене продажи и уточняется последующим пересчётом.
- Пакетное обновление переписывает у существующих строк единицу, количество, тариф, скидку, цену и доп. данные. Все переданные строки обязаны принадлежать именно тому заказу, в адресе которого выполняется операция: если хотя бы одна строка относится к другому заказу, запрос целиком отклоняется с ошибкой. После обновления итоги заказа пересчитываются.
- Пакетное удаление удаляет строки, сбрасывает у их единиц дату и цену продажи, затем пересчитывает заказ.
Прибыль
После каждого пересчёта итогов в фоне запускается отдельная задача расчёта прибыли по продаже. Она наполняет отчётные данные (выручка, себестоимость, рентабельность), которые уже подробно описаны в отчётности. Подробнее об отчёте и формулах рентабельности: «Отчётность прикладных модулей».Адреса и доступ
Фильтрация списка доступна по контрагенту (через наличие строк с этим контрагентом), диапазону дат создания, типу платежа,
сотруднику-создателю, клиенту и агенту. Поиск — по имени и телефону клиента, названию и уникальному номеру единицы
инвентаря.
Список продаж показывает только «содержательные» заказы: у которых сумма без скидки, либо сумма к оплате, либо оплаченная сумма
больше нуля. Пустые заказы-черновики без строк в списке не отображаются, хотя физически существуют и доступны по прямой ссылке.
Особенности поведения
Прочие особенности:- Статус «Отменено» объявлен в системе, но нигде не устанавливается автоматически — при пересчёте вычисляется только «Черновик» или «Продано».
- При пакетном создании построчная цена со скидкой временно приравнивается к цене продажи без учёта каких-либо скидок и корректна только после последующего пересчёта.
- Если у складского остатка нет ни одной закупочной цены единицы, поле «цены по единицам» строки остаётся пустым (не дополняется), в отличие от случая, когда цен просто меньше нужного количества.
- Скидка заказа и дополнительная скидка взаимоисключаемы: при положительной дополнительной скидке связь со скидкой обнуляется при сохранении; построчные скидки при этом действуют всегда. Правило учитывает сохранённое значение дополнительной скидки, поэтому изменение одной только процентной скидки её не обнуляет.
- Дополнительная скидка не может превышать стоимость строк заказа, а сумма к оплате не может стать отрицательной — итог ограничен нулём снизу.
- Изменение скидок в шапке пересчитывает сумму к оплате сразу же: пересчёт выполняется после применения новых значений.
- Пакетное обновление строк принимает только строки текущего заказа — идентификаторы чужого заказа приводят к ошибке.
- Оплаченная сумма считается только по успешным платежам, не связанным с банковской выпиской; частично оплаченный заказ остаётся в статусе «Черновик».
- Список продаж скрывает заказы, у которых все денежные итоги равны нулю, хотя такие заказы существуют и доступны по прямой ссылке.
- Удаление строки продажи автоматически пересобирает складской остаток по её группе, складу и контрагенту; пакетное удаление дополнительно сбрасывает дату и цену продажи у затронутых единиц.