marketplace2 → dev: Стол заказов (весь стек + dev-мердж + ku-selforg) #155
Open
claude
wants to merge 670 commits from
marketplace2 into dev
pull from: marketplace2
merge into: C9S:dev
C9S:main
C9S:dev
C9S:testnet
C9S:fix/598-51-membership-fee-and-type-cleanup
C9S:feat/capital-canon
C9S:feat/598-supplier-registry
C9S:feature/capital-cpp-private-data-templates
C9S:fix/soviet-install-validation
C9S:feat/ku-selforg
C9S:feat/membership-exit
C9S:feat/marketplace-admin-orders
C9S:fix/capital-share-onproject-event
C9S:ci/independent-env-deploy
C9S:fix/registration-pending-display
C9S:coopID
C9S:feat/expense-chassis-mvp
C9S:fix/zip-utf8-flag
C9S:feat/coopid-auth-ui
C9S:feat/coopid-7-signing-bridge
C9S:feat/coopid-12-recovery-account-from-confirm
C9S:feat/coopid-epic-9-metrics
C9S:feat/coopid-epic-6-access-rules-cleanup
C9S:feat/coopid-epic-12
C9S:feat/coopid-epic-11
C9S:feat/coopid-epic-7
C9S:feat/coopid-epic-9
C9S:feat/coopid-epic-6
C9S:feat/marketplace-process-registry
C9S:feat/marketplace-notifications-map
C9S:feat/marketplace-ku-economy
C9S:savanna
C9S:feat/apps-catalog-finish
C9S:feat/epic-13-billing-package-powerup
C9S:feat/coopid-epic-4
C9S:feat/coopid-epic-3
C9S:feat/blagorost-on-chassis
C9S:feat/coopid-epic-1
C9S:feat/marketplace-coop-stock
C9S:feat/marketplace-live-catalog
C9S:feat/coop-invest-blagorost
C9S:feat/ff-release-flow
C9S:fix/marketplace-offer-instance-not-template
C9S:fix/extension-config-lost-update
C9S:feature/C28-28-email-relay
C9S:feat/E16-onsite-sign-gate
C9S:feat/pwa-version-watch
C9S:fix/participants-registry-status-badges
C9S:feat/E16-coop-categories
C9S:fix/sanitize-blockchain-error-toast
C9S:fix/wallet-withdraw-no-phantom-payment
C9S:fix/agenda-program-offer-links
C9S:feat/notification-center-dc-v3
C9S:fix/chatcoop-livekit-room-name
C9S:feat/delete-inactive-participant
C9S:feat/registration-ledger2-suspense
C9S:feat/registration-refund
C9S:feat/registration-payment-dedup
C9S:perf/factory-parallel-fetch
C9S:feat/E16-sklad-rework
C9S:fix/decision-createproject-tsc
C9S:perf/factory-weasyprint-warm-pool
C9S:feat/E16-korzina-zakaz-agregat
C9S:fix/agenda-pending-new-question
C9S:feat/soviet-negative-consensus
C9S:feat/registration-payment-decline
C9S:feat/coop-standards-audit
C9S:parser2
C9S:feat/mkt-return-chairman-cosign
C9S:feat/registration-fsm
C9S:feat/pwa-reliable-update
C9S:parser2-block-time-and-version
C9S:fix/gorozhane-phantom-cleanup
C9S:fix/remove-bank-kpp
C9S:feat/E9-3b-sub-subscribe
C9S:feat/E9-9-approve-moderation
C9S:feat/E10-5-on-chain-watcher
C9S:feat/E10-4-install-pipeline
C9S:feat/E9-3b-ui-publish-package
C9S:feat/E1-tspp-docs-real-text
C9S:feat/E10-3b-dynamic-supergraph
C9S:apps-catalog
C9S:feat/E9-9-3-b-publish-mutation
C9S:feat/sig-v2-export
C9S:feat/E10-1-federation-subgraph
C9S:parser2-epic-4-forks
C9S:feat/decision-authorize-backend
C9S:feat/blagorost-program-expenses-ui
C9S:parser2-epic-6-canonical-storage
C9S:wip/pre-e16-desktop-docs
C9S:feat/E15-min-volume-per-ku
C9S:feat/blagorost-E2-E5-program-expenses
C9S:feat/epic-14-billing-notifications
C9S:blagorost
C9S:feat/E14-explicit-shipment
C9S:feat/marketplace-collective-supply
C9S:feat/blagorost-E1-contract
C9S:feat/C28-21-pg-signed-documents
C9S:provider-billing
C9S:fix/desktop-format-asset-errors
C9S:feat/marketplace-docs
C9S:feat/epic-12-billing-subscriptions
C9S:fix/min-soviet-members-3
C9S:parser2-epic-3-transport
C9S:feat/marketplace2-drop-blocked
C9S:worktree-design-wave1
C9S:feat/notif-mobile-canon
C9S:fix/vue-tsc-desktop
C9S:worktree-marketplace-docs-impl
C9S:feat/chatcoop-hide-matrix-room-id
C9S:feat/epic-8-coop-registry-provider
C9S:parser2-epic-2-idempotency
C9S:feat/chatcoop-secretary-rooms
C9S:feat/remove-l3-blocked
C9S:ci-trial-typecheck-2026-05-23
C9S:fix/controller-revert-transpileonly
C9S:chore/mongo-standalone-local
C9S:chore/ci-unify-release-workflows
C9S:feat/controller-swc-builder
C9S:feat/chatcoop-transcription-memo
C9S:fix/mono-base-ca-certificates
C9S:fix/wallet-withdraw-gateway-timing
C9S:feat/ledger2-burn-blocked-withdraw
C9S:fix/boot-tests-wallet-signagree-v2
C9S:chore/trustees-ownership
C9S:feat/capital-w-cap-gen-cooperative
C9S:chore/re-review-E5-apl-fail-fast
C9S:chore/re-review-E4-fail-fast-tx-hash
C9S:chore/re-review-E3-fix-withdraw-stub
C9S:chore/review-E3-vitrina-fixes
C9S:chore/review-E10-design-fixes
C9S:chore/review-E8-spisanie-fixes
C9S:chore/review-E7-vozvrat-fixes
C9S:chore/review-E6-vydacha-fixes
C9S:chore/review-E5-postavka-fixes
C9S:chore/review-E4-order-fixes
C9S:feat/epic0-onboarding-harness
C9S:chore/marketplace2-sync-dev-and-controller-di
C9S:feat/E11-stol-zakazov-frontend-and-tests
C9S:feat/E11-stol-zakazov-final
C9S:feat/capital-artifacts-access
C9S:fix/floor-asset-display
C9S:feat/epic-9-warehouse-reporting
C9S:feat/598-11-epic-8-writeoff
C9S:feat/E7-garantiynyy-vozvrat
C9S:design
C9S:fix/capital-revert-394-generation-convert-refs
C9S:fix/is-unioned-zod-string-parse
C9S:fix/capital-rename-generation-convert-to-money-invest
C9S:feat/E6-vydacha-payshchiku
C9S:worktree-remove-1081-1082-rename-1080
C9S:feat/init-by-server-from-provider
C9S:feat/E5-postavka-priemka
C9S:feat/E11-techdebt-L12-split-payout
C9S:feat/E4-zakaz
C9S:gh-pages
C9S:feat/E3-vitrina-canon
C9S:feat/E11-S1-ledger2-marketplace-ops
C9S:file-storage
C9S:feat/1-10-marketplace-registration-offer-status
C9S:feat/1-9-marketplace-board-acceptance
C9S:feat/1-8-marketplace-access-matrix
C9S:feat/1-7-marketplace-template-registry
C9S:feat/1-6-marketplace-role-guard
C9S:feat/1-5-marketplace-member-wallet
C9S:feat/1-4-marketplace-onboarding-gate
C9S:feat/1-3-marketplace-access-by-membership
C9S:feat/1-1-install-from-catalog
C9S:ci/lock-tags-only
C9S:onboarding
C9S:reports
C9S:ledger3
C9S:graph-standarts
C9S:feat/ledger-double-entry
C9S:feat/docs-enrichment
C9S:feat/documentation
C9S:feat/marketplace-orders
C9S:feat/interops-extension-system
C9S:cursor/development-environment-setup-2882
C9S:feat/unified-test-pipeline
C9S:fix/security-vulnerabilities
C9S:audio-stream
C9S:project-authorization-on-create
C9S:refactoring
C9S:capital
C9S:element
C9S:ledger
C9S:marketplace
C9S:notifications2
C9S:notifications
C9S:document2
C9S:TSK-900
C9S:TSK-878
C9S:dacom-dark-sun/sprint-4
C9S:uniconstructor/sprint-5
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "marketplace2"
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?
Зонтичный PR: подтягивает всю ветку marketplace2 (продукт «Стол заказов») в dev.
marketplace2 сейчас на 657 коммитов впереди dev и не отстаёт (0) — dev уже
целиком слит внутрь marketplace2 отдельным merge-коммитом, поэтому конфликтов
при мердже в dev быть не должно.
Состав: полный Стол заказов (каталог, заказы, приёмка/выдача, возвраты,
списание скоропорта, склад кооператива), экономика КУ (accrue/distribute/
spend, реестр плановых расходов), реестр поставщиков, самоорганизация
кооперативных участков (feat/ku-selforg — собрания/решения, приватность,
доверенные лица), плюс всё, что уже было в dev на момент слияния (двухфазный
регистрационный взнос через счёт 76, шасси расходов, self-service выход
пайщика и др.) — уже интегрировано и совместимо.
НЕ мерджить без явного решения — зонтичный PR на ревью.
🤖 Generated with Claude Code
1. Убран лишний import { withDefaults } from 'vue' из 9 файлов: - features/Request/CreateChildOrder/ui/CreateChildOrderButton.vue - widgets/Marketplace/SupplyOrderRequestCard/ui/Steps/{First..Eighth}Step.vue В Vue 3 withDefaults — compiler macro, доступен глобально без импорта, явный import конфликтует с локальным declaration (TS2440). 2. widgets/Marketplace/SupplyOrderRequestCard/ui/Base/Base.vue — request.membership_fee_amount → request.membership_fee (поле в IRequestData/SDK называется membership_fee). vue-tsc --noEmit --skipLibCheck: 0 ошибок.Добавлены кооперативные стандарты для процессов контракта marketplace в режиме членских взносов (упрощённая модель с одним программным кошельком w.mkt.fund, без транзитов): • p.mkt.supply.standard.yaml — Прямая поставка-приобретение имущества (7 операций ledger2, двухвариантная приёмка А/Б, двойные подписи АПП приёмки и АПП выдачи) • p.mkt.return.standard.yaml — Гарантийный возврат имущества (compensating forward o.mkt.return, без ledger2::revert) • p.mkt.wroff.standard.yaml — Утилизация скоропорта (ACCOUNT_ONLY с транзитом через счёт 91) Все wallet_from/wallet_to используют eosio::name-строки (w.mkt.fund, w.wal.share, w.mkt.payout) согласно рефакторингу 2026-04-27 на ветке reports. Документы привязаны к существующим шаблонам: • АПП приёмки = registry_id 702 (AssetContributionAct) • АПП выдачи = registry_id 802 (ReturnByAssetAct) • Заявление возврата = registry_id 800 (ReturnByAssetStatement) • ТТН и протокол списания = 0 + TODO (нет шаблонов в реестре). Все операции имеют статус proposed; имена ≤12 chars eosio::name. Бухгалтерские проводки помечены TBD-Standardization для последующей сверки с Ангелиной/Игорем. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>f(от funds) не нёс информации и путал чтение, новые имена односложные и говорят сами за себя; зеркальные пары: assign↔recall (целевое назначение / отзыв), block↔unblk (unblock=13 не помещается в eosio::name); правки только в стандартах + sister-doc архитектуры — operations.ts/hpp ещё не содержат этих кодов (войдут одной chunk-PR при формализации стандарта с командой) 609201e75frelated:и заголовка §7 (sed-truncate); из standards-site убраны: section в ProcessPage с slider'ом, computed relatedLinks, RELATION_HUMAN, relationHuman, RelatedView interface, импорты standardsIndex/RouterLink; из types/standard.ts удалены RelatedStandard, RelationKind, поле related; из graph/layout.ts — hasRelated; из EndNode.vue — prop hasRelated; SKILL.md — убрана §6 «Связи» (template и описание provides/triggers/affects); .process-page grid теперь auto / minmax(0,1fr) — рабочая зона растягивается на всю освободившуюся высоту 9dae639800- operations.hpp: enum WalletOp + REVOKE (списание blocked + обяз. Dr/Cr); удалены CONFIRM_SUPPLY/CONFIRM_RECEIPT; добавлены 12 операций членской модели — CONVERT_TO_MEMBER в operations::wallet и 11 в operations::marketplace (ASSIGN_TO_PROGRAM, BLOCK_FOR_ORDER, UNBLOCK_ON_CANCEL, RECALL_TO_UNIVERSAL, PURCHASE_FROM_SUPPLIER, PAY_SUPPLIER, CONSUME_BY_MEMBER + CONSUME_TRANSIT_CLOSE, RETURN_BY_MEMBER + RETURN_TRANSIT_CLOSE, WRITE_OFF_PERISHABLE + WRITE_OFF_TRANSIT_CLOSE); composite-проводки через транзит счёта 91 «Прочие доходы и расходы» разбиты на пары операций (часть 1 + часть 2, *2-суффикс), вызываемые последовательно в одной транзакции Antelope — атомарность через транзакцию. - accounts.hpp: добавлены счета 10 «Материалы» (А) и 91 «Прочие доходы и расходы» (А/П). - wallets.hpp: добавлен USER_SHARED-кошелёк w.mkt.member («ЦПП Стол Заказов — программный членский») с program_id=2 (marketplace). - processes.hpp: удалён p.mkt.reqst (клиринговый), добавлены p.mkt.supply / p.mkt.return / p.mkt.wroff. - p.mkt.{supply,return,wroff}.standard.yaml: composite-проводки разнесены на пары operations[]; транзит через 91 явно описан в комментариях и description (нетто-эффект — Дт 86 / Кт 10 на выдаче/утилизации и Дт 10 / Кт 86 на возврате). Согласовано с Ангелиной 2026-05-11. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>- Подключить MarketplacePluginModule в ExtensionsModule.register (расширение не загружалось в NestJS DI-контейнер). - Унифицировать имя расширения: MarketplacePlugin.name = 'market' (совпадает с ключом AppRegistry; install через installExtension({name:"market"}) теперь не падает на findByName('marketplace')). - Расширить MarketplacePlugin.initialize: bucket coop-<coopname> через optional file-storage порт (@Optional injection, fallback под warn-логом до merge PR #359); три AC-лога backend'а — 'Создан физический бакет ...', 'File storage готов', 'marketplace-extension готов'. - Bootstrap config-миграция v1 для расширения market. - Atomic rollback в ExtensionInteractor.installApp: при провале runApp снести запись через uninstallApp, только если её не было до install; ошибка пробрасывается наверх (UI Каталога показывает 'Ошибка'). - Process locator: обновить TODO p.mkt.* — заглушки готовы, активация в Story 4.1 при создании marketplace::requests. Unit-тесты: - tests/unit/marketplace/marketplace-plugin-initialize.test.ts (4 проходят). - tests/unit/appstore/extension-interactor-install-rollback.test.ts (3 проходят). Refs: blago/production/1-prilozhenie-stol-zakazov/components/3-minimalnyy-produkt/_bmad-output/implementation-artifacts/spec-1-1-install-from-catalog.md Co-authored-by: coopops <coopos@coopenomics.world> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>* Эпик 11: «Реестр процессов» на столе бухгалтера (598-14) UI-надстройка над уже работающим Phase A/B ProcessRegistry в core controller: страница /reports/processes показывает листинг процессов ledger2 с фильтрами по типу процесса (LEDGER2_PROCESS_REGISTRY) и пайщику, при раскрытии строки рисует events + documents процесса (через getProcess), отдаёт слот processInfoFactory для бизнес-описания (marketplace handlers уже регистрируют SUPPLY/RETURN/WRITEOFF в extensions/market/app/extensions.ts) и кнопку deep-link «Открыть в реестре операций» (filter process_hash). Используется existing SDK query `Queries.Processes.ListProcesses` — расширены entities/Process api+store+types методом `listProcesses` и type alias'ами IProcessListInput/IProcessListResult/IProcessSummary. Стол бухгалтера приобретает четвёртый базовый реестр (операции, проводки, **процессы**, кошельки, счета) — закрывает аудит-видимость marketplace flow «Стола заказов» в рамках Эпика 11. * Эпик 11 техдолг 598-21: batch-маркировка партии за один вызов Mutation `marketplaceLabelShipmentInventory(shipment_id, default_strategy?, per_order_overrides?)` массово маркирует все Order'ы партии поставки — оператор перестаёт проходить N карточек по одной. Service `MarketplaceInventoryLabelService.labelShipment`: 1. Shipment.findById → берёт coopname/cycle_id/braname. 2. orderRepo.findByCycleId(coopname, cycle_id) → filter по delivery_braname партии = все Order'ы партии. 3. Для каждого Order'а зовёт уже работающий execute() — единый источник правил маркировки (стратегия из Offer.barcode_strategy по 598-22, per-Order override для смешанных Offer'ов в партии). 4. Идемпотентность: ConflictException от execute() при повторной маркировке → skipped_order_ids в результате (повторный заход на страницу не валится fatal'ом). Возврат включает labeled_order_ids + skipped_order_ids + сами наклейки (`MarketplaceInventoryItem[]`) — UI оператора может одним вызовом получить grid этикеток для печати и понимать что было сделано. `@media print` grid layout и расширение `OperatorInventoryLabelingPage` под выбор default-стратегии на всю партию — следующий шаг, mutation теперь доступна. * Эпик 11 Stories 11.2 + 11.3: off-chain инварианты ledger2 marketplace + coverage трассировки 13 op-кодов Backend-side scaffold контрактных проверок Stories 11.2 (Journal/wjournal трассировка) + 11.3 (CI-инварианты ledger2). Реализация — pure-функциями без NestJS/PG: работают на синтетических массивах Ledger2OperationDTO, гонятся unit-тестом без реального chain'а (отвечает требованию off-chain агрегации: никаких сумм по всем кошелькам пайщиков в смарт-контракте). Состав: - `marketplace-ledger2-invariants.ts` — 6 pure-агрегаторов (I1 payout balance, I2 Δ86, I3 acc.10, I4 acc.91 transit = 0, I5 blocked в w.mkt.member, I6 нет orphan o.mkt.block). Та же логика что UI стола бухгалтера (`/reports/operations`, `/reports/postings`). - `marketplace-ledger2-invariants.spec.ts` — 86 тестов: happy path + violation path для каждого I1..I6 + property-based на 50 случайных последовательностях (mix happy/cancel/return/writeoff). - `marketplace-process-trace-coverage.spec.ts` — 10 групп: coverage по всем 13 marketplace operation_code (12 o.mkt.* + o.wal.conv) в cooptypes + OPERATION_CODE_TO_PROCESS_TYPE + PROCESS_HASH_LOCATOR; Phase-A якорь связности apply+walletop+debit+credit под одним process_hash; full-flow scenarios для supply/return/wroff. Контрактные тесты в Antelope simulator (mono-ai-5) остаются за другим агентом; здесь — backend-side mapping контроль и off-chain агрегация инвариантов, доступные для CI и admin-вью. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: ant <ant@noreply.local> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>CRITICAL: - service: tx_hash propwroff/createagenda/execwroff раньше нигде не сохранялся — audit-trail отсутствовал. Теперь extractTxHash и пишется в decision_log при submitToCouncil (propwroff_tx_hash, createagenda_tx_hash) и при executeAuthorizedProposal (execwroff_tx_hash per-item). - service: пустой tx_hash от цепи → fail-fast ConflictException (submitToCouncil + executeAuthorizedProposal). Раньше silent fall-through. - service: pre-gate в submitToCouncil — если proposal с тем же hash уже отправлен в совет, повторный submit отбивается (защита от двойного клика → дублирующего propwroff + createagenda). - service: inventory.applyStatusTransition WRITTEN_OFF теперь обязателен — раньше catch → warn без re-throw; позиция могла остаться RETURNED_TO_WAREHOUSE при успешном on-chain wroff'е и попасть в следующий cron-цикл → повторное списание. Теперь re-throw, proposal остаётся в EXECUTING для retry. - service: signer fallback на coopname удалён (coopname — аккаунт кооператива, не пайщик; контракт execwroff требует branch.is_user_authorized(signer) — coopname этого не пройдёт). - cron: amount=0 placeholder отбивался validateAndNormalizeItems (`amount <= 0`) — крон при auto_proposal_enabled=true ВСЕГДА падал. Теперь крон фильтрует кандидатов без unit_cost; если все без цены — отправляет напоминание председателю вместо broken DRAFT. MEDIUM: - resolver: throw new Error → BadRequestException для «DRAFT-only» валидации (унификация с остальными resolver'ами). Known limitations (Phase 2): - Story 8.1 AC требует ЧЕТЫРЕ типа кандидатов (RETURNED_TO_WAREHOUSE / EXCESS_RETURNED_TO_WAREHOUSE / без юр. оформления / expiry_date). Сейчас крон покрывает только expiry_date. Расширение требует добавить поля age_days/returned_at в inventory. - Story 8.3 AC «единая Antelope-транзакция NFR-R2» — by design контракта per-item execwroff (комментарий cpp прямо говорит «снимает ограничение на максимальный размер протокола»). AC ↔ контракт конфликт — требует переоформления AC. - Number()/toFixed() float-арифметика на суммах — на больших суммах возможна потеря точности; нужен переход на BigNumber. - cycle_started_at.toISOString() hash-mismatch при round-trip через PG с разной precision timestamptz. - onCouncilAuthorized synchronously вызывает execute — long-running в delta-listener'е, риск duplicate execute при retry. Нужен decoupling через background worker. Test plan: - [x] jest marketplace-writeoff — 31 passed. - [ ] e2e: двойной клик «Подписать и отправить» — второй submit отбивается ConflictException. - [ ] e2e: цепь возвращает {} вместо tx — ConflictException, статус draft остаётся DRAFT. - [ ] e2e: inventory.applyStatusTransition бросает — proposal в EXECUTING, retry возможен. - [ ] e2e: cron при auto=true и пустом unit_cost — reminder вместо DRAFT'а с amount=0. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Phase 0 ground work for «Стол заказов» MVP docs: - harness: - extend KNOWN_FIXTURES with 7 marketplace participants (chairkrg/chairodn/chairmyt/trustedkrg/opkrg/sidorov/petrova) - add cleanViteOverlays() helper to strip vite/HMR overlays before every shot/shotElement screenshot - loginAsChairman/loginAs: call cleanViteOverlays before clicks + waitForFunction (hash-router friendly) instead of waitForURL - scenarios: - scenarios/marketplace/PLAN.md (E2E план + структура столов) - scenarios/marketplace/chairman/branches.mjs — Сеть ПВЗ - boot seed: - boot/src/scripts/seed-marketplace-branches.ts — идемпотентно создаёт 3 КУ Подмосковья (krg/odn/myt) on-chain + Mongo organizations + addtrusted trustedkrg - desktop pug fixes (8 файлов в pages/Marketplace): vite vue-pug parser падал с «Unterminated string constant» на многострочных inline-массивах :columns="[...]" / :options="[...]" внутри pug templates. Выношу массивы в <script setup> как const — парсер проходит, типизация q-table через QTableProps['columns']. - quasar.config.cjs: vitePlugins=[] временно отключает vite-plugin-checker (overlay перехватывал клики Playwright + vue-tsc worker отъедал >4 ГБ heap). Refs: components/docs-harness/scenarios/marketplace/PLAN.md- init-wallet: info.coopname может быть undefined из-за race между login и loadSystemInfo. Когда login завершается быстрее, init-wallet вызывает loadUserWallet({coopname: undefined}) → GraphQL 400 → catch → reload → фронт никогда не редиректит после login. URL-fallback извлекает coopname из window.location.hash/pathname как safety net. - harness scenarios/marketplace/chairman/dashboard-overview.mjs: обзорный сценарий по 5 marketplace URL-ам (/marketplace, /marketplace/catalog, /marketplace/orders, /chairman, /chairman/approval-requests). Без waitForURL — фронт сейчас не делает redirect после login. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Submit-кнопка называется «Опубликовать на модерацию», не «Создать». Quasar рендерит label как div.q-field__label, не <label>, поэтому locator('.q-field').filter({ has: locator('.q-field__label', ...) }) — корректный путь к контейнеру q-select. Кадр 03 теперь снимается. Каталог в кадре 04 остаётся пустым: backend :2998 в текущей среде не имеет marketplace-резолверов (marketplaceListCategories отсутствует в GraphQL-схеме), fetchCategories возвращает []. Сценарий готов: когда controller с marketplace-extension будет поднят, выбор категории и публикация offer пройдут автоматически.Why: - backend mono-ai-4 :3028 был перезагружен с нуля (boot:extra с правильным MONGO_URI?directConnection=true и POSTGRES для per-instance портов), cooperative voskhod + 5 членов совета загружены в БД через cooparser initial-load - старые скриншоты в PR были сняты до wipe — UI мог показывать stale state Также: - components/desktop/quasar.config.cjs: viteConf.server.fs.strict=false для assets из bind-mount /home/admin/mono-ai-N (worktree compose override) - components/docs-harness/bin/shoot.mjs: - ensureOneFixture передаёт CHAIN_URL и MONGO_URI?directConnection=true в env add-plain-participant (без CHAIN_URL скрипт падает на ECONNREFUSED) - runScenario передаёт BASE_URL в env под лежащий снизу harness.mjs (раньше default :2999 — это mono-ai-1 desktop, не свой)marketв installExtraData — категории и marketplace mutations 433ae6dc6aensureBranchPaymentMethod() сохраняет dummy bank_transfer paymentMethod для каждой КУ в Mongo. Без него branch.interactor.getBranch() падает TypeError в строке 55 (new BankPaymentMethodDTO(null) destructure-ит username из null), и весь getBranches возвращает 500 → desktop UI «Кооперативные участки» показывает «Нет данных». После фикса страница показывает 3 КУ с председателями и реквизитами банка (ПАО Сбербанк / Тинькофф / ВТБ). MARKETPLACE_BRANCHES расширен полем bank_name; payment method сохраняется через generator.save ('paymentMethod', ...) после ensureMarketplaceBranch. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Зачем: пользователь обнаружил что 9 страниц Marketplace из PLAN.md §9.6 физически отсутствуют в Vue коде (бэкенд для Эпиков 1/3/4/5/6/8 DONE, фронтенд не реализован). Закрываю первую и самую компактную из 9 — Эпик 1 / Story 1.9-1.10 (L1 onboarding: приём кооперативом ЦПП «Стол заказов»). Что сделано: - SDK wrappers Queries.Marketplace.MarketplaceCppStatus + Mutations.Marketplace.MarketplaceAcceptCpp над уже существующими marketplaceCppStatus и marketplaceAcceptCpp GraphQL (Zeus схема в SDK уже содержит обе операции). - Vue page components/desktop/src/pages/Marketplace/OnboardingCoopAcceptCpp/{api,ui,index.ts} (UX-DR конвенции: mp-role-admin, marketplace-tokens.scss). - Роут /market/onboarding/coop-cpp в extensions/market/install.ts (roles: chairman/member, через agreementsBase). Аудит остальных 8 страниц + приоритизация — в PLAN.md §9.7. Ограничение: desktop в worktree через symlink тянет shared /home/admin/mono-ai-4/components/sdk, поэтому без пересборки shared sdk страница не подхватится в dev на :3029. Это будет решено отдельным PR (либо merge ветки, либо синхронизация SDK к shared). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>cycle_type Postgres-domain (snake_case) теперь конвертируется в eosio::name (без `_`) на boundary chain submit: marketplace-offer.types.ts: + MARKETPLACE_CYCLE_TYPE_CHAIN_NAME registry + toChainCycleType(cycle) helper (соответствует enum-правилу CLAUDE.md) marketplace-order-create.service.ts:160: cycle_type: toChainCycleType(offer.cycle_type) Mapping: time_based→timebased, volume_based→volumebased, open_subscription→opensubscr, individual→individual (см. components/contracts/cpp/lib/domain/table_marketplace_orders.hpp:69-71). После фикса pipeline проходит cycle_type-валидацию и доходит до `o.wal.block`, где упирается в новый блокер: пустой L3-кошелёк тестовых пайщиков (0,00 RUB). UI корректно показывает Notify «Недостаточно средств для заказа: требуется 240.0000 RUB, доступно 0.0000 RUB» через extractErrorMessage(). Обновлены: - order-create.md admonition (старый блокер resolved, новый описан) - shot переименован 03-order-create-onchain-error → 03-order-create-no-funds - PLAN §9.11 фиксирует решённый и новый блокер - Task #137 заведён для пополнения L3-кошельков в installExtraData Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>* desktop OnboardingMemberPickCpp/api: client.Mutation(mut, { input }) не передавал переменную в GraphQL — правильный pattern `{ variables: { input } }` (как в submitCreateOrder). Backend отвечал «Variable $input of required type MarketplaceSignOnboardingOfferInput! was not provided», подпись ЦПП не доходила до on-chain. После фикса `wallet::signagree` (voskhod/ekaterina program_id=2 draft_id=699) проходит, marketplace::createorder больше не падает на «walletop: не подписано program_id=2». * docs-harness/bin/shoot.mjs: ветка `wasUp && distRebuilt` делала `pkill -f 'quasar.js dev'` на хосте + spawn хостовый `pnpm run dev`. Quasar dev живёт в docker-контейнере, pkill на хосте ничего не убивает, а параллельный хостовый pnpm dev писал в .q-cache под admin uid, пока контейнер пишет под node uid — EACCES, кэш разваливается, Vite перестаёт резолвить @coopenomics/sdk. Если порт отвечает — ничего не трогаем, vite сам подхватит dist через fs-watch. * harness order-create.mjs: переписан под полный flow magistral II с шагом подписи L3 ЦПП через /market/onboarding/member-cpp + debug-снимок 00-marketplace-onboarding-page для будущей диагностики. Magistral II по L3-подписи разблокирована. Остался отдельный блокер в MarketplaceOrderCreateService.normalizeTxResult — backend не дождётся tx_hash от цепи, хотя on-chain action createorder проходит (out-of-band sync error). Это вне фоллоуапа Эпика 1. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>* MarketplaceOrderCreateService.normalizeTxResult бросал «цепь не вернула tx_hash» хотя on-chain createorder проходил и кошелёк списывался. Причина: код искал `tx?.transaction?.id` и `tx?.processed?.id`, но @wharfkit/session@1.6.1 возвращает TransactResult структуры `{ response: { transaction_id, processed: { id, block_num } }, transaction: ResolvedTransaction (без id-поля), resolved: ResolvedSigningRequest, ... }`. Поля `.processed` на верхнем уровне нет, `.transaction.id` либо undefined либо Checksum256 (не string). * Правильно: `tx.response.transaction_id` (+ fallback'и на `resolved.transaction.id` и плоский `transaction.id` для совместимости с другими wharfkit-версиями — как в `extractTxHash` marketplace-apl-reception / return-claim / issuance / writeoff сервисов, где этот pattern уже работал). E2E подтверждён: ekaterina подписывает ЦПП → marketplaceCreateOrder проходит → Notify «Заказ создан» → кошелёк списан → offer quantity_available уменьшился. Magistral II полностью разблокирована. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Документация (components/docs): - 14 пользовательских страниц «Стол заказов» (onboarding/offerer/orderer/operator) + nav-секция в mkdocs.yml - проза бизнес-языком по фактам со скриншотов; магистраль II (шаги 6–10) сняты e2e Backend (controller): - финальная подпись выдачи авторизуется по подписи заказчика в документе (устранён 403 на шаге 10) - signable-payloads приёмки/выдачи отдают DocumentAggregate {hash, rawDocument, document} — канон второй подписи поверх документа первого подписанта без регенерации - L3-mutation marketplaceSignOnboardingOffer + DTO; schema.gql + zeus regen - DTO/мапперы приёмки (accept_braname/fact_quantity/reception_id/supplier_account/total_amount) Desktop: - OperatorInventoryLabeling/Issuance/Reception API + IssueActFinalizeDialog; KU-chairman доступ к /market-pvz/* Harness (docs-harness): - prod-SPA подход; toast/overlay-фикс в lib/harness.mjs; новые/обновлённые сценарии magistral II + diag-e2e-apl STOP_AFTER Boot (installExtraData): - ролевые фикстуры + 3 КУ, эмиссия L3-кошельков, активация КУ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>- ledger2: восстановлены 11 операций o.mkt.* + wallet::CONVERT_TO_MEMBER + кошелёк w.mkt.member, утерянные кривым merge (operations.hpp/wallets.hpp откатились на legacy-сторону, тогда как accounts/processes остались на Эпике 11). CONSUME_BY_MEMBER → существующий WalletOp::BURN_BLOCKED (без дубля enum-слота). marketplace.wasm снова собирается. - propwroff: action расширен (document2 statement, std::string meta); контракт сам ставит повестку inline-вызовом soviet::createagenda от permission_level{marketplace, active} (marketplace в contracts_whitelist). - backend: propWroff несёт statement+meta (через SignedDigitalDocumentInputDTO .toDocument()); отдельный createWriteoffAgenda удалён из порта/адаптера/ сервиса — кооператив не в whitelist, второй вызов создавал бы дубль повестки. cooptypes IPropWroff +statement+meta. spec 31/31. - desktop: суммы списания форматируются через formatAsset2Digits на столе председателя, в ленте совета (фикс поля total_loss_amount→total_amount, показывалось «—»), в деталях проекта и виджете процесса. - harness: writeoff-propose снова доводит проект до повестки совета (ENABLE_COUNCIL_SUBMIT=true после фикса моста).- access-matrix: capability Payment:read:all для admin/board_readonly/board (член совета ведёт надзор за выплатами, подтверждает кассир) - резолвер marketplaceListOutgoingPayments(supplier_account?, statuses?) под RequireMarketplaceAccess('Payment','read:all') - repository.listAll(coopname, filter) + адаптер: coopname + опц. payee_account + In(statuses), created_at DESC - SDK: Queries.Marketplace.ListOutgoingPayments + regen zeus (controller/zeus, sdk/src/zeus) - desktop: BoardPayoutsReadonly с placeholder на реальную таблицу (фильтры поставщик/статус, сводка-счётчики, локализация статусов) - harness-сценарий marketplace/board/payouts-readonly Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Расширение market давало один смешанный стол из 21 страницы (заказчик + поставщик + админ вперемешку) и отдельный Стол ПВЗ, причём market-pvz вообще не объявлялся в backend AppRegistry → его маршруты молча терялись. - backend extensions.registry.ts: AppRegistry['market'].desktops теперь объявляет 4 стола (market/market-supplier/market-pvz/market-admin) — фронт прикрепляет маршруты только к объявленным backend столам. - desktop install.ts: возвращает 4 workspace, 29 страниц разнесены по ролям; Стол администратора виден только chairman+member (meta.roles), остальные — всем; имена маршрутов сохранены (навигация по имени). - init-installed-extensions: убран немой catch{} (теперь console.error) + warn, когда install вернул workspace, отсутствующий на backend, — раньше сломанный/несинхронный стол выглядел как «пустой» без диагностики. Проверено на стенде: getDesktop = 4 стола, Pinia-стор = children 6/6/8/9, скриншот навигатора подтверждает рендер страниц по столам. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Семантика in-code не меняется: Ledger2::apply(coopname, op, amount, ...) вызывается с теми же operation_id (o.mkt.block / o.mkt.unblk / o.mkt.consum), изменения только в doc-блоках и inline-комментариях: - createorder.cpp: "BLOCK на w.mkt.member" → "TRANSFER w.mkt.member → w.mkt.order" - cancelorder.cpp: "сумма остаётся на .available" → уточнено, что снятие резерва - declineorder.cpp: "резерв возвращается заказчику" → уточнено через TRANSFER - expireorder.cpp: тот же flow - signiss2.cpp: actual<ordered → снятие части резерва (UNBLOCK_ON_CANCEL), actual>ordered → доп. резерв (BLOCK_FOR_ORDER), CONSUME_BY_MEMBER теперь BURN с w.mkt.order Поведенческих изменений в C++ нет — вся семантика выражена через изменения в OPERATION_REGISTRY (предыдущий коммит). Этот коммит — только документация точки вызовов, чтоб не путать читателя. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Инвариант I5 переименован: `BlockedConsistency` → `ReserveConsistency`. Считает резерв через пары TRANSFER + BURN в новой модели: Σ TRANSFER(w.mkt.member → w.mkt.order) // o.mkt.block — резерв входит − Σ TRANSFER(w.mkt.order → w.mkt.member) // o.mkt.unblk — резерв снят − Σ BURN(w.mkt.order) // o.mkt.consum — резерв сожжён = Σ balance(w.mkt.order у пайщиков) Раньше I5 сверялся с suma blocked у w.mkt.member-кошельков (поле `.blocked`). Поле `.blocked` для marketplace-кошельков теперь deprecated (всегда 0) — резерв выражается через `.available` отдельного кошелька w.mkt.order. Инвариант I6 переименован: `NoOrphanedBlocks` → `NoOrphanedReserves`. Логика парности по process_hash (consum без block, unblk без block, block+unblk+consum = двойное закрытие) не меняется — op_code'ы o.mkt.block/unblk/consum сохранены. Фикстуры в spec.ts переписаны под новую модель: walletFrom/walletTo для block теперь w.mkt.member → w.mkt.order, для unblk наоборот, для consum — walletFrom=w.mkt.order (BURN). ВНИМАНИЕ — pre-existing baseline: `marketplace-process-trace-coverage.spec.ts` и 4 теста в `*-invariants.spec.ts`, которые опираются на `MARKETPLACE_OPERATION_CODES` (фильтр через `Ledger2.LEDGER2_OPERATION_REGISTRY.contract === 'marketplace'`), падают с pre-existing проблемой: `cooptypes/ledger2/operations.ts` содержит только 2 legacy marketplace-операции (`o.mkt.supply`/`o.mkt.recv`) вместо 13 новых. Это известный блокер Эпика 11 Story 11.1 (синхронизация TS-стороны cooptypes с C++ operations.hpp) — выходит за scope этого PR. Проверено: 32/36 тестов в marketplace-ledger2-invariants.spec.ts passed (те же 4 теста были сломаны на pre-state baseline). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Форма «Создать предложение» переверстана по канону MONO Design System как VerticalStepper-мастер (Товар → Цена и наличие → Условия поставки → Изображения → Проверка; эталон CreateMeetForm): бизнес-язык вместо time_based/volume_based, BaseRadioCard под отсечку, reserve-hint-space против layout shift. Изображения товара (закрыт gap parent-UX, где MVP-epics уронили offer-фото): - jsonb-колонка marketplace_offer.images ({bucket_key,content_hash,mime_type}[], индекс 0 = обложка); миграция v7 (DDL через synchronize); - MarketplaceOfferImagesService на @UseBucket('stol-zakazov:images', AR31) — зеркало return-claim-канона; ключ content-addressed offers/<coop>/<owner>/<sha>; - base64-инпут images в create/update DTO (≤8, ≤10МБ, jpeg/png/webp), декод+put в offer.service + cleanup сирот при провале записи; - @ResolveField images → HMAC-signed URL (ленивый резолв, не в каждом list); - codegen: schema.gql + zeus (controller+sdk) + offerSelector. DRY: fileToBase64 вынесен в shared/lib/utils, два return-claim-дубля переключены. Research вариантов продукта (off-chain PG-only, контракт не трогается; счётчики 3.4 на variant-уровень — самая инвазивная часть; FR18a снимается, не нарушается) зафиксирован в плане проекта (Эпик 13, research-only). Тесты: offer-service 43/43 (вкл. 3 новых на images), moderation+counters зелёные; tsc контроллера 0, ESLint desktop 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Аудит кастов по Столу оператора (ПВЗ) и Столу администратора: - template-кастов 0, `as any` 0 — опасных/рантайм-фатальных нет; - два реальных хака в admin-страницах убраны без каста: - BoardAgendaWriteoff: `(... ) as never` — локальный строковый WriteoffStatus не стыковался с SDK-входом statuses (enum MarketplaceWriteoffProposalStatus). Добавлена явная таблица STATUS_TO_ENUM (5 видимых совету статусов → enum), statuses строится map'ом. Тип доказан образцом соседней AdminWriteoffsPage, которая так же кормит listWriteoffProposals enum-массивом. - OnboardingCoopAcceptCpp/composable: `stepToRegistryId[meta.id] as number` → typeof-guard (робастно к noUncheckedIndexedAccess). НЕ тронуты api-слойные `return result as <ViewType>` (OperatorIssuance/Reception/ InventoryLabeling/ReturnClaims, AdminWriteoffs): это НЕСУЩЕЕ сужение Zeus-скаляров (DateTime/ID типизированы Zeus как unknown; view-тип сужает их до string/ NonNullable через Omit&{…}). Убрать = сломать типы (unknown не присваивается string) или добавить бессмысленный рантайм-.map(). Направление каста безопасное (unknown→точный тип), у каждого инлайн-обоснование. Это не `as any`. ESLint 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Убран ручной ввод 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>- 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>Страница создания предложения поставщиком грузила список КУ запросом marketplaceListKUDetails с пустым data: {}, из-за чего GraphQL отклонял запрос «Field "coopname" of required type "String!" was not provided» и кооперативные участки не загружались. Переведён на entity-store MarketplaceKUDetails (как AdminIssuancePoints): coopname берётся из systemStore.info, onlyActive: true. Инлайн client.Query с пустым data убран (DRY: используем готовую обёртку entity). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Принятие гарантийного возврата (accretrn) оформляется второй подписью председателя КУ на том же заявлении пайщика (канон двухподписных актов), а не отдельным документом. Удалённое рассмотрение (aprretrem/rejretrem) и отказ на осмотре (rejretrn) — процедурные действия без подписи документа. Контракт: - table return_request: убраны поля decision_remote / decision_visit; statement при accretrn перезаписывается версией с обеими подписями. - accretrn принимает document2 statement, требует обе подписи (verify_document_or_fail{orderer, chairman}); aprretrem/rejretrem/rejretrn больше не принимают документ. - собран зелёным (marketplace.wasm). cooptypes: интерфейсы IAprRetRem/IRejRetRem/IRejRetrn без decision, IAccRetrn.decision → statement. backend: сервис/DTO/резолвер — удалённые шаги и отказ без документа, accretrn принимает со-подписанное заявление (signed_statement). standard p.mkt.return: registry 800→1104 (членская модель, = коду), секция документов и подписи переписаны на бизнес-язык; один документ — заявление с подписью пайщика и со-подписью председателя при принятии. Follow-up (отдельный срез): персистентность подписанного заявления в claim + экспозиция в DTO + со-подпись в desktop OnSiteDecisionDialog + zeus regen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>При подаче заявления на гарантийный возврат backend теперь сохраняет подписанное пайщиком заявление (registry 1104) в claim — новая jsonb-колонка marketplace_return_claim.statement (создаётся synchronize). Раньше документ уходил только в цепь, и председателю было нечего со-подписывать. - types/entity/typeorm/mapper/repo: поле statement (ISignedDocumentDomainInterface | null). - submitReturnClaim сохраняет input.signed_statement в claim. - новый метод getChairmanReturnSignablePayload + запрос marketplaceReturnClaimChairmanSignablePayload → DocumentAggregate {rawDocument + подпись пайщика}; председатель накладывает вторую подпись (signDocument(raw, chairman, 2, [document])) — канон APP-приёмки. Ownership: член КУ доставки (как в marketplaceReturnClaim). Follow-up: desktop OnSiteDecisionDialog (со-подпись на приёме) + zeus regen (generate-schema/generate-client/sdk build) — блокированы codegen-пайплайном. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Диспетчер событий по __typename (shared/lib/marketplace/marketplace-realtime) + composable useMarketplaceRealtime(handlers, {onResync}) с регистрацией на mount и снятием на unmount. Подписка marketplace разводит события: личные (заказ/приёмка) — прямая дочитка гейта, каталожные — в диспетчер. Каталог заказчика: остаток — точечный патч карточки по offer_id без перефетча и мельтешения; новый оффер и catch-up — debounced тихое обновление с сохранением загруженной глубины (страховочный resync 60с не дёргает прокрутку). OffererMyOffers переведён на realtime, polling 30с снят — одобрение/остаток мгновенно, отклонение подхватывает 60-сек catch-up канала. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Страница списания переверстана по канону: вкладки PageTabs «Кандидаты / На повестке / Архив» вместо россыпи карточек и списков; ленты проектов — канон- таблица .table-wrap с BaseBadge-статусами и EmptyState; CTA только на вкладке кандидатов. Документ Заявления 1108: сумма в формате «1 020,00 RUB» (2 знака, разделители), из преамбулы убрано «по итогам цикла», под заголовком добавлен город «г. {{ coop.city }}». Те же суммы 2-знака применены к Записке 1111. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Рендерер BaseDocument навязывает в Shadow DOM white-space: pre-wrap и th{width:30% !important}; пятиколоночный thead давал 5×30%=150% и таблица уезжала вправо («Причина» схлопывалась в столбик), а кастомные margin'ы вместо канонных переносов давали огромные вертикальные зазоры. Привёл оба документа 1-в-1 к style-блоку и структуре сиблингов (эталон 1106): addressee справа, заголовок по центру, город под подзаголовком справа; список позиций — многоколоночная таблица без <th> (шапка через <td><b>), суммы 2 знака.Документы 1108/1111: убран white-space:pre-wrap (рендерил переносы строк исходника и вместе с дефолтными margin'ами <p> удваивал разрывы — документ разъезжался по вертикали); спейсинг переведён на явные margin'ы по эталону уплотнённого 1110; '.digital-document { white-space: normal }' перебивает форсированный pre-wrap из Shadow DOM рендерера. Подписант 1108 — 'от Председателя Совета'. Диалог подписи: документ рендерится канон-компонентом DocumentHtmlReader в листе фиксированной ширины (на мобильном — во всю), без 60vh-обрубка. Детальная страница: журнал решений переведён на канон ActivityTimeline, убран служебный on-chain идентификатор. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>В повестке совета документ рендерит BaseDocument: он прогоняет html через sanitizeHtml (ВЫРЕЗАЕТ <style> документа) и форсит в Shadow DOM .digital-document{white-space:pre-wrap}. Прежняя вёрстка 1108/1111 полагалась на <style> с классами (.addressee/.title-block + margin'ы) — всё вырезалось, оставался pre-wrap → огромные отступы + выравнивание влево. Переверстано 1-в-1 по канон-документу 1106 (он корректен и в повестке, и в предпросмотре): выравнивание инлайн (style=text-align), вертикальный ритм — пустыми строками под pre-wrap, плотные абзацы — инлайн margin:0px, центр-заголовок — h1.header (shadowStyles центрирует .header). Добавлена колонка «Ед. изм.» (ед.) — у инвентаря нет поля единицы, склад считается в дискретных единицах, поэтому константа. Предпросмотр (SubmitToCouncilDialog): рендер html как есть, без класса .statement (тянул глобальный h1{line-height:4.5rem}) и без нормализатора, ломавшего pre-wrap — теперь идентичен повестке. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Колонка marketplace_writeoff_proposal.status была varchar(16), а статус PENDING_CONFIRMATION = 20 символов: callback совета onmktwoauth отлавливался, но UPDATE статуса молча падал «value too long» → проект навсегда застревал в ON_AGENDA (решение совета «не отлавливалось»). Расширил до 32. На колонке индекс (coopname,status), поэтому synchronize не смог изменить длину сам (recreate → ADD NOT NULL на непустой таблице) — расширение выполнено ALTER COLUMN TYPE на месте. Единицы измерения в Заявлении (1108) и Служебной записке (1111): вместо зашитой «ед.» бэкенд резолвит реальную единицу товара по партиям позиции (inventory → заказ/published_offer → offer.unit_of_measure → шт./кг/л/упак.), прокидывает в документ; шаблоны рендерят {{ it.unit }}. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>- BaseDocument.shadowStyles: .digital-document h1 { text-align:center } — заголовок (ПРОТОКОЛ №, СЛУЖЕБНАЯ ЗАПИСКА и пр.) центрируется на слое рендера, как в других документах; инлайн-стили выживают санитайзер, а блочные правила <style> — нет, поэтому правка шаблона существующий подписанный документ не центрировала - DocumentViewerDialog: убрал лишнюю обёртку-лист (ширину никто не просил, проблема была только в выравнивании заголовка) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Поставщик отклонял входящий заказ (decline=erase строки в chain-RAM), но заказ исчезал и тут же возвращался в «Ждут акцепта», а повторный decline/accept падал «не найден по хэшу». Причина: парсер на erase шлёт present=false с последним живым value строки ('active'); у терминального CANCELLED_BY_SUPPLIER forward-rank=undefined, поэтому updateFromBlockchain перетирал backend-статус обратно в ACTIVE. Guard: не менять статус, если заказ уже в терминальной отмене/возврате (mapper выдаёт только живые on-chain статусы, cancelled — KNOWN_UNMAPPED). +2 регрессионных теста. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Текст генерируемых документов учреждения кооперативного участка по замечаниям методолога. Структура он-чейн пакетов не затронута. - 323 Протокол собрания: убрано «кооперативного участка» из названия и meeting_name (просто «собрание пайщиков»); литерация «Протокол № КУ-N» сохранена. - Повестка собрания (desktop, KuMeetingDetails/onStart + KuMeetings): в каждый вопрос добавлена принадлежность «...потребительского кооператива «Восход»»; полномочие обратиться в совет вшито во второй вопрос (третий вопрос не нужен — методолог «три в два»). Имя кооператива из System store (vars.name / full_abbr_genitive). - 322 Бюллетень: в текст добавлено «потребительского кооператива «{name}»». - 324 Заявление в совет: «прошу Совет согласовать создание участка ... и согласовать кандидатуру избранного председателя». - 325 Решение совета: повестка разложена на 2 вопроса (учреждение + утверждение председателя и поручение Совету организовать сопровождение — банковский счёт, доверенность). - 327/328 Договоры матответственности: из названия убрано «ПОЛНОЙ ИНДИВИДУАЛЬНОЙ» (тело без изменений). - 329 Доверенность председателю КУ: переработана по эталону — реквизиты ПК в шапку, паспорт+регистрация инлайн в первый абзац, банковский счёт «№ —» (прочерк до открытия счёта в банке), ссылка на «Протокол № —» совета (прочерк), убран нижний блок «Уполномоченный: ФИО», подпись доверителя + М.П. - 330 Доверенность оператору: переработана по эталону — шапка «Кооперативный участок ... ПК ...», доверитель — председатель КУ, паспорт оператора инлайн, без банковского счёта, подпись + М.П. (КУ). Эталоны: ~/blago/production/shared/ШАБЛОН_Доверенность_*.pdf, ШАБЛОН_ДОГОВОР_О_МАТЕРИАЛЬНОЙ_ОТВЕТСТВЕННОСТИ_*.pdf Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Тот же промах, что и в предыдущем merge-коммите: zeus/{const,index}.ts регенерировались после первичного git add плейсхолдера и не попали в коммит. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.