Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ZMSKVR-72): create closure for specific day and office #915

Open
wants to merge 4 commits into
base: next
Choose a base branch
from

Conversation

manjencic
Copy link
Contributor

@manjencic manjencic commented Feb 28, 2025

Pull Request Checklist (Feature Branch to next):

  • Ich habe die neuesten Änderungen aus dem next Branch in meinen Feature-Branch gemergt.
  • Das Code-Review wurde abgeschlossen.
  • Fachliche Tests wurden durchgeführt und sind abgeschlossen.

Summary by CodeRabbit

  • New Features

    • Added interactive controls on the availability day page to toggle closure (blocked) status with real-time feedback.
    • Updated calendar views with clear visual indicators and an enhanced legend to highlight blocked dates.
    • Extended API functionality to support dynamic management of closure status.
  • Chores

    • Implemented backend enhancements and database support to reliably manage closure data.

Copy link
Contributor

coderabbitai bot commented Feb 28, 2025

Walkthrough

This pull request introduces a new closure management feature across multiple application layers. Two new POST routes have been added—one for the admin interface and another for the API—to toggle the closure status for a specified scope on a given date. New controller classes have been created to handle these requests. In addition, the templates are updated to display closure indicators, and the back-end has been extended with new database models, query builders, JSON schemas, and entity classes dealing with closures. Finally, an SQL migration creates the necessary table in the database.

Changes

File(s) Changes Summary
zmsadmin/routing.php, zmsapi/routing.php Added new POST routes for toggling availability closures (admin and API endpoints).
zmsadmin/src/Zmsadmin/ScopeAvailabilityDayClosure.php, zmsapi/src/Zmsapi/AvailabilityClosureToggle.php Introduced new controller classes to handle HTTP requests for toggling closure status.
zmsadmin/templates/block/availability/monthtable.twig, zmsadmin/templates/block/calendar/legend.twig, zmsadmin/templates/page/availabilityday.twig Updated Twig templates to add closure icons, a legend entry for "Gesperrt", and an AJAX-based UI for toggling closures.
zmsadmin/src/Zmsadmin/ScopeAvailabilityMonth.php Modified the JSON response to include a new closureList entry by importing the Closure entity.
zmsdb/src/Zmsdb/Closure.php, zmsdb/src/Zmsdb/Query/Closure.php, zmsdb/src/Zmsdb/Query/Day.php, zmsdb/src/Zmsdb/Query/ProcessStatusFree.php, zmsdb/src/Zmsdb/Scope.php Added a new database model for closures, query builders for managing closure conditions, updated SQL queries to join and filter closures, and extended scope references to incorporate closure data.
zmsentities/schema/closure.json, zmsentities/schema/dereferenced/closure.json, zmsentities/schema/dereferenced/scope.json, zmsentities/schema/scope.json, zmsentities/src/Zmsentities/Closure.php, zmsentities/src/Zmsentities/Collection/ClosureList.php, zmsentities/src/Zmsentities/Scope.php Defined new JSON schemas for closures and added a "closure" property to the scope schema; introduced new entity and collection classes for closure management, including a getter method in the Scope entity.
zmsdb/migrations/91740751372-create-closures-table.sql Created a new SQL migration file to generate the closures table with appropriate columns and indexes.
zmsdb/src/Zmsdb/DayOff.php Added a new import for the DayoffList class.
zmsapi/cron/cronjob.minutly Inserted additional echo statements for debugging without altering the core deletion logic.

Sequence Diagram(s)

sequenceDiagram
    participant User as Admin User
    participant Browser as Web Browser
    participant JS as ToggleFunction (JS)
    participant Route as zmsadmin Routing
    participant Controller as ScopeAvailabilityDayClosure
    participant DB as Database Layer

    User->>Browser: Load availability day page
    Browser->>JS: Render toggle closure button
    User->>Browser: Click "Toggle Closure"
    Browser->>JS: Execute toggleClosure()
    JS->>Route: AJAX POST /scope/{id}/availability/day/{date}/closure/toggle/
    Route->>Controller: Dispatch request
    Controller->>DB: Toggle closure record for given scope/date
    DB-->>Controller: Return closure data
    Controller-->>Route: Return JSON response
    Route-->>JS: Send response
    JS->>Browser: Update UI based on response
Loading
sequenceDiagram
    participant Client as API Client
    participant API_Router as zmsapi Routing
    participant API_Controller as AvailabilityClosureToggle
    participant DB as Database Layer

    Client->>API_Router: POST /scope/{id}/availability/{date}/closure/toggle/
    API_Router->>API_Controller: Dispatch request
    API_Controller->>DB: Validate and toggle closure record
    DB-->>API_Controller: Return updated closure info
    API_Controller-->>API_Router: Construct JSON response
    API_Router-->>Client: Return response
Loading

Suggested reviewers

  • ThomasAFink

Poem

I'm just a bunny, hopping through code so bright,
Toggling closures by day and by night,
Routes and queries now dance in a row,
With icons and legends putting on a show.
May each toggle bring magic in every byte,
Hoppy code and whiskers—a delight in sight!
🐰✨


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7166beb and cfcc1b6.

📒 Files selected for processing (1)
  • zmsdb/migrations/91740751372-create-closures-table.sql (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • zmsdb/migrations/91740751372-create-closures-table.sql
⏰ Context from checks skipped due to timeout of 90000ms (17)
  • GitHub Check: CodeQL
  • GitHub Check: call-owasp-security-checks / security-scan (zmsclient, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsdb, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsslim, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsentities, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsdldb, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsticketprinter, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsstatistic, 8.0)
  • GitHub Check: call-php-unit-tests / zmsdb-test
  • GitHub Check: call-owasp-security-checks / security-scan (zmsmessaging, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmscitizenapi, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmscalldisplay, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsapi, 8.0)
  • GitHub Check: Analyze (python)
  • GitHub Check: call-php-unit-tests / zmsapi-test
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsadmin, 8.0)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (24)
zmsentities/schema/closure.json (1)

1-25: Schema definition follows best practices but has a capitalization inconsistency

The schema definition for closure follows JSON schema best practices with clear type definitions, descriptions, and required fields. However, there's an inconsistency in property naming convention - "Datum" uses Pascal case while other properties like "id" and "lastChange" use camelCase.

Consider renaming "Datum" to "datum" for consistency with other property names across the codebase.

-        "Datum": 1447924981
+        "datum": 1447924981

And the same change in the properties section:

-        "Datum": {
+        "datum": {
zmsentities/schema/dereferenced/scope.json (1)

234-257: Dereferenced schema maintains the same capitalization inconsistency

The dereferenced schema correctly inlines the closure schema definition, but it carries forward the same capitalization inconsistency with the "Datum" property noted in the closure.json file.

For consistency with other property names in the schema, consider renaming "Datum" to "datum" here as well.

-                    "Datum": 1447924981
+                    "datum": 1447924981

And:

-                    "Datum": {
+                    "datum": {
zmsentities/schema/dereferenced/closure.json (2)

2-25: The closure schema structure looks good, but consider some improvements.

The schema is well-structured with clear property definitions and appropriate restrictions. However, there are a few suggestions:

  1. The property Datum (German) is inconsistent with other English property names (id, lastChange). Consider using consistent language in the schema.
  2. The example object could include all properties, including lastChange.
  3. I notice that in the SQL queries, there's a StandortID column referenced when joining with the closures table, but this field isn't represented in this schema.

16-19: Consider using ISO 8601 for date representation.

While Unix timestamps are valid for date/time representation, ISO 8601 format might be more human-readable and consistent with modern API practices.

zmsdb/src/Zmsdb/Query/Day.php (2)

87-87: LEFT JOIN implementation is correct but has naming inconsistency.

The LEFT JOIN with the closures table is correctly implemented to match records based on scope, year, month, and day. However, there's a naming inconsistency: StandortID uses PascalCase while other columns use camelCase (scopeID, year, month, day).

Consider standardizing the column naming convention across the database.


89-89: Add a comment explaining the HAVING clause.

The HAVING clause correctly filters out slots that have corresponding closures. However, adding a comment would improve code readability and maintainability.

-            HAVING cc.id IS NULL
+            -- Filter out slots that are marked as closed
+            HAVING cc.id IS NULL
zmsdb/src/Zmsdb/Query/ProcessStatusFree.php (2)

33-34: Consider explicitly listing needed columns instead of using s.*.

Using s.* simplifies the query, but it can impact performance by retrieving unnecessary columns from the slot table. Consider explicitly listing only the required columns.


48-48: Add a comment explaining the HAVING clause.

Similar to the suggestion for Day.php, adding a comment would improve code readability and maintainability.

-            HAVING cc.id IS NULL
+            -- Filter out slots that are marked as closed
+            HAVING cc.id IS NULL
zmsadmin/src/Zmsadmin/ScopeAvailabilityMonth.php (1)

13-13: Added import for Closure class.

The import is correctly added, though it appears to be unused in the current implementation since we're only accessing the closure list through the scope object. Consider removing this import if it's not needed.

-use BO\Zmsentities\Closure;
zmsapi/routing.php (1)

4142-4184: Minor typo and parameter type mismatch in Swagger documentation.

The new endpoint for toggling availability closure looks well-structured, but there are two small issues in the Swagger documentation:

  1. In the summary, "Toogle" should be "Toggle"
  2. The "date" parameter is described as type "integer" but based on the format YYYY-MM-DD, it should be of type "string"
-          summary: Toogle availability closure for specific day
+          summary: Toggle availability closure for specific day
-                  type: integer
+                  type: string
zmsadmin/src/Zmsadmin/ScopeAvailabilityDayClosure.php (1)

26-27: Add input validation for parameters

The code retrieves scopeId and date from the arguments array but doesn't validate these values before using them.

Consider adding validation to ensure the parameters exist and are in the expected format:

-        $scopeId = $args['id'];
-        $date = $args['date'];
+        $scopeId = isset($args['id']) ? $args['id'] : null;
+        $date = isset($args['date']) ? $args['date'] : null;
+        
+        if (!$scopeId || !$date || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
+            return \BO\Slim\Render::withJson(
+                $response->withStatus(400),
+                ['error' => 'Invalid scope ID or date format']
+            );
+        }
zmsdb/migrations/91740144530-create-closures-table.sql (3)

3-10: Add NOT NULL constraints for required fields

The table definition does not specify which columns are required. If certain columns like year, month, day, and StandortID are mandatory for a closure, they should have the NOT NULL constraint.

 CREATE TABLE `closures` (
    `id` INT(5) UNSIGNED AUTO_INCREMENT,
-   `year` SMALLINT(5),
-   `month` TINYINT(5),
-   `day` TINYINT(5),
-   `StandortID` INT(5) UNSIGNED,
+   `year` SMALLINT(5) NOT NULL,
+   `month` TINYINT(5) NOT NULL,
+   `day` TINYINT(5) NOT NULL,
+   `StandortID` INT(5) UNSIGNED NOT NULL,
    `updateTimestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

7-7: Consider consistent column naming convention

The column name StandortID uses PascalCase while other columns use snake_case. For consistency, consider using snake_case for all column names.

-   `StandortID` INT(5) UNSIGNED,
+   `standort_id` INT(5) UNSIGNED,

Note: If this is following an existing convention in your database schema, you can disregard this suggestion.


7-11: Consider adding foreign key constraint

If StandortID references a primary key in another table (like a 'standorts' or 'scopes' table), consider adding a foreign key constraint to maintain referential integrity.

   `StandortID` INT(5) UNSIGNED,
   `updateTimestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
   PRIMARY KEY (`id`),
   INDEX (StandortID),
-  INDEX (StandortID, year, month, day)
+  INDEX (StandortID, year, month, day),
+  FOREIGN KEY (StandortID) REFERENCES standorts(id) ON DELETE CASCADE

Replace standorts(id) with the actual table and column name that StandortID references.

zmsadmin/templates/page/availabilityday.twig (2)

40-65: Improve error handling and user feedback in AJAX call

The current implementation only logs errors to the console when the AJAX request fails. Users should be informed about failures.

                }).fail(err => {
                    console.log('error', err)
+                    alert('Fehler beim Aktualisieren des Sperrstatus. Bitte versuchen Sie es erneut.')
                })

Additionally, consider adding a loading state to the button while the request is in progress:

            function toggleClosure() {
                const ok = confirm('Möchten Sie wirklich Die Terminbuchung für diesen Tag {% if locked %}entsperren{% else %}sperren{% endif %}?')
                if (!ok) {
                    return
                }

+               const button = event.target
+               const originalText = button.value
+               button.value = 'Wird bearbeitet...'
+               button.disabled = true

                const currentDate = '{{ dateString }}'
                const url = `{{ includeUrl() }}/scope/{{ scope.id }}/availability/day/${currentDate}/closure/toggle/`
                $.ajax(url, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    data: JSON.stringify({})
                }).done(data => {
                    if (data.closure.existing) {
                        document.getElementById('closure-close').classList.remove('hidden')
                        document.getElementById('closure-open').classList.add('hidden')
                    } else {
                        document.getElementById('closure-close').classList.add('hidden')
                        document.getElementById('closure-open').classList.remove('hidden')
                    }
+                   button.value = originalText
+                   button.disabled = false
                }).fail(err => {
                    console.log('error', err)
+                   alert('Fehler beim Aktualisieren des Sperrstatus. Bitte versuchen Sie es erneut.')
+                   button.value = originalText
+                   button.disabled = false
                })
            }

33-38: Add ARIA attributes for accessibility

The message divs should have appropriate ARIA attributes for better accessibility.

-        <div id="closure-close" class="message message--warning {% if not locked %}hidden{% endif %}">
+        <div id="closure-close" class="message message--warning {% if not locked %}hidden{% endif %}" role="alert" aria-live="polite">
             Die Terminbuchung für diesen Tag ist gesperrt. <input class="button btn" style="margin-top: -6px;" type="button" onclick="toggleClosure()" value="Entsperren">
         </div>
-        <div id="closure-open" class="message message--info {% if locked %}hidden{% endif %}">
+        <div id="closure-open" class="message message--info {% if locked %}hidden{% endif %}" role="alert" aria-live="polite">
             Die Terminbuchung für diesen Tag ist NICHT gesperrt. <input class="button btn" style="margin-top: -6px;" onclick="toggleClosure()" type="button" value="Sperren">
         </div>
zmsdb/src/Zmsdb/Query/Closure.php (2)

19-28: Add type hinting and documentation to getEntityMapping method

The getEntityMapping method would benefit from return type hinting and better documentation.

-    public function getEntityMapping()
+    /**
+     * Returns the mapping between entity attributes and database fields
+     *
+     * @return array Associative array mapping entity attributes to database fields
+     */
+    public function getEntityMapping(): array
     {
         return [
             'id' => 'closure.id',
             'year' => 'closure.year',
             'month' => 'closure.month',
             'day' => 'closure.day',
             'lastChange' => 'closure.updateTimestamp'
         ];
     }

30-36: Add type validation in addConditionDate method

The addConditionDate method doesn't validate that the parameter is actually a DateTime object.

-    public function addConditionDate(DateTime $date)
+    /**
+     * Adds conditions to the query for a specific date
+     *
+     * @param DateTime $date The date to filter by
+     * @return $this For method chaining
+     * @throws \InvalidArgumentException If date is not a DateTime object
+     */
+    public function addConditionDate(DateTime $date)
     {
+        if (!($date instanceof DateTime)) {
+            throw new \InvalidArgumentException('Date must be a DateTime object');
+        }
         $this->query->where('closure.year', '=', $date->format('Y'));
         $this->query->where('closure.month', '=', $date->format('m'));
         $this->query->where('closure.day', '=', $date->format('d'));
         return $this;
     }

Note: The type hint in the method signature already enforces that $date is a DateTime object, so the runtime check isn't strictly necessary. However, adding the check with an informative error message provides better diagnostics.

zmsdb/src/Zmsdb/Closure.php (2)

18-24: Simplify collection handling.

The current loop logic for adding entities to the collection can be simplified.

if (count($result)) {
-    foreach ($result as $entity) {
-        if ($entity instanceof Entity) {
-            $closureList->addEntity($entity);
-        }
-    }
+    $closureList->addEntities(array_filter($result, function($entity) {
+        return $entity instanceof Entity;
+    }));
}

42-42: Remove unnecessary parentheses.

The parentheses around the return statement are unnecessary.

-return ($this->deleteItem($query));
+return $this->deleteItem($query);
zmsentities/src/Zmsentities/Closure.php (2)

38-41: Fix parameter name typo.

There's a typo in the parameter name availabiliy which should be availability.

-public function isAffectingAvailability(Availability $availabiliy, \DateTimeInterface $now)
+public function isAffectingAvailability(Availability $availability, \DateTimeInterface $now)
{
-    return $availabiliy->isBookable($this->getDateTime(), $now);
+    return $availability->isBookable($this->getDateTime(), $now);
}

22-22: Ensure date formatting is robust.

The date components are concatenated with hyphens, which might cause issues if month or day is single-digit.

-return (new \BO\Zmsentities\Helper\DateTime($this->year . '-' . $this->month . '-' . $this->day));
+return (new \BO\Zmsentities\Helper\DateTime(sprintf('%04d-%02d-%02d', $this->year, $this->month, $this->day)));
zmsentities/src/Zmsentities/Collection/ClosureList.php (2)

25-34: Optimize getEntityByName method.

The current implementation continues iterating after finding a match. Use early return for better performance.

public function getEntityByName($name)
{
-    $result = null;
    foreach ($this as $entity) {
        if ($entity->name == $name) {
-            $result = $entity;
+            return $entity;
        }
    }
-    return $result;
+    return null;
}

60-69: Enhance documentation for withNew method.

This method appears to create a new collection containing only the entities from the input collection that aren't already in the current collection, based on date. Consider adding more comprehensive documentation.

+/**
+ * Returns a new collection containing only entities from the input 
+ * collection that don't have matching dates in the current collection.
+ *
+ * @param ClosureList $closureList The input collection to check
+ * @return ClosureList A new collection with only new entities
+ */
public function withNew(ClosureList $closureList)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d00044 and 0154a8a.

📒 Files selected for processing (23)
  • zmsadmin/routing.php (1 hunks)
  • zmsadmin/src/Zmsadmin/ScopeAvailabilityDayClosure.php (1 hunks)
  • zmsadmin/src/Zmsadmin/ScopeAvailabilityMonth.php (2 hunks)
  • zmsadmin/templates/block/availability/monthtable.twig (1 hunks)
  • zmsadmin/templates/block/calendar/legend.twig (1 hunks)
  • zmsadmin/templates/page/availabilityday.twig (2 hunks)
  • zmsapi/cron/cronjob.minutly (1 hunks)
  • zmsapi/routing.php (1 hunks)
  • zmsapi/src/Zmsapi/AvailabilityClosureToggle.php (1 hunks)
  • zmsdb/migrations/91740144530-create-closures-table.sql (1 hunks)
  • zmsdb/src/Zmsdb/Closure.php (1 hunks)
  • zmsdb/src/Zmsdb/DayOff.php (1 hunks)
  • zmsdb/src/Zmsdb/Query/Closure.php (1 hunks)
  • zmsdb/src/Zmsdb/Query/Day.php (2 hunks)
  • zmsdb/src/Zmsdb/Query/ProcessStatusFree.php (2 hunks)
  • zmsdb/src/Zmsdb/Scope.php (1 hunks)
  • zmsentities/schema/closure.json (1 hunks)
  • zmsentities/schema/dereferenced/closure.json (1 hunks)
  • zmsentities/schema/dereferenced/scope.json (1 hunks)
  • zmsentities/schema/scope.json (1 hunks)
  • zmsentities/src/Zmsentities/Closure.php (1 hunks)
  • zmsentities/src/Zmsentities/Collection/ClosureList.php (1 hunks)
  • zmsentities/src/Zmsentities/Scope.php (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • zmsdb/src/Zmsdb/DayOff.php
  • zmsapi/cron/cronjob.minutly
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsslim, 8.0)
  • GitHub Check: call-php-unit-tests / module-test (zmsticketprinter, 8.0)
  • GitHub Check: call-php-unit-tests / module-test (zmsstatistic, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsticketprinter, 8.0)
  • GitHub Check: call-php-unit-tests / module-test (zmsslim, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsmessaging, 8.0)
  • GitHub Check: call-php-unit-tests / zmsdb-test
  • GitHub Check: call-php-unit-tests / zmsclient-test
  • GitHub Check: call-owasp-security-checks / security-scan (zmsapi, 8.0)
  • GitHub Check: call-php-unit-tests / zmsapi-test
🔇 Additional comments (15)
zmsentities/schema/scope.json (1)

136-141: Appropriate addition of closure schema reference

The "closure" property has been correctly added to the scope schema, following the same pattern as the existing "dayoff" property. This is a clean implementation that maintains consistency with the existing schema structure.

zmsadmin/routing.php (1)

495-496: Well-structured route that follows established patterns

The new route for toggling closure status follows the existing routing patterns in the application. It's appropriately placed at the end of the file and correctly uses the POST method for a state-changing operation.

zmsadmin/templates/block/calendar/legend.twig (1)

52-52: The calendar legend entry for "Gesperrt" looks good!

The addition of this entry with the red 'X' icon provides a clear visual indicator for blocked/closed days, which aligns well with the PR objective to create closures for specific days and offices.

zmsdb/src/Zmsdb/Query/Day.php (1)

77-78: Column added for closure ID looks good.

Adding the cc.id column is necessary for the closure filtering logic.

zmsdb/src/Zmsdb/Query/ProcessStatusFree.php (1)

46-46: LEFT JOIN implementation is consistent with Day.php.

The LEFT JOIN with the closures table matches the implementation in Day.php, which ensures consistent handling of closures across different queries. However, the same naming inconsistency with StandortID exists here.

zmsdb/src/Zmsdb/Scope.php (1)

43-43: Good integration of the closure data retrieval.

The new line correctly follows the established pattern for loading related data when resolving scope references. This addition ensures that closure information will be available when requested with the proper resolve level.

zmsentities/src/Zmsentities/Scope.php (2)

5-5: Properly added import for ClosureList.

The import statement is correctly placed with other imports at the beginning of the file.


108-120: Well-structured implementation of getClosureList method.

The method follows the same pattern as the existing getDayoffList() method, ensuring consistency in code style and behavior. It properly handles type checking, initialization, and entity conversion, which will make working with closure entities more reliable.

zmsadmin/templates/block/availability/monthtable.twig (2)

94-96: Good addition of closure status indicator.

The conditional check for closures and the corresponding icon display are implemented correctly. This provides visual feedback for users when a day has been marked as closed.


100-104: Improved HTML structure for holiday row.

The minor formatting changes to the holiday row improve readability and consistency with the rest of the template.

zmsadmin/src/Zmsadmin/ScopeAvailabilityMonth.php (1)

71-71: Properly integrated closure list into the template response.

The closure list is correctly added to the template context, allowing the template to access and display closure information.

zmsapi/src/Zmsapi/AvailabilityClosureToggle.php (1)

48-49:

❓ Verification inconclusive

Consider validating date format.

The date parameter is directly used without validation, which could lead to errors if an invalid date is provided.


🏁 Script executed:

#!/bin/bash
# Check the routing configuration to see if there's any validation at that level
rg -A 5 "availability/day/{date:.+}/closure/toggle" --type php

Length of output: 206


Attention: Date Parameter Validation Requires Manual Verification

The current implementation assigns the date parameter without any explicit format validation. While the route configuration might be expected to enforce a proper format, our automated check using the regex pattern availability/day/{date:.+}/closure/toggle failed due to a syntax issue (the curly braces were not escaped). This leaves us without automated confirmation that the date is being validated elsewhere.

  • The assignment of $date in zmsapi/src/Zmsapi/AvailabilityClosureToggle.php (lines 48-49) does not include any validation.
  • The attempted route-level verification yielded a regex parse error, so please manually verify if the routing layer or any middleware is responsible for validating the date format.
  • If no validation exists upstream, consider adding a check (e.g., using DateTime::createFromFormat or a similar approach) to ensure the date parameter conforms to the expected format.
zmsdb/src/Zmsdb/Closure.php (1)

50-54:

❓ Verification inconclusive

Consider removing redundant type casting.

The explicit casting to int might be redundant if the database query handles it properly.


🏁 Script executed:

#!/bin/bash
# Check the Closure query implementation to understand the expected data types
rg -A 10 "class Closure" --type php -- "src/Zmsdb/Query"

Length of output: 112


Next Steps: Manual Verification of Casting Redundancy

The search for a "src/Zmsdb/Query" file yielded no results, so we couldn’t automatically verify whether the query execution layer handles type conversion. The snippet in zmsdb/src/Zmsdb/Closure.php explicitly casts date components to integers, which may be redundant if the underlying database query mechanism performs automatic type conversion.

  • Verify manually if the query execution code (or driver) already enforces integer types on these parameters.
  • If confirmed, consider removing the casts to simplify the code; if not, retain the casts for explicit type safety.
zmsentities/src/Zmsentities/Closure.php (1)

35-35:

✅ Verification successful

Verify the existence of the lastChange property.

The method assumes lastChange property exists, but it's not explicitly defined in this file.


🏁 Script executed:

#!/bin/bash
# Check the schema definition to ensure lastChange property exists
fd closure.json -E node_modules

Length of output: 110


Schema Clarity: Verified Existence of lastChange Property

  • The JSON schema files (zmsentities/schema/closure.json and zmsentities/schema/dereferenced/closure.json) include a definition for the lastChange property.
  • Although the Closure.php file does not explicitly declare the property, its existence is confirmed via the schema.
zmsentities/src/Zmsentities/Collection/ClosureList.php (1)

48-58:

✅ Verification successful

Verify exception class exists.

The code throws \BO\Zmsentities\Exception\DayoffWrongYear, but it's not clear if this exception class exists.


🏁 Script executed:

#!/bin/bash
# Check if the exception class exists
rg -A 3 "class DayoffWrongYear" --type php

Length of output: 347


Exception class DayoffWrongYear exists as expected.

  • Verified that in zmsentities/src/Zmsentities/Exception/DayoffWrongYear.php, the class is defined and correctly extends \Exception.

Comment on lines +243 to +245
"required": [
"Datum"
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Ensure property name changes are consistently applied

If you rename "Datum" to "datum" as suggested, ensure the required property list is also updated.


🏁 Script executed:

#!/bin/bash
# Check for other references to the "Datum" property
grep -r "\"Datum\"" --include="*.json" --include="*.php" .

Length of output: 661


Action Required: Consistent Property Renaming Across Schemas
In zmsentities/schema/dereferenced/scope.json (lines 243-245), the "required" array still lists "Datum". If you're renaming the property to "datum", please update this as well as all other occurrences (e.g., in zmsentities/schema/dereferenced/closure.json and zmsentities/schema/closure.json) to ensure consistency across the codebase.

-                "required": [
-                    "Datum"
-                ],
+                "required": [
+                    "datum"
+                ],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"required": [
"Datum"
],
"required": [
"datum"
],

Comment on lines 29 to 36
try {
$closureToggled = \App::$http->readPostResult(
'/scope/' . $scopeId . '/availability/' . $date . '/closure/toggle/',
new \BO\Zmsentities\Closure()
)->getEntity();
} catch (\Exception $e) {
var_dump($e->getMessage());exit;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve error handling

The current error handling mechanism uses var_dump and exit, which is not suitable for production code. This approach provides no structured error response and terminates script execution abruptly.

Consider implementing proper error handling:

-        try {
-            $closureToggled = \App::$http->readPostResult(
-                '/scope/' . $scopeId . '/availability/' . $date . '/closure/toggle/',
-                new \BO\Zmsentities\Closure()
-            )->getEntity();
-        } catch (\Exception $e) {
-            var_dump($e->getMessage());exit;
-        }
+        try {
+            $closureToggled = \App::$http->readPostResult(
+                '/scope/' . $scopeId . '/availability/' . $date . '/closure/toggle/',
+                new \BO\Zmsentities\Closure()
+            )->getEntity();
+        } catch (\Exception $e) {
+            $this->logger->error('Failed to toggle closure: ' . $e->getMessage());
+            return \BO\Slim\Render::withJson(
+                $response->withStatus(500),
+                ['error' => 'Failed to toggle closure status']
+            );
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
$closureToggled = \App::$http->readPostResult(
'/scope/' . $scopeId . '/availability/' . $date . '/closure/toggle/',
new \BO\Zmsentities\Closure()
)->getEntity();
} catch (\Exception $e) {
var_dump($e->getMessage());exit;
}
try {
$closureToggled = \App::$http->readPostResult(
'/scope/' . $scopeId . '/availability/' . $date . '/closure/toggle/',
new \BO\Zmsentities\Closure()
)->getEntity();
} catch (\Exception $e) {
$this->logger->error('Failed to toggle closure: ' . $e->getMessage());
return \BO\Slim\Render::withJson(
$response->withStatus(500),
['error' => 'Failed to toggle closure status']
);
}

Comment on lines +67 to +70
{% set a = getNow()|date('Y-m-d') %}
{% if scope.closure.hasEntityByDate('2025-02-24') %}
X
{% endif %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove debug/test code

This code block appears to be debug or test code checking for a hardcoded date (2025-02-24). It should be removed before merging to production.

-        {% set a = getNow()|date('Y-m-d') %}
-        {% if scope.closure.hasEntityByDate('2025-02-24') %}
-            X
-        {% endif %}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{% set a = getNow()|date('Y-m-d') %}
{% if scope.closure.hasEntityByDate('2025-02-24') %}
X
{% endif %}

Comment on lines +44 to +54
public function addConditionId($id)
{
$this->query->where('closure.id', '=', $id);
return $this;
}

public function addConditionClosureId($id)
{
$this->query->where('closure.id', '=', $id);
return $this;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove redundant method

The methods addConditionId and addConditionClosureId are identical. This is redundant and can lead to confusion when maintaining the code.

Consider removing one of the methods and updating all references:

    public function addConditionId($id)
    {
        $this->query->where('closure.id', '=', $id);
        return $this;
    }

-   public function addConditionClosureId($id)
-   {
-       $this->query->where('closure.id', '=', $id);
-       return $this;
-   }

If these methods are intended for different purposes, consider adding more detailed PHPDoc comments to explain the distinction between them.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public function addConditionId($id)
{
$this->query->where('closure.id', '=', $id);
return $this;
}
public function addConditionClosureId($id)
{
$this->query->where('closure.id', '=', $id);
return $this;
}
public function addConditionId($id)
{
$this->query->where('closure.id', '=', $id);
return $this;
}

Comment on lines +52 to +55
try {
$closure = (new Closure())->readByScopeIdAndDate($scopeId, new DateTime($date));
} catch (\Exception $e) {
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve exception handling.

The current empty catch block silently swallows all exceptions, which could hide important errors and make debugging difficult.

try {
    $closure = (new Closure())->readByScopeIdAndDate($scopeId, new DateTime($date));
} catch (\Exception $e) {
+    // Initialize with a new empty closure entity
+    $closure = new ClosureEntity();
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
$closure = (new Closure())->readByScopeIdAndDate($scopeId, new DateTime($date));
} catch (\Exception $e) {
}
try {
$closure = (new Closure())->readByScopeIdAndDate($scopeId, new DateTime($date));
} catch (\Exception $e) {
// Initialize with a new empty closure entity
$closure = new ClosureEntity();
}

Comment on lines +63 to +64
$closure->existing = false;
$data['message'] = 'Closure has been deleted';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Property naming is confusing.

Similarly, setting existing = false for a deleted closure is counterintuitive.

(new Closure())->deleteEntity($closure->getId());
-$closure->existing = false;
+$closure->active = false;
$data['message'] = 'Closure has been deleted';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$closure->existing = false;
$data['message'] = 'Closure has been deleted';
(new Closure())->deleteEntity($closure->getId());
$closure->active = false;
$data['message'] = 'Closure has been deleted';

Comment on lines +59 to +60
$closure->existing = true;
$data['message'] = 'Closure has been created';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Property naming is confusing.

Setting existing = true for a newly created closure is counterintuitive and may lead to confusion.

$closure = (new Closure())->createOne($scopeId, new DateTime($date));
-$closure->existing = true;
+$closure->active = true;
$data['message'] = 'Closure has been created';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$closure->existing = true;
$data['message'] = 'Closure has been created';
$closure = (new Closure())->createOne($scopeId, new DateTime($date));
$closure->active = true;
$data['message'] = 'Closure has been created';

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
zmsadmin/src/Zmsadmin/ScopeAvailabilityDayClosure.php (1)

29-32: ⚠️ Potential issue

Add proper error handling for the HTTP request

The current implementation does not handle potential exceptions from the HTTP request, which could lead to unhandled exceptions and poor user experience.

Add a try-catch block to properly handle exceptions:

-        $closureToggled = \App::$http->readPostResult(
-            '/scope/' . $scopeId . '/availability/' . $date . '/closure/toggle/',
-            new \BO\Zmsentities\Closure()
-        )->getEntity();
+        try {
+            $closureToggled = \App::$http->readPostResult(
+                '/scope/' . $scopeId . '/availability/' . $date . '/closure/toggle/',
+                new \BO\Zmsentities\Closure()
+            )->getEntity();
+        } catch (\Exception $e) {
+            $this->logger->error('Failed to toggle closure: ' . $e->getMessage());
+            return \BO\Slim\Render::withJson(
+                $response->withStatus(500),
+                ['error' => 'Failed to toggle closure status']
+            );
+        }
zmsadmin/templates/page/availabilityday.twig (1)

67-70: ⚠️ Potential issue

Remove debug/test code

This code block appears to be debug or test code checking for a hardcoded date (2025-02-24). It should be removed before merging to production.

-        {% set a = getNow()|date('Y-m-d') %}
-        {% if scope.closure.hasEntityByDate('2025-02-24') %}
-            X
-        {% endif %}
🧹 Nitpick comments (3)
zmsadmin/src/Zmsadmin/ScopeAvailabilityDayClosure.php (1)

11-12: Remove unused imports

The Closure and AvailabilityList imports are not used in this class.

 use BO\Slim\Render;
-use BO\Zmsdb\Closure;
-use BO\Zmsentities\Collection\AvailabilityList;
 use Psr\Http\Message\ResponseInterface;
zmsadmin/templates/page/availabilityday.twig (2)

42-42: Improve confirmation dialog message

The current confirmation message is not very descriptive. It could be improved to provide more context to the user about what they are about to do.

-                const ok = confirm('Möchten Sie wirklich Die Terminbuchung für diesen Tag {% if locked %}entsperren{% else %}sperren{% endif %}?')
+                const ok = confirm('Möchten Sie wirklich die Terminbuchung für {{ dateString }} {% if locked %}entsperren? Benutzer werden wieder Termine für diesen Tag buchen können.{% else %}sperren? Benutzer werden keine neuen Termine für diesen Tag buchen können.{% endif %}')

33-38: Make the UI text more consistent and user-friendly

The messages and button text could be improved to be more consistent and user-friendly.

-        <div id="closure-close" class="message message--warning {% if not locked %}hidden{% endif %}">
-            Die Terminbuchung für diesen Tag ist gesperrt. <input class="button btn" style="margin-top: -6px;" type="button" onclick="toggleClosure()" value="Entsperren">
+        <div id="closure-close" class="message message--warning {% if not locked %}hidden{% endif %}">
+            <strong>Gesperrt:</strong> Die Terminbuchung für den {{ dateString }} ist derzeit gesperrt. <input class="button btn" style="margin-top: -6px;" type="button" onclick="toggleClosure()" value="Entsperren">
         </div>
-        <div id="closure-open" class="message message--info {% if locked %}hidden{% endif %}">
-            Die Terminbuchung für diesen Tag ist NICHT gesperrt. <input class="button btn" style="margin-top: -6px;" onclick="toggleClosure()" type="button" value="Sperren">
+        <div id="closure-open" class="message message--info {% if locked %}hidden{% endif %}">
+            <strong>Verfügbar:</strong> Die Terminbuchung für den {{ dateString }} ist derzeit aktiv. <input class="button btn" style="margin-top: -6px;" onclick="toggleClosure()" type="button" value="Sperren">
         </div>
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0154a8a and 1dda629.

📒 Files selected for processing (2)
  • zmsadmin/src/Zmsadmin/ScopeAvailabilityDayClosure.php (1 hunks)
  • zmsadmin/templates/page/availabilityday.twig (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (16)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsclient, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsdb, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsslim, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsentities, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsdldb, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsticketprinter, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsstatistic, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsmessaging, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmscitizenapi, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmscalldisplay, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsapi, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsadmin, 8.0)
  • GitHub Check: call-php-unit-tests / zmsdb-test
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: call-php-unit-tests / zmsapi-test
🔇 Additional comments (1)
zmsadmin/src/Zmsadmin/ScopeAvailabilityDayClosure.php (1)

26-27: Validate input parameters

The scopeId and date parameters are used directly without validation, which could lead to unexpected behavior if they contain invalid values.

Consider adding validation for these parameters:

         $scopeId = $args['id'];
         $date = $args['date'];
+        
+        // Validate scope ID is numeric
+        if (!is_numeric($scopeId)) {
+            return \BO\Slim\Render::withJson(
+                $response->withStatus(400),
+                ['error' => 'Invalid scope ID format']
+            );
+        }
+        
+        // Validate date format
+        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
+            return \BO\Slim\Render::withJson(
+                $response->withStatus(400),
+                ['error' => 'Invalid date format']
+            );
+        }

Comment on lines +61 to +63
}).fail(err => {
console.log('error', err)
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve error handling in AJAX request

The current error handling only logs to the console but doesn't provide any feedback to the user when an error occurs.

                }).fail(err => {
                    console.log('error', err)
+                    alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.')
                })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
}).fail(err => {
console.log('error', err)
})
}).fail(err => {
console.log('error', err)
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.')
})

Comment on lines +47 to +64
const currentDate = '{{ dateString }}'
const url = `{{ includeUrl() }}/scope/{{ scope.id }}/availability/day/${currentDate}/closure/toggle/`
$.ajax(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
data: JSON.stringify({})
}).done(data => {
if (data.closure.existing) {
document.getElementById('closure-close').classList.remove('hidden')
document.getElementById('closure-open').classList.add('hidden')
} else {
document.getElementById('closure-close').classList.add('hidden')
document.getElementById('closure-open').classList.remove('hidden')
}
}).fail(err => {
console.log('error', err)
})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add loading state to prevent multiple submissions

The current implementation does not disable the button during the AJAX request, which could lead to multiple submissions if the user clicks the button multiple times.

                const currentDate = '{{ dateString }}'
                const url = `{{ includeUrl() }}/scope/{{ scope.id }}/availability/day/${currentDate}/closure/toggle/`
+               
+               // Disable buttons during request
+               const closeButton = document.querySelector('#closure-close input');
+               const openButton = document.querySelector('#closure-open input');
+               closeButton.disabled = true;
+               openButton.disabled = true;
+               
                $.ajax(url, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    data: JSON.stringify({})
                }).done(data => {
                    if (data.closure.existing) {
                        document.getElementById('closure-close').classList.remove('hidden')
                        document.getElementById('closure-open').classList.add('hidden')
                    } else {
                        document.getElementById('closure-close').classList.add('hidden')
                        document.getElementById('closure-open').classList.remove('hidden')
                    }
+                   // Re-enable buttons
+                   closeButton.disabled = false;
+                   openButton.disabled = false;
                }).fail(err => {
                    console.log('error', err)
+                   alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.')
+                   // Re-enable buttons
+                   closeButton.disabled = false;
+                   openButton.disabled = false;
                })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const currentDate = '{{ dateString }}'
const url = `{{ includeUrl() }}/scope/{{ scope.id }}/availability/day/${currentDate}/closure/toggle/`
$.ajax(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
data: JSON.stringify({})
}).done(data => {
if (data.closure.existing) {
document.getElementById('closure-close').classList.remove('hidden')
document.getElementById('closure-open').classList.add('hidden')
} else {
document.getElementById('closure-close').classList.add('hidden')
document.getElementById('closure-open').classList.remove('hidden')
}
}).fail(err => {
console.log('error', err)
})
}
const currentDate = '{{ dateString }}'
const url = `{{ includeUrl() }}/scope/{{ scope.id }}/availability/day/${currentDate}/closure/toggle/`
// Disable buttons during request
const closeButton = document.querySelector('#closure-close input');
const openButton = document.querySelector('#closure-open input');
closeButton.disabled = true;
openButton.disabled = true;
$.ajax(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
data: JSON.stringify({})
}).done(data => {
if (data.closure.existing) {
document.getElementById('closure-close').classList.remove('hidden')
document.getElementById('closure-open').classList.add('hidden')
} else {
document.getElementById('closure-close').classList.add('hidden')
document.getElementById('closure-open').classList.remove('hidden')
}
// Re-enable buttons
closeButton.disabled = false;
openButton.disabled = false;
}).fail(err => {
console.log('error', err)
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.')
// Re-enable buttons
closeButton.disabled = false;
openButton.disabled = false;
})
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
zmsdb/migrations/91740751372-create-closures-table.sql (3)

3-8: Column Definitions: Consider Enforcing NOT NULL Constraints

The columns year, month, day, and StandortID are critical for identifying closure records and are used in composite indexes. It is advisable to add NOT NULL constraints to these columns to enforce data integrity unless a NULL value is explicitly required by your business logic.

Proposed diff:

@@
-   `year` SMALLINT(5),
-   `month` TINYINT(5),
-   `day` TINYINT(5),
-   `StandortID` INT(5) UNSIGNED,
+   `year` SMALLINT(5) NOT NULL,
+   `month` TINYINT(5) NOT NULL,
+   `day` TINYINT(5) NOT NULL,
+   `StandortID` INT(5) UNSIGNED NOT NULL,
@@

9-11: Index Naming and Redundancy Check

The table defines two indexes:

  • A single-column index on StandortID.
  • A composite index on (StandortID, year, month, day).

Since the composite index's leftmost column is StandortID, it should also serve standalone queries filtering by StandortID. Verify if both indexes are necessary. Additionally, consider naming them explicitly (e.g., idx_standort and idx_closure) for easier reference and maintenance during performance troubleshooting.

Proposed diff for naming:

@@
-   INDEX (StandortID),
-   INDEX (StandortID, year, month, day)
+   INDEX idx_standort (StandortID),
+   INDEX idx_closure (StandortID, year, month, day)
@@

12-12: Statement Termination: Consider Adding a Semicolon

It is common practice to terminate the CREATE TABLE statement with a semicolon. Ensure that the migration tool or the SQL interpreter being used does not require an explicit semicolon at the end. If it does, consider adding one to align with standard SQL syntax.

Proposed diff:

@@
-)
+);
@@
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1dda629 and 7166beb.

📒 Files selected for processing (1)
  • zmsdb/migrations/91740751372-create-closures-table.sql (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (18)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsclient, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsdb, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsslim, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsentities, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsdldb, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsticketprinter, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsstatistic, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsmessaging, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmscitizenapi, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmscalldisplay, 8.0)
  • GitHub Check: call-php-unit-tests / module-test (zmsentities, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsapi, 8.0)
  • GitHub Check: call-owasp-security-checks / security-scan (zmsadmin, 8.0)
  • GitHub Check: call-php-unit-tests / module-test (zmscitizenapi, 8.0)
  • GitHub Check: call-php-unit-tests / module-test (zmscalldisplay, 8.0)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: call-php-unit-tests / module-test (zmsadmin, 8.0)
🔇 Additional comments (1)
zmsdb/migrations/91740751372-create-closures-table.sql (1)

1-2: Ensure Idempotency with Table Drop

The DROP TABLE IF EXISTS clause is correctly used to ensure that any pre-existing version of the closures table is removed before creation. This is a good practice in migration scripts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant