From 9ce0c625efa56c718a4dd964ea46f7a67c430bbc Mon Sep 17 00:00:00 2001 From: Konstantinos Arvanitakis Date: Tue, 29 Sep 2026 01:10:32 +0300 Subject: [PATCH] Bump version to 0.27.0 --- CHANGELOG.md | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ composer.json | 2 +- package.json | 2 +- 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd8cfe0..a76c73f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,105 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [0.27.0] - 2026-09-29 + +### Added +- `Modules\Core\Shipping\Contracts\SupportsCashCollection` — a shipping driver + implements this to say a person is physically present at handoff to collect + cash. `AcsRateDriver` implements it (a courier can); `BoxNowRateDriver` and + the new `StorePickupRateDriver` don't (an unattended locker or a store + clerk deciding to accept cash isn't the same fact as a courier collecting + it on delivery). `Modules\Core\Checkout\Services\CheckoutService:: + getPaymentMethods()` now checks this for cash-on-delivery specifically, so + COD is no longer offered alongside Box Now — `RequiresFulfillmentType` + alone couldn't distinguish "an unattended carrier" from "an attended one," + both being `carrier`. +- `Modules\Core\Shipping\Carriers\StorePickup\StorePickupRateDriver` — a + first-party replacement for `lunarphp/table-rate-shipping`'s own + `Collection` driver, following the same shape as `AcsRateDriver`/ + `BoxNowRateDriver`. Fixes two bugs the vendor driver had: it read + `ShippingMethod->name` directly instead of decoding the translatable JSON + column, so the storefront showed the raw JSON blob instead of a + translated name; and it never checked product exclusions the same way + the vendor's own generic drivers did. +- `Modules\Core\Shipping\Concerns\ExcludesRestrictedProducts` — shared + product-exclusion check (a shipping zone's configured "this product can't + ship via this method" list), now applied consistently by every + first-party driver (ACS, Box Now, Store Pickup). Previously only Lunar's + own generic drivers honored exclusions at all — ACS and Box Now silently + ignored them. +- `Modules\Core\Localization\Database\Seeders\StorefrontTranslationsSeeder` + — the `storefront` translation group is now seeded the same way + `checkout`/`validation` already are (a dedicated, idempotent seeder run + from the entrypoint), rather than as a private method inside + `InstallLunarCommand`. `Modules\Core\Localization\Services\ + StorefrontLabels` is removed; its ~160 lines moved into the new seeder. +- `StoreDetailsService::bankTransferInstructionsFor()` — sanitized HTML for + a bank transfer order's confirmation email, gated on + `OrderStatusFlow::isBankTransfer()`. +- `StoreServiceProvider::applyMailFromName()` — listens for + `Illuminate\Mail\Events\MessageSending` and renames the From header's + display name to Store Details' `mail_from_name`, when set, for every + outgoing email app-wide (order notifications, OTP codes, contact form + confirmations, etc.), no per-mailable changes needed. Only touches a + message whose From address still matches `config('mail.from.address')` + — the sending address itself is untouched (a deliverability/domain- + authentication concern, not a merchant-editable text field), and a + mailable/notification that already set its own explicit sender is left + alone entirely. +- `Order.meta['locale']` — the shopper's locale at checkout, saved by + `CheckoutService::initiatePayment()` so every order notification renders + in the locale they actually checked out in (via `Notification::locale()` + in `NotificationRegistry::register()`), independent of whatever locale + happens to be active when the notification is actually sent (a payment + webhook, a queued job, a staff action). +- `Order.meta['coupon_code']` — copied from the cart at checkout, so the + confirmation email always shows the code the order was actually placed + with, rather than reading the cart row (which may since have been + cleared/reused). +- Contact details on the storefront and product confirmation emails now + accept `$order` directly (all 8 order notification views), removing two + workarounds: `placed.blade.php` no longer reaches the order through + `$lines->first()->order`, and `status-updated.blade.php` no longer + reverse-searches a status key from its English label. + +### Changed +- The vendor's own generic shipping drivers (`free-shipping`, `flat-rate`, + `ship-by`, `collection`) are no longer offered at all — every shipping + method now uses a first-party driver (ACS, Box Now, or Store Pickup), + each of which declares its own fulfillment type. The `data.fulfillment_type` + Select on the shipping method form is removed, along with the + merchant-facing fallback it existed for — every registered driver now + hardcodes this fact about itself rather than a merchant configuring it + per row. +- `OrderCapturedNotification` ("payment captured") no longer sends for any + payment method except bank transfer. For every other method, placing the + order and paying for it are the same moment from the shopper's + perspective — `OrderPlacedNotification` already covers it. Bank transfer + is the one case where payment confirmation is a genuine, later, separate + event (staff marking the order paid once the wire arrives). +- `OrderStatusUpdatedNotification` no longer sends for an order's first + transition off `awaiting_payment`, except for a bank transfer order — + for every other payment method that transition happens in the same + request as checkout itself, so it's not new information the shopper + hasn't already been told. +- `OrderStatusUpdatedNotification`'s subject line now names the order's + actual current status ("Your order :reference is now :status") instead + of a generic "has been updated." +- The checkout page's payment methods now refresh live when the shipping + option changes, instead of requiring a full page reload — switching to + store pickup correctly drops cash-on-delivery and offers "pay in store" + immediately. + +### Fixed +- `StoreDetailsService::bankTransferInstructionsFor()` returned the raw + Tiptap JSON array `bank_transfer_instructions` is stored as, instead of + rendering it to HTML — the order confirmation email for a bank transfer + order failed outright (`TypeError`, queued job marked `FAIL`) rather than + showing the store's payment instructions. Now converts via Filament's own + `RichContentRenderer`, the same converter the admin panel itself uses to + render a `RichEditor` field's content read-only. + ## [0.26.5] - 2026-09-28 ### Added diff --git a/composer.json b/composer.json index 85d4975..ece4e5f 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "boboko/core", "description": "Core module — authentication and shared panel behaviour", "type": "library", - "version": "0.26.5", + "version": "0.27.0", "autoload": { "psr-4": { "Modules\\Core\\": "src/" diff --git a/package.json b/package.json index e6c2b8a..6698e9f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@boboko/core", - "version": "0.26.5", + "version": "0.27.0", "private": true, "type": "module", "description": "Portable Stimulus controllers and styles for boboko-core's cart + checkout module. Installed as a real npm dependency (file:../boboko-core in dev, a tagged git install in prod) so a consuming app's `npm install` resolves this package's own dependencies (leaflet, @hotwired/stimulus) transitively, the same way `composer update boboko/*` does for PHP. See CONTRIBUTE.md's \"JS/CSS: a real npm package\" section.",