feat(appointment): auto-expire unpaid bookings via Symfony Scheduler

Run the 15-min payment-expiry every minute through Symfony Scheduler so
unpaid pending bookings flip to expired without a system crontab. Install
symfony/scheduler; extract the expiry logic into AppointmentExpiryService
(reused by the existing command); add ExpireAppointmentsMessage + handler
and an #[AsSchedule] provider (RecurringMessage::every 1 minute); wire a
scheduler_default transport in messenger.yaml. Slots already free
just-in-time via isSlotTaken, so this only syncs the DB status.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
hamed
2026-06-15 22:43:50 +03:30
co-authored by Claude Opus 4.8
parent a348dcae5f
commit 71ab8892c9
12 changed files with 400 additions and 23 deletions
Generated
+86 -1
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "245ea537c0b4605205b72071da16ee4b",
"content-hash": "0fd2472709b043fbb4c5f1b34a590095",
"packages": [
{
"name": "doctrine/collections",
@@ -5178,6 +5178,91 @@
],
"time": "2026-05-23T18:04:28+00:00"
},
{
"name": "symfony/scheduler",
"version": "v7.4.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/scheduler.git",
"reference": "d8fff93e5d29af0262e5693b76376117259b4532"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/scheduler/zipball/d8fff93e5d29af0262e5693b76376117259b4532",
"reference": "d8fff93e5d29af0262e5693b76376117259b4532",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/clock": "^6.4|^7.0|^8.0"
},
"require-dev": {
"dragonmantank/cron-expression": "^3.1",
"symfony/cache": "^6.4.36|^7.4.8|^8.0.8",
"symfony/console": "^6.4|^7.0|^8.0",
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
"symfony/lock": "^6.4|^7.0|^8.0",
"symfony/messenger": "^6.4|^7.0|^8.0",
"symfony/serializer": "^6.4|^7.1|^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Scheduler\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sergey Rabochiy",
"email": "upyx.00@gmail.com"
},
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides scheduling through Symfony Messenger",
"homepage": "https://symfony.com",
"keywords": [
"cron",
"schedule",
"scheduler"
],
"support": {
"source": "https://github.com/symfony/scheduler/tree/v7.4.13"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-05-25T06:06:12+00:00"
},
{
"name": "symfony/security-bundle",
"version": "v7.4.13",