feat: Эпик 14 (14.1+14.5) — единый явный путь отгрузки (самовывоз/экспедитор+ТТН) #50
Reference in New Issue
Block a user
Delete Branch "feat/E14-explicit-shipment"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Эпик 14 (доработки пилота 2026-05-30): единый явный путь отгрузки
Закрывает разрыв «спека ↔ реализация» в Эпике 5: Story 5.1 требует явный выбор варианта доставки (самовывоз / экспедитор+ТТН) для индивидуальных и пакетных заказов, но реализация навязывала индивидуальным Вариант А и оставляла страницу подготовки отгрузки read-only.
Story 14.1 — backend (
controller)acceptIndividualбольше не авто-формирует партию Варианта А. Теперь синтезируется только заявка (cycle) в статусеACCEPTED; партию поставщик формирует явно черезmarketplaceCreateShipmentс выбором варианта — единый путь с пакетными заказами.ACCEPTEDдо явного формирования отгрузки.shipmentCreate), обновлён spec и комментарий forward-guard.tsc --noEmitзелёный.Story 14.5 — desktop (
desktop)marketplaceCreateShipment.lib/shipmentFormation.ts. Refresh унифицирован на общийRefreshButton. ESLint--max-warnings 0зелёный.Вне scope этого PR (следующие PR Эпика 14)
TTNPrintPreview), drag-n-dropExpeditorGroupingBoard.Полная спека — Эпик 14 в
epics.mdMVP «Стол заказов».Codegen
Не требовался: переиспользованы существующие
marketplaceCreateShipment/marketplaceListSupplierOrders; схема не менялась.🤖 Generated with Claude Code
Убран ручной ввод shipment_id + кнопка «Создать акт» (ломались: оператор копировал обрезанный для показа id → invalid input syntax for type uuid). Вместо этого — список ожидающих приёмки партий КУ (статус SUPPLY_PREPARED из listShipmentsByBraname) с кнопкой «Создать акт приёмки» на каждой; QR-сканер остаётся для приёмки с телефона. Оба пути зовут createAplReception({shipment_id}). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>@@ -59,1 +66,4 @@// Факт считается от скорректированной оператором цены (actual_unit_price),// а не от цены заказа (o.unit_price): оператор мог снизить/поднять цену на// месте (испорчена упаковка, замена позиции и т. п.).const eosio::asset fact_cost = eosio::asset(что происходит с разницей план/факт для заказчика? Если факт больше - должно быть немедленно списано с кошелька паевых дополнительным паевым взносом, который должен быть сконвертировать в членские. Это значит нужно создать и задействовать отдельное действие конвертации паевого в членский на программе стол заказов, чтобы списывать дополнительно ИМеННО с него! Иначе просто нельзя делать. Нельзя списывать с паевого. Надо списывать с членского. А для этого надо сконвертировать на него. Т.е. конвртация паевой - членский стола заказов должна производиться дополнительным параллельным вызовом, если необходимо досписать что-то .Просто взять и досписать с паевого НЕЛЬЗЯ. А на членском скорее всего будет недостаточно. Это в случае - если больше. Если меньше - то вернуть на членский стола заказов. И там при отмене и при гарантийном возврате средства возвращаются на членский главный - надо скорректировать и возвращать на членский стола заказов. Везде коррекцию это сделать - по всем отменам, и в стандарте.
@@ -98,2 +106,4 @@* открытии), поэтому здесь передаём только подписанный документ.*/export async function finalizeIssuance(order_id: string,и здесь инпут типизированные строго от SDK !!
@@ -62,0 +83,4 @@Queries.Marketplace.ListSupplierPickupOrders.IOutput['marketplaceListSupplierPickupOrders'][number];export async function listSupplierPickupOrders(braname: string,типизируй input как data с интерфейсом IInput из SDK!! ЗАПОМНИ ЭТО УЖЕ!
@@ -0,0 +35,4 @@account: string;}const PREFIX = 'mp1';префикс сделай blago
@@ -0,0 +4,4 @@// генерации QR (`qrcode` — без собственных типов) и нативного декодера// `BarcodeDetector` (поддерживается Chromium; зависимостей не добавляем).declare module 'qrcode' {Какая-то ерунда - зачем ты сюда занес это и сделал глобальный shims, тогда как ты работаешь с РАСШИРЕНИЕМ? Что, без этого нельзя чтоль никак? Ну его нафиг - убирай давай
- desktop API (OperatorReception/OperatorIssuance): все обёртки client.Query/ Mutation принимают `data: IInput['data']` из SDK и передают `{ data }` целиком, без позиционных аргументов и разворачивания полей (канон desktop). Call-sites обновлены (приёмка/выдача/подпись/председатель КУ). - handoff-token: префикс кода передачи `mp1` → `blago`. - удалён глобальный src/shims-marketplace-qr.d.ts: типы `qrcode` через @types/qrcode (dev-dep), `BarcodeDetector` — узким локальным типом в QrScanner (нет в lib.dom). Фронт-only, codegen не нужен. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Страница «Подключение ЦПП Стол заказов»: - Лоадер на «Объявить»: карточка использовала локальный submitting и закрывала диалог сразу после синхронного emit('step-submit'), пока реальная async-отправка проекта решения шла в composable (handleStepSubmit) с отдельным submitting, не пробрасываемым в карточку. Итог — диалог схлопывался мгновенно, лоадера не было нигде. Теперь submitting проброшен из composable в CouncilOnboardingCard: кнопка «Объявить» крутит лоадер, диалог держится открытым до завершения транзакции и закрывается по watcher'у (submitting true→false). - Ширина: убран max-width 860px у карточки онбординга — растягивается на всю ширину страницы. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>