3 min readAug 12, 2026by jakub

Changelog

Current version: 1.0.0

1.0.0

QuoteRequest

Initial release.

  • Four-table schema (qoliber_quote_request, _item, _comment, _history) with an extensible aggregate + repository pattern; money columns are decimal(20,4).
  • DI-configured state machine and the generic transition primitive (Api\State\TransitionServiceInterface) every caller — admin, customer, or cron — transitions through.
  • Api\QuoteRequestManagementInterface: createFromCart, review, sendProposal, negotiate, accept, reject, requestRevision, cancel, reopen, markOrdered, each guarded by optimistic concurrency (expectedVersion).
  • Api\Security\OwnershipGuardInterface: fail-closed ownership/visibility guard used by every consuming module.
  • Customer-safe and admin read-model DTOs plus their assemblers — the only shapes ever handed across the Core boundary.
  • Item, comment, and history repositories; history is read-only and recorded automatically by every transition.
  • Customer-deletion anonymization (Api\QuoteRequestCustomerDetacherInterface): nulls customer_id, preserves the row, the submission-time email/name/company snapshot, and the status.
  • Per-store increment-ID sequencing on Magento's own SalesSequence machinery, configurable prefix (default Q-).
  • Quotes do not reserve, hold, or decrement stock at any stage (see README).

Quality gate: phpcs (Magento2 + PSR-12 + PHPCompatibility 8.1–8.4), phpstan level 8 with no baseline, phpmd — all exit 0. Unit and integration suites green (see the family-wide totals in the metapackage release-hardening report).

QuoteRequestAdminUi

Initial release.

  • Admin grid over Core's admin read-model DTO.
  • Negotiation form and controllers (review, send proposal, cancel, reopen), each calling Core's QuoteRequestManagementInterface — no local transition logic.
  • Per-resource ACL, declared independently by every controller (Qoliber_QuoteRequest::view, ::send_proposal, ::cancel, ::reopen); denying one leaf leaves every other resource reachable.

Quality gate: phpcs, phpstan level 8 (no baseline), phpmd — all exit 0. Unit and integration suites green (see the family-wide totals in the metapackage release-hardening report).

QuoteRequestCheckout

Initial release.

  • Negotiated-price survival through Magento's totals/shipping recalculation, both tax-inclusive and tax-exclusive tax bases.
  • Cart lock: blocks cart-rule/coupon application on a cart bound to an accepted quote request.
  • Availability\ItemAvailabilityChecker: deleted/disabled/out-of-stock/qty-short precedence, aborts the cart load on any changed line rather than proceeding with stale availability.
  • Full accept → cart → order lifecycle, driven entirely through Core's QuoteRequestManagementInterface transition primitives — no local transition logic.
  • Quotes never reserve, hold, or decrement stock while under negotiation (see README).

Quality gate: phpcs, phpstan level 8 (no baseline), phpmd — all exit 0. Unit and integration suites green (see the family-wide totals in the metapackage release-hardening report).

QuoteRequestFrontend

Initial release.

  • Cart-page "Request a Quote" button submitting the current cart via Core's createFromCart.
  • My Quotes list + detail views over Core's customer-safe DTO, with Accept / Reject / Request Revision customer controllers, each calling Core's transition primitives.
  • Theme-agnostic ViewModels — all storefront logic lives in PHP, never .phtml, so the optional Hyvä package can be templates-only.
  • Ownership-guard coverage on every storefront controller (fail-closed); CSRF-safe state-changing actions; output-escaping on every customer-controlled field (customer_note, comment bodies, name, company).

Quality gate: phpcs, phpstan level 8 (no baseline), phpmd — all exit 0. Unit and integration suites green (see the family-wide totals in the metapackage release-hardening report).

QuoteRequestNotifications

Initial release.

  • Transactional outbox: transition-event observers enqueue synchronously in the same transaction as the transition — a send failure never rolls back a transition.
  • Drain cron with retry/backoff over the outbox.
  • Expiry cron transitioning quotes past their expiry window through Core's transition primitive; terminal states are never re-expired.
  • Email templates audited for raw-modifier XSS on customer-controlled variables — none found/used.

Quality gate: phpcs, phpstan level 8 (no baseline), phpmd — all exit 0. Unit and integration suites green (see the family-wide totals in the metapackage release-hardening report).

Changelog — Quote Request — Sales & Payments — Extensions | qoliber Docs