Repository navigation
4.13.0 dev - #313
Merged
Merged
4.13.0 dev#313
Conversation
- Hide payment QR, PDF header/footer snippets and image upload for email templates - Keep snippet sidebar in view while scrolling; let the editor shrink in narrow windows - Mark root-level dates in the schema, guard nullable dates with data-if on insert - Describe portal fee snippets, clarify the embedded template tooltip - Fix paste/drop in the visual editor and loop autocomplete swallowing text
AI assistants (Claude Code, Cursor, n8n, ...) can connect to /mcp to evaluate data, check availability and prices and create reservations. - symfony/mcp-bundle with stateless and session-based MCP revisions; JSON responses only, subscriptions/listen refused and no listChanged capability, so no stream pins a PHP-FPM worker - Off by default: operator switch MCP_ENABLED, admin switches under Settings > AI assistants (allowed host names, reservation writes) - Tokens with the use "AI assistant" (scope mcp:access) only work at /mcp and must expire; the REST API rejects them. New scopes guests:read and reservations:write, always bound to the owner's roles - Every tool declares #[McpRequiresScope], enforced centrally by ScopedReferenceHandler (fail closed) and written to mcp_tool_call_log; entity changes record channel and token prefix - Guest names, contact data and remarks only with guests:read; free text is marked as untrusted_text - 14 read and booking tools; reservations are booked via preview token (idempotent), strict availability check under a row lock, optional extras, and notify staff through the new assistant_booking.created workflow trigger (system workflow seeded when MCP is switched on) - Session-free ReservationBookingService; REST query logic moved into shared services (reservations, invoices, stay parameters, statistics, tourist tax) used by REST and MCP alike - Keep MCP debug logs with tool arguments out of the prod error buffer - Move InvalidInvoiceNumberPatternException to App\Exception
Hoteliers who want to know something like the planned arrival time had no way to ask for it without adding another field to the form, and every extra field is one more hurdle for guests. A placeholder in the existing comment field asks the question without making the form any longer. The text is set under Settings > Online booking > Checkout texts, stored as plain text (max. 255 characters) and rendered as the textarea's placeholder attribute, escaped by Twig. Empty means no placeholder, so nothing changes for existing installations. The classic theme gets the attribute as well. Its templates are frozen for custom CSS, but an attribute leaves structure and classes untouched, and without it the setting would silently do nothing there.
- Settings: paginate the MCP tool call log like the workflow log; paginator accepts an optional CSS class - get_operations_report: room plan per day with housekeeping status and booked extras; new AI scope operations:read (ROLE_OPERATIONS); prompt daily_operations_briefing - Read-only pricing tools: get_rate_calendar (nights merged into periods), get_price_rules, get_occupancy_forecast (AvailabilityService::getRoomNightsPerDay), get_booking_pace (previous-year comparison); prompt price_review - Special prices: preview_special_price / create_special_price via session-free SpecialPriceService; new AI scope prices:write (administrators only); conflicts are only overwritten with consent, uninvoiced reservations in the period are listed as a warning - Price periods get an optional description (price form, overview, REST API, OpenAPI)
…prepare them - Drafts move from the session to bank_import_drafts: private per user, deleted after 2 days without changes (on access and by app:purge-logs), edits lock the draft row, excluded from the change log - Line editing rules extracted to BankImportLineEditor, shared by the bank import pages and MCP - MCP: list_bank_import_drafts, get_bank_import_lines, get_bank_import_context, update_bank_import_lines; new AI scope bank-import:write (ROLE_CASHJOURNAL), purposes as untrusted_text, IBANs shortened
The due date so far always followed the payment period in the invoice settings. An invoice can now carry a date of its own, set when it is created or later in the edit modal: a number of days from the invoice date, the last departure of its room positions, or a fixed date. Only the resulting date is stored (invoices.payment_due_date); days and departure are ways of entering it. An issued invoice therefore keeps its date when its date or positions change later. Invoices without one keep following the settings, so nothing changes for existing data. Invoice::resolvePaymentDueDate() is the single place that decides, and the invoice view, the template variable paymentDueDate, the ZUGFeRD payment terms and the EN 16931 check all read it.
"X days after invoice date" offers each invoice on one fixed day, so a payment reminder built on it goes out too early once an invoice has a later due date of its own. A condition cannot fix that: it can refuse the day, not postpone it. The new trigger invoice.days_after_due_date matches on the due date the invoice prints (Invoice::resolvePaymentDueDate()). Days may be 0 (on the due date) or negative (before it). The query narrows candidates by the configured payment periods and resolves each one, since a due date without an own date depends on the issuer that applies to the invoice.
Follows the review on #303. The due date is now always stored: a new invoice gets the invoice date plus its issuer's period when it is created (prefilled in the form, and set by a prePersist listener for every other way an invoice is made), and the migration fixes the date existing invoices have been printing. A later change of the period in the settings no longer rewrites invoices already sent. A rollback is refused while an invoice has a date other than its settings give. The dialog has a single date field. A number of days and the last departure are helpers next to it that fill in the date in the browser; they carry no name, so they are never submitted and cannot block saving. The mode choice and its help text are gone; the label reads "Fälligkeitsdatum". With every invoice carrying its date, the "X days after the due date" trigger selects ids by payment_due_date and limits in the query instead of loading and resolving candidates. InvoiceService no longer needs the settings resolver.
Bookings keep the price they were booked at (room nights, guest adjustments, extras); later price list changes only apply to new bookings. Existing invoices are untouched. - price promise as JSON on reservations, written on every create/edit path - open bookings without invoice are promised today's price before the first price change - price tab shows when today's prices differ and lets you apply them - prices still used by an open booking are deactivated instead of deleted - fix child discount positions for stays across different price rows
Rules change room prices by weekday, period, lead time or occupancy, for one, several or all subsidiaries and room categories. Matching rules are added up and held within configurable limits and rounding. - new "Price rules" tab with templates, live preview and limits - rules apply to quotes, online booking, new bookings and the rate calendar; existing bookings keep their promised price - occupancy per subsidiary, optionally counted across subsidiaries - reservation shows which rules are part of the room price - online and MCP bookings only at the price shown (create_reservation now takes expectedTotal) - hint to price rules in the period section of the price form
Follows the second review on #303. The due date now sits with number and invoice date: in the creation step between them (saved on the fly like both), in the number and date dialog when editing, and in the invoice header as a label-value line below them. The payment method and remark form is back to its original shape. Next to the date field, a small menu sets it to the issuer's standard period, an own number of days typed into the menu, or the last departure. The departure is only offered while it does not lie before the invoice date, and a moved invoice date takes the due date along at the same distance. The menu carries no names, so only the date is ever submitted. The invoice header shows number, invoice date and due date as three label-value lines, so it is no taller than the address beside it.
The price calendar shows per branch, room category and occupancy what a night costs today and why. Day prices set a fixed price for single nights or ranges and take the place of the price rules there. - day price stated for an occupancy; other occupancies and origins follow in proportion - manual day prices are exact; assistant/API ones stay within limits - phone list and desktop month grid, night details in an offcanvas - reservation and rate calendar show day prices
…day prices and availability
… canceled invoices when fixing a booking's promised price
Agreed on #303. Next to the last departure, the due date menu now offers the earliest arrival of the room positions. Both follow the same rule: offered only while they do not lie before the invoice date, and the divider above them goes when neither is.
In the normal view on touch screens the first swipe up hides the navbar, the second the filter row and the third opens the week view. Closing the week view brings the normal view back with navbar and filter row.
…hown The line sat on the first header row (the month row), so it went missing when the table settings hid that row; with navbar and filter row swiped away the gap showed at the top of the screen. The scroll container now draws it in every view, as the week view already did.
The floating button now appears on all touch devices, tablets included, instead of below a width; with a mouse the button in the filter row stays. It is drawn as translucent glass in the manner of iOS 26: the content behind it blurred, a fine light edge and a soft shadow, with a dark variant for the dark theme.
…ce-template-payment-means # Conflicts: # translations/Templates/messages.de.xlf
…ayment-means feat: pick the invoice template by payment means
- Navbar, filter row and the normal view's header rows are slimmer on touch screens (navbar 82 -> 58px, filter row and table header together about 80px less on a tablet); desktop keeps its sizes. - The filter row is vertically centred and fits one line from 576px, so also on phones held sideways; tighter spacing on touch screens. - The notification badge stays inside the slimmer bar, and the menu button is white like the rest of the bar.
The opaque holiday tint only applied to holidays on a weekend; on a weekday the header cell kept Bootstrap's translucent bg-info bg-opacity-25, and reservation bars showed through it when scrolling.
…uch screens - Going back with the browser left the reservation overview without its listeners (no swiping, paging, week view): the setup flag was an attribute that Turbo's page cache kept. It is a property now, and the controller clears it and its modal observer on disconnect. - The side menu is cleaned up synchronously before Turbo caches the page; Offcanvas.hide() released the body's scroll lock only after the animation. - The side menu is for touch screens below lg (phones, tablets upright); with a mouse the bar is always expanded and wraps in a narrow window. Below xl the user menu shows its icon only. - Menu button without frame and without the focus ring after a tap. - Following the new AGENTS.md rules: theme variables instead of fixed colours for the glass button and the menu button, text-body-secondary instead of text-secondary for the filter row's icons.
…lash - In the touch week view a swipe down returns to the normal view as it was before the third swipe up, with navbar and filter row still hidden; a swipe up still restores the complete normal view. - Switching between normal and week view hides the table until the new one has loaded, so the old table no longer flashes up in the new layout.
…ens only As before, desktop gets the side menu below xl. Touch screens switch to lg on connect, so a tablet held sideways keeps the full bar. The collapsed-state rules are tied to the expand class in use; the always-expanded desktop bar is gone.
#308 feat(reservations): week view for the reservation table
…lease notes; fix: keep the due date test independent of the last invoice number
…'t prefill partial companion addresses; updated release notes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.