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 aredecimal(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): nullscustomer_id, preserves the row, the submission-time email/name/company snapshot, and the status. - Per-store increment-ID sequencing on Magento's own
SalesSequencemachinery, configurable prefix (defaultQ-). - 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
QuoteRequestManagementInterfacetransition 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).