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(ZMS-3460): create endpoint for free appointments grouped by office #797

Merged
merged 17 commits into from
Feb 5, 2025

Conversation

manjencic
Copy link
Contributor

@manjencic manjencic commented Jan 23, 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.

Description

Short description or comments

Reference

Issues #XXX

Summary by CodeRabbit

  • New Features

    • Added a new API endpoint /available-appointments-by-office/ to retrieve available appointments for multiple offices on a specific date.
    • Introduced support for querying appointments across multiple offices and services simultaneously.
  • Improvements

    • Enhanced validation and processing of office and service identifiers.
    • Updated services to handle multiple office and service IDs more flexibly.
  • Technical Updates

    • Created a new model AvailableAppointmentsByOffice to support grouped appointment retrieval.
    • Introduced a new JSON schema for AvailableAppointmentsByOffice to define the structure of available appointments.

Copy link
Contributor

coderabbitai bot commented Jan 23, 2025

Walkthrough

This pull request introduces a new API endpoint /available-appointments-by-office/ that allows retrieving available appointments for a specific day, grouped by office. The changes span multiple files in the zmscitizenapi project, focusing on enhancing the system's ability to handle multiple office and service IDs. A new model AvailableAppointmentsByOffice has been created to support the grouping of appointments by office, and several services have been updated to accept arrays of office and service IDs instead of single identifiers.

Changes

File Change Summary
zmscitizenapi/routing.php Added new route for /available-appointments-by-office/ endpoint
zmscitizenapi/src/Zmscitizenapi/Controllers/Availability/AvailableAppointmentsListByOfficeController.php New controller for handling available appointments by office requests
zmscitizenapi/src/Zmscitizenapi/Services/Availability/... Updated services to support multiple office and service IDs
zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php Modified validation methods to accept arrays of office and service IDs
zmscitizenapi/src/Zmscitizenapi/Models/AvailableAppointmentsByOffice.php New model for representing appointments grouped by office
zmsentities/schema/citizenapi/availableAppointmentsByOffice.json New JSON schema for available appointments by office

Sequence Diagram

sequenceDiagram
    Client->>API: Request available appointments
    API->>ValidationService: Validate request parameters
    ValidationService-->>API: Validation result
    API->>AvailableAppointmentsListService: Get appointments
    AvailableAppointmentsListService->>ZmsApiFacadeService: Fetch appointments
    ZmsApiFacadeService-->>AvailableAppointmentsListService: Appointment data
    AvailableAppointmentsListService->>API: Grouped appointments
    API->>Client: Return appointments by office
Loading

Possibly related PRs

  • feat(ZMS-3459): return slotTimeInMinutes #779: Changes in this PR introduce a new property slotTimeInMinutes to the Office class, which is relevant to the main PR's new endpoint that retrieves available appointments by office, as it may utilize this property in its response structure.

Suggested reviewers

  • ThomasAFink

Poem

🐰 Hop, hop, hooray! A new API is here to play,
Multiple offices, services galore,
Appointments grouped with precision and more!
CodeRabbit's magic makes booking a breeze,
Flexibility dancing with elegant ease! 🎉


🪧 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. (Beta)
  • @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: 6

🔭 Outside diff range comments (2)
zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (2)

Line range hint 546-578: Implement logic for $groupByOffice or remove unused parameter

The parameter $groupByOffice is added to the processFreeSlots method signature but is not utilized within the method body. This can lead to confusion and may indicate incomplete implementation of the grouping logic.

If the intention is to group appointment timestamps by office, consider implementing the necessary logic inside the method. Alternatively, if grouping is not required, remove the $groupByOffice parameter to avoid misleading future maintainers.


Line range hint 546-578: Return the correct instance when grouping by office

Currently, the method processFreeSlots returns an instance of ProcessFreeSlots, even when appointments are grouped by office. Since you're grouping timestamps by scope ID (which may represent offices), you should return an instance of ProcessFreeSlotsGroupByOffice to align with the new data structure.

Modify the return statement to return the appropriate class instance:

-            return new ProcessFreeSlots($appointmentTimestamps);
+            if ($groupByOffice) {
+                return new ProcessFreeSlotsGroupByOffice($appointmentTimestamps);
+            } else {
+                // Flatten the timestamps if not grouping by office
+                $flatTimestamps = [];
+                foreach ($appointmentTimestamps as $timestamps) {
+                    $flatTimestamps = array_merge($flatTimestamps, $timestamps);
+                }
+                asort($flatTimestamps);
+                return new ProcessFreeSlots($flatTimestamps);
+            }

Ensure that the ProcessFreeSlotsGroupByOffice class is properly utilized to handle the grouped data.

🧹 Nitpick comments (6)
zmscitizenapi/src/Zmscitizenapi/Models/ProcessFreeSlotsGroupByOffice.php (1)

16-17: Define the property type explicitly

The docblock for $appointmentTimestamps mentions that it can be array|null, but the property is declared as public array|null $appointmentTimestamps = [];, which initializes it as an empty array. This can cause confusion about whether the property can ever be null.

Consider defining the property more explicitly:

-    /** @var array|null */
-    public array|null $appointmentTimestamps = [];
+    /** @var array */
+    public array $appointmentTimestamps;

Also, initialize the property in the constructor to ensure it's always an array.

zmscitizenapi/src/Zmscitizenapi/Controllers/Availability/AvailableAppointmentsListByOfficeController.php (1)

33-42: Ensure consistent error handling and response formatting

The ternary operator used in the return statement can be hard to read and may lead to inconsistent responses if $result does not match expected formats. Consider separating the error handling and success response for clarity.

Refactor the return statement for better readability:

             $result = $this->service->getAvailableAppointmentsListByOffice($request->getQueryParams());

-            return is_array($result) && isset($result['errors'])
-                ? $this->createJsonResponse(
-                    $response,
-                    $result,
-                    ErrorMessages::getHighestStatusCode($result['errors'])
-                )
-                : $this->createJsonResponse($response, $result->toArray(), 200);
+            if (is_array($result) && isset($result['errors'])) {
+                $statusCode = ErrorMessages::getHighestStatusCode($result['errors']);
+                return $this->createJsonResponse($response, $result, $statusCode);
+            } else {
+                return $this->createJsonResponse($response, $result->toArray(), 200);
+            }

This enhances readability and maintainability.

zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableAppointmentsListService.php (2)

50-58: Consider adding type hints for better type safety.

The method signature could benefit from explicit type hints for the parameters and return type.

-    private function getAvailableAppointments(object $data, ?bool $groupByOffice = false): array|AvailableAppointments
+    private function getAvailableAppointments(
+        object $data,
+        ?bool $groupByOffice = false
+    ): array|AvailableAppointments|\BO\Zmsentities\Collection\ProcessList

61-71: Add return type hint and PHPDoc for consistency.

The new method is missing a return type hint and documentation.

-    public function getAvailableAppointmentsListByOffice($queryParams)
+    /**
+     * Get available appointments grouped by office
+     *
+     * @param array $queryParams Query parameters containing date, officeIds, and serviceIds
+     * @return array|AvailableAppointments|\BO\Zmsentities\Collection\ProcessList
+     */
+    public function getAvailableAppointmentsListByOffice(array $queryParams): array|AvailableAppointments|\BO\Zmsentities\Collection\ProcessList
zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php (1)

360-362: Consider adding array element validation.

While the method checks for non-empty arrays and numeric values, it might be good to add validation for individual office IDs (e.g., positive integers only).

     private static function isValidOfficeIds(?array $officeIds): bool
     {
-        return !empty($officeIds) && self::isValidNumericArray($officeIds);
+        return !empty($officeIds) && 
+            self::isValidNumericArray($officeIds) && 
+            array_reduce($officeIds, fn($valid, $id) => $valid && $id > 0, true);
     }
zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php (1)

21-28: Consider validating before making the API call.

While the error handling is good, consider validating the appointment days before making the API call to getAvailableDays to avoid unnecessary network requests for invalid data.

-        $result = $this->getAvailableDays($clientData);
-        $errors = ValidationService::validateAppointmentDaysNotFound($result->toArray());
-
-        if (!empty($errors)) {
-            return $errors;
-        }
-
-        return $result;
+        $preValidationErrors = ValidationService::validateAppointmentDaysNotFound([]);
+        if (!empty($preValidationErrors)) {
+            return $preValidationErrors;
+        }
+
+        $result = $this->getAvailableDays($clientData);
+        return $result;
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 27555bb and 999edd7.

📒 Files selected for processing (8)
  • zmscitizenapi/routing.php (1 hunks)
  • zmscitizenapi/src/Zmscitizenapi/Controllers/Availability/AvailableAppointmentsListByOfficeController.php (1 hunks)
  • zmscitizenapi/src/Zmscitizenapi/Models/ProcessFreeSlotsGroupByOffice.php (1 hunks)
  • zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableAppointmentsListService.php (2 hunks)
  • zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php (3 hunks)
  • zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php (4 hunks)
  • zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (5 hunks)
  • zmsentities/schema/citizenapi/processFreeSlotsGroupByOffice.json (1 hunks)
🔇 Additional comments (8)
zmscitizenapi/src/Zmscitizenapi/Controllers/Availability/AvailableAppointmentsListByOfficeController.php (1)

25-31: Handle potential localization of error messages

In the error response at lines 26-30, the status code is retrieved using ErrorMessages::get('invalidRequest', $this->language)['statusCode']. Ensure that the error messages are correctly localized based on the client's language preferences.

zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableAppointmentsListService.php (2)

28-30: LGTM: Proper handling of multiple office IDs.

The implementation correctly splits comma-separated office IDs and trims whitespace.


44-44: LGTM: Updated validation call.

Correctly passing the array of office IDs to the validation service.

zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php (2)

88-89: LGTM: Proper validation of office and service IDs arrays.

The validation logic correctly handles arrays of office and service IDs.

Also applies to: 96-100


Line range hint 146-156: LGTM: Consistent validation in getAvailableAppointments.

The method properly validates all required parameters including the arrays of office and service IDs.

zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php (3)

39-40: Well-implemented input handling for multiple offices and services.

Good use of array_map with trim for input sanitization, and proper handling of empty inputs maintains backward compatibility.


50-51: Verify ValidationService compatibility with array inputs.

Ensure that ValidationService::validateGetBookableFreeDays has been updated to handle arrays of office and service IDs correctly.

✅ Verification successful

✓ ValidationService is already compatible with array inputs

The validateGetBookableFreeDays method is correctly typed to accept arrays of office and service IDs, with proper array validation in place. No changes needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the validateGetBookableFreeDays method implementation
rg -t php "function validateGetBookableFreeDays" --glob "ValidationService.php"

Length of output: 203


Script:

#!/bin/bash
# Get the validateGetBookableFreeDays method implementation with context
ast-grep --pattern 'public static function validateGetBookableFreeDays($_) {
  $$$
}'

Length of output: 87


Script:

#!/bin/bash
# Get the validateGetBookableFreeDays method implementation with context
rg -t php "function validateGetBookableFreeDays" -B 2 -A 15 --glob "ValidationService.php"

Length of output: 1800


58-65: Verify ZmsApiFacadeService compatibility with array inputs.

The return type change to AvailableDays improves type safety. However, please verify that ZmsApiFacadeService::getBookableFreeDays has been updated to handle arrays of office and service IDs.

✅ Verification successful

✓ ZmsApiFacadeService is compatible with array inputs

The ZmsApiFacadeService::getBookableFreeDays method is correctly typed to accept arrays for office IDs, service IDs, and service counts, and returns an AvailableDays object. The implementation is fully compatible with the changes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the getBookableFreeDays method implementation
rg -t php "function getBookableFreeDays" --glob "ZmsApiFacadeService.php"

# Search for AvailableDays usage to ensure proper return type handling
rg -t php "class AvailableDays" --glob "AvailableDays.php"

Length of output: 370


Script:

#!/bin/bash
# Get the implementation of getBookableFreeDays method
rg -t php -A 10 "function getBookableFreeDays" zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php

# Check for any array type hints or docblock
rg -t php -B 5 "function getBookableFreeDays" zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php

Length of output: 744

Comment on lines 503 to 527
string $date,
array $officeIds,
array $serviceIds,
array $serviceCounts,
?bool $groupByOffice = false
): AvailableAppointments|array {

$requests = [];
$providers = [];
foreach ($serviceIds as $index => $serviceId) {
$slotCount = isset($serviceCounts[$index]) ? intval($serviceCounts[$index]) : 1;
for ($i = 0; $i < $slotCount; $i++) {
$requests[] = [
'id' => $serviceId,
'source' => \App::$source_name,
'slotCount' => 1,
'source' => \App::$source_name
];
}
}

foreach ($officeIds as $officeId) {
$providers[] = [
'id' => $officeId,
'source' => \App::$source_name
];
}

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

Handle potential mismatch between $serviceIds and $serviceCounts

In the loop starting at line 513, you attempt to retrieve $serviceCounts[$index] for each $serviceId. While you provide a default value of 1 when $serviceCounts[$index] is not set, this could mask issues where the counts are unintentionally mismatched.

Consider adding a validation check to ensure that $serviceIds and $serviceCounts have the same number of elements:

             $requests = [];
+            if (count($serviceIds) !== count($serviceCounts)) {
+                throw new InvalidArgumentException('The number of service IDs must match the number of service counts.');
+            }
             $providers = [];
📝 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
string $date,
array $officeIds,
array $serviceIds,
array $serviceCounts,
?bool $groupByOffice = false
): AvailableAppointments|array {
$requests = [];
$providers = [];
foreach ($serviceIds as $index => $serviceId) {
$slotCount = isset($serviceCounts[$index]) ? intval($serviceCounts[$index]) : 1;
for ($i = 0; $i < $slotCount; $i++) {
$requests[] = [
'id' => $serviceId,
'source' => \App::$source_name,
'slotCount' => 1,
'source' => \App::$source_name
];
}
}
foreach ($officeIds as $officeId) {
$providers[] = [
'id' => $officeId,
'source' => \App::$source_name
];
}
string $date,
array $officeIds,
array $serviceIds,
array $serviceCounts,
?bool $groupByOffice = false
): AvailableAppointments|array {
$requests = [];
if (count($serviceIds) !== count($serviceCounts)) {
throw new InvalidArgumentException('The number of service IDs must match the number of service counts.');
}
$providers = [];
foreach ($serviceIds as $index => $serviceId) {
$slotCount = isset($serviceCounts[$index]) ? intval($serviceCounts[$index]) : 1;
for ($i = 0; $i < $slotCount; $i++) {
$requests[] = [
'id' => $serviceId,
'source' => \App::$source_name
];
}
}
foreach ($officeIds as $officeId) {
$providers[] = [
'id' => $officeId,
'source' => \App::$source_name
];
}

Comment on lines 428 to 455
public static function getBookableFreeDays(
array $officeIds,
array $serviceIds,
array $serviceCounts,
string $startDate,
string $endDate
): AvailableDays {
$firstDay = DateTimeFormatHelper::getInternalDateFromISO($startDate);
$lastDay = DateTimeFormatHelper::getInternalDateFromISO($endDate);
$services = [];
$providers = [];

$serviceNumber = 0;
foreach ($serviceIds as $serviceId) {
$services[] = [
'id' => $serviceId,
'source' => \App::$source_name,
'slotCount' => $serviceCounts[$serviceNumber],
];
$serviceNumber++;
}

foreach ($officeIds as $officeId) {
$providers[] = [
'id' => $officeId,
'source' => \App::$source_name,
];
}
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

Ensure matching lengths of $serviceIds and $serviceCounts to prevent undefined offsets

In the loop starting at line 441, you access $serviceCounts[$serviceNumber] without verifying that the index exists. If $serviceCounts does not have the same number of elements as $serviceIds, this could lead to "Undefined offset" notices or errors.

Apply this diff to add validation before the loop:

+            if (count($serviceIds) !== count($serviceCounts)) {
+                throw new InvalidArgumentException('The number of service IDs must match the number of service counts.');
+            }
📝 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 static function getBookableFreeDays(
array $officeIds,
array $serviceIds,
array $serviceCounts,
string $startDate,
string $endDate
): AvailableDays {
$firstDay = DateTimeFormatHelper::getInternalDateFromISO($startDate);
$lastDay = DateTimeFormatHelper::getInternalDateFromISO($endDate);
$services = [];
$providers = [];
$serviceNumber = 0;
foreach ($serviceIds as $serviceId) {
$services[] = [
'id' => $serviceId,
'source' => \App::$source_name,
'slotCount' => $serviceCounts[$serviceNumber],
];
$serviceNumber++;
}
foreach ($officeIds as $officeId) {
$providers[] = [
'id' => $officeId,
'source' => \App::$source_name,
];
}
public static function getBookableFreeDays(
array $officeIds,
array $serviceIds,
array $serviceCounts,
string $startDate,
string $endDate
): AvailableDays {
$firstDay = DateTimeFormatHelper::getInternalDateFromISO($startDate);
$lastDay = DateTimeFormatHelper::getInternalDateFromISO($endDate);
$services = [];
$providers = [];
if (count($serviceIds) !== count($serviceCounts)) {
throw new InvalidArgumentException('The number of service IDs must match the number of service counts.');
}
$serviceNumber = 0;
foreach ($serviceIds as $serviceId) {
$services[] = [
'id' => $serviceId,
'source' => \App::$source_name,
'slotCount' => $serviceCounts[$serviceNumber],
];
$serviceNumber++;
}
foreach ($officeIds as $officeId) {
$providers[] = [
'id' => $officeId,
'source' => \App::$source_name,
];
}

Comment on lines 13 to 34
public static $schema = 'citizenapi/processFreeSlots.json';

/** @var array|null */
public array|null $appointmentTimestamps = [];

/**
* @param array $appointmentTimestamps
*/
public function __construct(array $appointmentTimestamps = [])
{

$this->appointmentTimestamps = array_map('intval', $appointmentTimestamps);

$this->ensureValid();
}

private function ensureValid(): void
{
if (!$this->testValid()) {
throw new InvalidArgumentException('The provided data is invalid according to the schema.');
}
}
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

Correct the schema path in the $schema property

The $schema property currently points to 'citizenapi/processFreeSlots.json', which may not correspond to the correct schema for the ProcessFreeSlotsGroupByOffice class.

Update the schema path to reflect the appropriate JSON schema file:

-    public static $schema = 'citizenapi/processFreeSlots.json';
+    public static $schema = 'citizenapi/processFreeSlotsGroupByOffice.json';

This ensures that the ensureValid() method validates against the correct schema.

📝 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 static $schema = 'citizenapi/processFreeSlots.json';
/** @var array|null */
public array|null $appointmentTimestamps = [];
/**
* @param array $appointmentTimestamps
*/
public function __construct(array $appointmentTimestamps = [])
{
$this->appointmentTimestamps = array_map('intval', $appointmentTimestamps);
$this->ensureValid();
}
private function ensureValid(): void
{
if (!$this->testValid()) {
throw new InvalidArgumentException('The provided data is invalid according to the schema.');
}
}
public static $schema = 'citizenapi/processFreeSlotsGroupByOffice.json';
/** @var array|null */
public array|null $appointmentTimestamps = [];
/**
* @param array $appointmentTimestamps
*/
public function __construct(array $appointmentTimestamps = [])
{
$this->appointmentTimestamps = array_map('intval', $appointmentTimestamps);
$this->ensureValid();
}
private function ensureValid(): void
{
if (!$this->testValid()) {
throw new InvalidArgumentException('The provided data is invalid according to the schema.');
}
}

Comment on lines 24 to 26
$this->appointmentTimestamps = array_map('intval', $appointmentTimestamps);

$this->ensureValid();
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

Validate the structure of $appointmentTimestamps

Currently, the constructor maps $appointmentTimestamps using array_map('intval', $appointmentTimestamps); but since the data is intended to be grouped by office, which suggests a nested array structure, the mapping may not function as expected.

Adjust the logic to handle nested arrays appropriately. For example:

-            $this->appointmentTimestamps = array_map('intval', $appointmentTimestamps);
+            foreach ($appointmentTimestamps as $officeId => $timestamps) {
+                $this->appointmentTimestamps[$officeId] = array_map('intval', $timestamps);
+            }

This ensures that timestamps for each office are properly converted to integers.

📝 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
$this->appointmentTimestamps = array_map('intval', $appointmentTimestamps);
$this->ensureValid();
foreach ($appointmentTimestamps as $officeId => $timestamps) {
$this->appointmentTimestamps[$officeId] = array_map('intval', $timestamps);
}
$this->ensureValid();

Comment on lines 312 to 352
/**
* @swagger
* /available-appointments-by-office/:
* get:
* summary: Get available appointments for a specific day grouped by office
* tags:
* - appointments
* parameters:
* - name: date
* description: Date in format YYYY-MM-DD
* in: query
* required: true
* type: string
* - name: officeId
* description: Comma separated Office IDs
* in: query
* required: true
* type: string
* - name: serviceIds
* description: Comma separated Service IDs
* in: query
* required: true
* type: string
* responses:
* 200:
* description: List of available appointments grouped by office id
* schema:
* type: object
* properties:
* meta:
* $ref: "schema/metaresult.json"
* data:
* $ref: "schema/citizenapi/availableAppointments.json"
*/
createLanguageRoutes(
\App::$slim,
'/available-appointments-by-office/',
'\BO\Zmscitizenapi\Controllers\Availability\AvailableAppointmentsListController',
"AvailableAppointmentsListController",
"get"
);
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

Verify the controller path in the route definition.

The route is using AvailableAppointmentsListController but based on the AI summary, there should be a new AvailableAppointmentsListByOfficeController. This might cause runtime errors.

-    '\BO\Zmscitizenapi\Controllers\Availability\AvailableAppointmentsListController',
+    '\BO\Zmscitizenapi\Controllers\Availability\AvailableAppointmentsListByOfficeController',

Also, consider updating the Swagger documentation to include:

  • Response format for error cases (400, 404)
  • Example values for the parameters
  • More detailed description of the response schema

Committable suggestion skipped: line range outside the PR's diff.

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

🔭 Outside diff range comments (1)
zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (1)

Line range hint 551-583: Remove or utilize the unused groupByOffice parameter.

The groupByOffice parameter is passed to the method but never used in the implementation.

Either remove the parameter or implement the grouping functionality:

-   private static function processFreeSlots(ProcessList $freeSlots, bool $groupByOffice): ProcessFreeSlots|array
+   private static function processFreeSlots(ProcessList $freeSlots): ProcessFreeSlots|array

Or if grouping by office is needed:

    private static function processFreeSlots(ProcessList $freeSlots, bool $groupByOffice): ProcessFreeSlots|array
    {
        // ... existing code ...

        $appointmentTimestamps = array_reduce(
            iterator_to_array($freeSlots),
            function ($timestamps, $slot) use ($currentTimestamp, $groupByOffice) {
                if (isset($slot->appointments) && is_iterable($slot->appointments)) {
                    foreach ($slot->appointments as $appointment) {
                        if (isset($appointment->date) && isset($appointment->scope->id)) {
                            $timestamp = (int) $appointment->date;
                            $scopeId = (int) $appointment->scope->id;

                            if ($timestamp > $currentTimestamp) {
-                               $timestamps[$scopeId][$timestamp] = true;
+                               $key = $groupByOffice ? $appointment->scope->provider->id : $scopeId;
+                               $timestamps[$key][$timestamp] = true;
                            }
                        }
                    }
                }
                return $timestamps;
            },
            []
        );
🧹 Nitpick comments (3)
zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php (2)

32-33: Enhance input validation for office and service IDs.

While the basic parsing logic is correct, consider adding additional validation:

  1. Filter out empty strings after splitting
  2. Validate ID format before processing
  3. Consider adding a maximum limit for the number of IDs to prevent potential abuse
-            'officeIds' => array_map('trim', explode(',', $queryParams['officeId'] ?? '')),
-            'serviceIds' => array_map('trim', explode(',', $queryParams['serviceId'] ?? '')),
+            'officeIds' => array_filter(array_map('trim', explode(',', $queryParams['officeId'] ?? ''))),
+            'serviceIds' => array_filter(array_map('trim', explode(',', $queryParams['serviceId'] ?? ''))),

Line range hint 1-60: Consider caching strategy for multiple office queries.

The service now handles multiple offices and services, which could increase response times and server load. Consider implementing caching for frequently requested office/service combinations.

zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (1)

Line range hint 428-583: Consider implementing caching for performance optimization.

The methods handle multiple offices and services, which could lead to increased response times when dealing with many combinations. Consider implementing caching for frequently accessed data patterns.

Suggestions:

  1. Cache the results of getFreeDays and getFreeTimeslots with a short TTL
  2. Implement batch processing for multiple office/service combinations
  3. Add request rate limiting to prevent API abuse
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 999edd7 and ec8569b.

📒 Files selected for processing (2)
  • zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php (2 hunks)
  • zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: call-unit-tests / zmsapi-test
  • GitHub Check: call-unit-tests / zmsdb-test
🔇 Additional comments (5)
zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php (3)

51-51: Breaking change: Return type modification.

The return type has been restricted to AvailableDays instead of AvailableDays|array. This could be a breaking change for consumers expecting the array return type.

Please ensure all consumers of this method are updated to handle the new return type.


43-44: Verify ValidationService compatibility with array inputs.

Ensure that ValidationService::validateGetBookableFreeDays has been updated to handle arrays of IDs correctly.

✅ Verification successful

Validation service is already compatible with array inputs

The validateGetBookableFreeDays method is properly implemented to handle arrays of office IDs and service IDs, with appropriate validation for both array formats and numeric values.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for ValidationService implementation
ast-grep --pattern 'function validateGetBookableFreeDays($_)'

Length of output: 951


Script:

#!/bin/bash
# First, find the ValidationService class file
fd ValidationService

Length of output: 164


Script:

#!/bin/bash
# View the ValidationService implementation
cat zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php

Length of output: 13211


54-55: Verify ZmsApiFacadeService compatibility with array inputs.

Ensure that ZmsApiFacadeService::getBookableFreeDays has been updated to handle arrays of office and service IDs.

✅ Verification successful

ZmsApiFacadeService is already compatible with array inputs

The getBookableFreeDays method signature explicitly declares array parameters for both $officeIds and $serviceIds, confirming compatibility with the current usage.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for ZmsApiFacadeService implementation
ast-grep --pattern 'function getBookableFreeDays($_)'

Length of output: 943


Script:

#!/bin/bash
# Search for ZmsApiFacadeService class and method implementation
ast-grep --pattern 'class ZmsApiFacadeService {
  $$$
  public function getBookableFreeDays($_) {
    $$$
  }
  $$$
}'

# Fallback to ripgrep
echo "=== Searching with ripgrep ==="
rg -l "getBookableFreeDays" --type php

Length of output: 472


Script:

#!/bin/bash
# Examine ZmsApiFacadeService implementation
echo "=== ZmsApiFacadeService implementation ==="
rg "getBookableFreeDays" zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php -B 2 -A 10

Length of output: 620

zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (2)

428-448: ⚠️ Potential issue

Validate array lengths to prevent undefined offset access.

The loop accessing $serviceCounts[$serviceNumber] could lead to undefined offset errors if $serviceIds and $serviceCounts have different lengths.

Add validation before the loop:

        $services = [];
        $providers = [];

+       if (count($serviceIds) !== count($serviceCounts)) {
+           throw new InvalidArgumentException('The number of service IDs must match the number of service counts.');
+       }
        $serviceNumber = 0;
        foreach ($serviceIds as $serviceId) {

Likely invalid or redundant comment.


508-532: 🛠️ Refactor suggestion

Optimize request array construction and add validation.

The nested loops for building requests array can be optimized, and array length validation is needed.

Consider this optimization:

        $requests = [];
+       if (count($serviceIds) !== count($serviceCounts)) {
+           throw new InvalidArgumentException('The number of service IDs must match the number of service counts.');
+       }
        $providers = [];
-       foreach ($serviceIds as $index => $serviceId) {
-           $slotCount = isset($serviceCounts[$index]) ? intval($serviceCounts[$index]) : 1;
-           for ($i = 0; $i < $slotCount; $i++) {
-               $requests[] = [
-                   'id' => $serviceId,
-                   'source' => \App::$source_name
-               ];
-           }
-       }
+       $requests = array_merge(...array_map(
+           fn($index) => array_fill(
+               0,
+               intval($serviceCounts[$index] ?? 1),
+               ['id' => $serviceIds[$index], 'source' => \App::$source_name]
+           ),
+           array_keys($serviceIds)
+       ));

Likely invalid or redundant comment.

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 (4)
zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php (4)

96-100: Update error messages for array validation

The error messages (invalidOfficeId and invalidServiceId) should be updated to reflect that we're now validating arrays of IDs. Consider using more descriptive messages like invalidOfficeIds or invalidServiceIds.


156-156: Consider adding array size limits

While the array validation is functionally correct, consider adding checks for:

  1. Maximum number of office IDs to prevent potential DoS
  2. Duplicate office IDs in the array

360-362: Enhance array validation for office IDs

The current validation only checks for non-empty arrays with numeric values. Consider adding:

  1. Validation that each office ID is greater than 0 (like in isValidOfficeId)
  2. Deduplication of office IDs
  3. Maximum array size limit
 private static function isValidOfficeIds(?array $officeIds): bool
 {
-    return !empty($officeIds) && self::isValidNumericArray($officeIds);
+    if (empty($officeIds) || !self::isValidNumericArray($officeIds)) {
+        return false;
+    }
+    $maxOffices = 10; // Consider making this configurable
+    if (count($officeIds) > $maxOffices) {
+        return false;
+    }
+    $uniqueOfficeIds = array_unique($officeIds);
+    return count(array_filter($uniqueOfficeIds, fn($id) => $id > 0)) === count($uniqueOfficeIds);
 }

425-433: Document legacy validation methods

These single ID validation methods appear to be legacy code. Consider:

  1. Adding @deprecated tags with migration instructions
  2. Adding @see tags referencing the new array validation methods
+    /**
+     * @deprecated Use isValidOfficeIds() instead for better support of multiple offices
+     * @see isValidOfficeIds()
+     */
     private static function isValidOfficeId(?int $officeId): bool
     {
         return !empty($officeId) && $officeId > 0;
     }

+    /**
+     * @deprecated Use isValidServiceIds() instead for better support of multiple services
+     * @see isValidServiceIds()
+     */
     private static function isValidServiceId(?int $serviceId): bool
     {
         return !empty($serviceId) && $serviceId > 0;
     }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ec8569b and 94a1a88.

📒 Files selected for processing (1)
  • zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Analyze (python)
  • GitHub Check: call-unit-tests / zmsapi-test
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: call-unit-tests / zmsdb-test
🔇 Additional comments (2)
zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php (2)

88-89: Breaking Change: Method signature updated to accept arrays

The signature change from single IDs to arrays (officeIdofficeIds, serviceIdserviceIds) is a breaking change that could affect existing API clients. Consider:

  1. Adding a new method instead of modifying the existing one
  2. Maintaining backward compatibility by accepting both single values and arrays

Run this script to find potential usages that might be affected:


146-146: Breaking Change: Ensure consistent handling of array parameters

Similar to validateGetBookableFreeDays, this is a breaking change. Ensure that:

  1. The handling of array parameters is consistent across all methods
  2. The migration strategy for existing clients is documented

Run this script to verify consistent parameter handling:

✅ Verification successful

Parameter type change is properly validated and consistent with existing patterns

The change from single officeId to array officeIds is consistent with:

  • Proper validation through isValidOfficeIds helper method
  • Similar array parameter handling in other validation methods
  • Existing validation patterns for both single and array office IDs
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all validation methods to ensure consistent parameter handling
ast-grep --pattern 'public static function validate$_($_) { $$$ }'

Length of output: 68


Script:

#!/bin/bash
# Try both ast-grep and ripgrep to find validation methods
echo "=== Using ast-grep with simpler pattern ==="
ast-grep --pattern 'function validate'

echo -e "\n=== Using ripgrep to find validation methods ==="
rg "function validate\w+\s*\([^)]+\)" -A 1

Length of output: 75751


Script:

#!/bin/bash
# Search specifically in ValidationService.php for the relevant method
echo "=== Searching for validateGetAvailableAppointments method ==="
rg "validateGetAvailableAppointments" -A 5 zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php

echo -e "\n=== Searching for similar validation methods with officeId parameter ==="
rg "officeId" -A 2 zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php

Length of output: 2222

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: 1

🔭 Outside diff range comments (2)
zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableAppointmentsListServiceTest.php (2)

Line range hint 158-163: Fix inconsistent parameter types between mock services.

The ValidationService mock uses ?array $officeIds while ZmsApiFacadeService mock still uses ?int $officeId. This inconsistency could lead to type mismatch errors.

Update the ZmsApiFacadeService mock to match the new parameter type:

     public static function getAvailableAppointments(
         ?string $date,
-        ?int $officeId,
+        ?array $officeIds,
         ?array $serviceIds,
         ?array $serviceCounts
     ): \BO\Zmscitizenapi\Models\AvailableAppointments|array

Line range hint 29-43: Add test coverage for multiple offices functionality.

The test case only covers a single office ID scenario ('officeId' => '123'). Since the service now supports multiple offices, we need test coverage for this functionality.

Add a new test case to verify the multi-office scenario:

public function testGetAvailableAppointmentsListWithMultipleOfficesReturnsAvailableAppointments(): void
{
    // Arrange
    $queryParams = [
        'date' => '2025-01-15',
        'officeId' => '123,456',  // Multiple office IDs
        'serviceId' => '789',
        'serviceCount' => '1'
    ];
    
    $expectedAppointments = new AvailableAppointments([1705317600, 1705321200]);
    
    $this->createMockValidationService([]);
    $this->createMockFacade($expectedAppointments);

    // Act
    $result = $this->service->getAvailableAppointmentsList($queryParams);

    // Assert
    $this->assertInstanceOf(AvailableAppointments::class, $result);
    $this->assertEquals($expectedAppointments, $result);
}
🧹 Nitpick comments (2)
zmscitizenapi/tests/Zmscitizenapi/Services/Core/ValidationServiceTest.php (1)

Line range hint 91-144: Consider adding test cases for array-specific scenarios.

While the current test cases cover basic validation, consider adding tests for:

  • Empty arrays ([])
  • Arrays with multiple values ([1, 2, 3])
  • Arrays with mixed valid/invalid values ([1, 'invalid', 2])

This would ensure robust validation for the new array-based parameters.

zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableAppointmentsListServiceTest.php (1)

Line range hint 96-116: Add validation test for invalid office IDs.

Since we now support multiple office IDs, we should add a test case to verify validation of invalid office IDs, similar to how we test invalid service IDs.

Add a new test case:

public function testGetAvailableAppointmentsListWithInvalidOfficeIdsReturnsValidationError(): void
{
    // Arrange
    $queryParams = [
        'date' => '2025-01-15',
        'officeId' => 'invalid,ids',
        'serviceId' => '456',
        'serviceCount' => '1'
    ];
    $expectedError = ['errors' => ['Invalid office IDs']];
    
    $this->createMockValidationService($expectedError);

    // Act
    $result = $this->service->getAvailableAppointmentsList($queryParams);

    // Assert
    $this->assertIsArray($result);
    $this->assertEquals($expectedError, $result);
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 94a1a88 and 7d319ba.

📒 Files selected for processing (3)
  • zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableAppointmentsListServiceTest.php (1 hunks)
  • zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableDaysListServiceTest.php (1 hunks)
  • zmscitizenapi/tests/Zmscitizenapi/Services/Core/ValidationServiceTest.php (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Analyze (python)
  • GitHub Check: call-unit-tests / zmsdb-test
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: call-unit-tests / zmsapi-test
🔇 Additional comments (6)
zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableDaysListServiceTest.php (1)

Line range hint 28-93: Add test coverage for multiple offices and services.

The test cases only cover scenarios with single office and service IDs, but the validation service now accepts arrays. Please add test cases to cover:

  1. Multiple office IDs
  2. Multiple service IDs
  3. Mix of valid and invalid IDs in arrays
  4. Empty arrays

This will help ensure the new functionality works as expected and maintains backward compatibility.

zmscitizenapi/tests/Zmscitizenapi/Services/Core/ValidationServiceTest.php (5)

93-95: LGTM! Test case updated to support array parameters.

The test case has been correctly updated to validate the new array-based parameters for office IDs, service IDs, and service counts.


102-104: LGTM! Invalid date test case maintains array parameters.

The test case correctly maintains consistency with array parameters while testing invalid date scenarios.


114-116: LGTM! Invalid office ID test case updated.

The test case properly validates array input with an invalid office ID (0).


126-128: LGTM! Invalid service IDs test case updated.

The test case correctly validates array input with an invalid service ID ('invalid').


138-140: LGTM! Invalid service counts test case updated.

The test case properly validates array input with an invalid service count ('invalid').

Comment on lines +162 to +163
?array $officeIds,
?array $serviceIds,
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

Interface mismatch between ValidationService and ZmsApiFacadeService.

The ValidationService now accepts arrays for office and service IDs, but ZmsApiFacadeService still expects single integers. This inconsistency needs to be addressed:

  1. If the intention is to support multiple offices/services, update the facade interface accordingly
  2. If not, revert the validation service changes

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: 1

🧹 Nitpick comments (1)
zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableAppointmentsListService.php (1)

50-58: Add PHPDoc to document the groupByOffice parameter.

The purpose and effect of the groupByOffice parameter should be documented for better code maintainability.

+/**
+ * Get available appointments for the given criteria
+ * 
+ * @param object $data The appointment request data
+ * @param bool|null $groupByOffice When true, appointments are grouped by office
+ * @return array|AvailableAppointments Appointments or validation errors
+ */
 private function getAvailableAppointments(object $data, ?bool $groupByOffice = false): array|AvailableAppointments
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1105c6d and f93b834.

📒 Files selected for processing (2)
  • zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableAppointmentsListService.php (2 hunks)
  • zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: call-unit-tests / zmsapi-test
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: call-unit-tests / zmsdb-test
🔇 Additional comments (3)
zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableAppointmentsListService.php (3)

43-47: 🛠️ Refactor suggestion

Add validation for array length correspondence.

Ensure that serviceIds and serviceCounts arrays have matching lengths and correspond to each other to prevent mismatched service requests.

Consider adding this validation before the current validation call:

if (count($data->serviceIds) !== count($data->serviceCounts)) {
    return [
        'errors' => [
            'validation' => ['Service IDs and counts must have matching lengths']
        ]
    ];
}

28-30: Add validation for individual office IDs.

While the conversion from comma-separated string to array is correct, consider adding validation for the format/structure of individual office IDs to prevent invalid inputs.

 'officeIds' => isset($queryParams['officeId'])
-    ? array_map('trim', explode(',', (string) $queryParams['officeId']))
+    ? array_filter(array_map(function($id) {
+        $id = trim($id);
+        return preg_match('/^\d+$/', $id) ? $id : null;
+    }, explode(',', (string) $queryParams['officeId'])))
     : [],

32-36: Validate service counts as positive integers.

The service counts should be validated to ensure they are positive integers to prevent invalid inputs.

 'serviceCounts' => isset($queryParams['serviceCount'])
-    ? array_map('trim', explode(',', (string) $queryParams['serviceCount']))
+    ? array_filter(array_map(function($count) {
+        $count = trim($count);
+        return (is_numeric($count) && $count > 0) ? (int)$count : null;
+    }, explode(',', (string) $queryParams['serviceCount'])))
     : []
✅ Verification successful

The review comment is correct - service counts validation is necessary.

The test files confirm that service counts:

  • Must be positive integers
  • Must match the number of service IDs
  • Are validated with error messages for invalid formats

The suggested validation in the review comment would prevent runtime errors and improve API reliability.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for serviceCounts usage and validation
rg -l "serviceCount" --type php

# Look for the class implementation
ast-grep --pattern 'class AvailableAppointmentsListService {
  $$$
}'

# Search for validation patterns
rg "validate|sanitize|filter" --type php -A 2 -B 2

Length of output: 66009


Script:

#!/bin/bash
# Search for serviceCount usage in code
rg -A 5 -B 5 "serviceCount" --type php

# Look for the AvailableAppointmentsListService implementation
ast-grep --pattern 'class AvailableAppointmentsListService {
  $$$
  public function __construct($$$) {
    $$$
  }
  $$$
}'

# Search for validation patterns in ValidationService
cat zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php

Length of output: 65805

Comment on lines 61 to 71
public function getAvailableAppointmentsListByOffice($queryParams)
{
$clientData = $this->extractClientData($queryParams);

$errors = $this->validateClientData($clientData);
if (!empty($errors['errors'])) {
return $errors;
}

return $this->getAvailableAppointments($clientData, true);
}
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 type hints and documentation for the new method.

The new method should include proper type hints and documentation for better code quality and maintainability.

+/**
+ * Get available appointments grouped by office
+ *
+ * @param array $queryParams The query parameters containing date, officeId, serviceId, and serviceCount
+ * @return array|AvailableAppointments Appointments grouped by office or validation errors
+ */
-public function getAvailableAppointmentsListByOffice($queryParams)
+public function getAvailableAppointmentsListByOffice(array $queryParams): array|AvailableAppointments
📝 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 getAvailableAppointmentsListByOffice($queryParams)
{
$clientData = $this->extractClientData($queryParams);
$errors = $this->validateClientData($clientData);
if (!empty($errors['errors'])) {
return $errors;
}
return $this->getAvailableAppointments($clientData, true);
}
/**
* Get available appointments grouped by office
*
* @param array $queryParams The query parameters containing date, officeId, serviceId, and serviceCount
* @return array|AvailableAppointments Appointments grouped by office or validation errors
*/
public function getAvailableAppointmentsListByOffice(array $queryParams): array|AvailableAppointments
{
$clientData = $this->extractClientData($queryParams);
$errors = $this->validateClientData($clientData);
if (!empty($errors['errors'])) {
return $errors;
}
return $this->getAvailableAppointments($clientData, true);
}

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

🔭 Outside diff range comments (1)
zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableAppointmentsListServiceTest.php (1)

Line range hint 157-164: Replace eval-based mocking with PHPUnit's built-in mocking.

While the parameter type changes correctly reflect the new array-based functionality, using eval for mocking is discouraged due to security risks and maintainability concerns. Consider using PHPUnit's built-in mocking capabilities instead.

Example refactor:

private function createMockValidationService(array $returnValue): void
{
    $mock = $this->getMockBuilder(ValidationService::class)
        ->disableOriginalConstructor()
        ->addMethods(['validateGetAvailableAppointments'])
        ->getMock();
    
    $mock->expects($this->any())
        ->method('validateGetAvailableAppointments')
        ->willReturn($returnValue);
        
    // Inject mock into service
}

Also applies to: 174-180

🧹 Nitpick comments (1)
zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php (1)

26-35: Enhance input validation and sanitization.

The current implementation could be improved to handle edge cases more robustly:

  1. Filter out empty values after exploding
  2. Remove duplicate IDs
  3. Validate format before processing

Consider applying this improvement:

-        $queryParams['officeId'] = $queryParams['officeId'] ? (string) $queryParams['officeId'] : '';
-        $queryParams['serviceId'] = $queryParams['serviceId'] ? (string) $queryParams['serviceId'] : '';
-        // ...
-        'officeIds' => array_map('trim', explode(',', $queryParams['officeId'])),
-        'serviceIds' => array_map('trim', explode(',', $queryParams['serviceId'])),
+        $queryParams['officeId'] = isset($queryParams['officeId']) ? (string) $queryParams['officeId'] : '';
+        $queryParams['serviceId'] = isset($queryParams['serviceId']) ? (string) $queryParams['serviceId'] : '';
+        // ...
+        'officeIds' => array_unique(array_filter(array_map('trim', explode(',', $queryParams['officeId'])))),
+        'serviceIds' => array_unique(array_filter(array_map('trim', explode(',', $queryParams['serviceId'])))),
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f93b834 and e4b1108.

📒 Files selected for processing (3)
  • zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php (2 hunks)
  • zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableAppointmentsListServiceTest.php (2 hunks)
  • zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableDaysListServiceTest.php (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableDaysListServiceTest.php
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: call-unit-tests / zmsdb-test
  • GitHub Check: call-unit-tests / zmsapi-test
🔇 Additional comments (5)
zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableAppointmentsListServiceTest.php (2)

Line range hint 29-35: Well-structured test data and error handling.

The test data structure is consistent across test cases with clear error messages and proper type handling for query parameters.


Line range hint 28-43: Add test cases for multiple office IDs.

The test suite lacks coverage for the new array-based office IDs functionality. Consider adding test cases that verify:

  • Multiple office IDs being processed correctly
  • Empty office IDs array handling
  • Invalid office IDs in the array

Example test case structure:

public function testGetAvailableAppointmentsListWithMultipleOffices(): void
{
    // Arrange
    $queryParams = [
        'date' => '2025-01-15',
        'officeId' => '123,456',  // Multiple offices
        'serviceId' => '789',
        'serviceCount' => '1'
    ];
    
    $expectedAppointments = new AvailableAppointments([/* timestamps */]);
    
    $this->createMockValidationService([]);
    $this->createMockFacade($expectedAppointments);

    // Act
    $result = $this->service->getAvailableAppointmentsList($queryParams);

    // Assert
    $this->assertInstanceOf(AvailableAppointments::class, $result);
    $this->assertEquals($expectedAppointments, $result);
}
✅ Verification successful

Test coverage gap for multiple office IDs confirmed

The service implementation explicitly supports multiple office IDs through array-based processing, but there are no test cases covering this functionality. The original review suggestion to add test cases for multiple office IDs is valid and important for ensuring proper test coverage.

Key implementation details that should be tested:

  • Comma-separated office IDs parsing in extractClientData
  • Array-based office ID validation in validateClientData
  • Multiple office ID handling in getAvailableAppointments
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for test cases with multiple office IDs in the test file
echo "=== Searching test file for multiple office ID tests ==="
rg -A 5 "officeId.*['\"].*,.*['\"]" zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableAppointmentsListServiceTest.php

# Find and check the service implementation
echo -e "\n=== Finding service implementation ==="
fd -t f "AvailableAppointmentsListService.php" --exec cat {}

# Search for other related test files
echo -e "\n=== Finding related test files ==="
fd -t f ".*Test\.php$" | rg -l "officeId.*['\"].*,.*['\"]"

Length of output: 2921

zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableDaysListService.php (3)

53-53: Great improvement in type safety!

The return type change from array|AvailableDays to AvailableDays makes the contract more explicit and type-safe.


56-57: Verify array handling in ZmsApiFacadeService.

Ensure that ZmsApiFacadeService::getBookableFreeDays properly handles arrays of office and service IDs.

✅ Verification successful

Arrays are properly handled in ZmsApiFacadeService::getBookableFreeDays

The method signature explicitly declares array parameters for office and service IDs with proper type hints, ensuring correct array handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the facade method implementation
ast-grep --pattern 'function getBookableFreeDays($_)' 

Length of output: 943


Script:

#!/bin/bash
# Find the ZmsApiFacadeService file
rg -l "class ZmsApiFacadeService"

# After finding the file, we'll examine its content

Length of output: 933


Script:

#!/bin/bash
# Examine the facade service implementation
echo "=== ZmsApiFacadeService Implementation ==="
rg -A 10 "function getBookableFreeDays" zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php

echo -e "\n=== Test Cases ==="
rg -A 5 "getBookableFreeDays" zmscitizenapi/tests/Zmscitizenapi/Services/Availability/AvailableDaysListServiceTest.php

Length of output: 1045


45-46: Verify array validation in ValidationService.

Ensure that ValidationService::validateGetBookableFreeDays properly handles arrays of IDs.

✅ Verification successful

Array validation in ValidationService is properly implemented

The validateGetBookableFreeDays method is designed to handle arrays of office IDs and service IDs, with comprehensive validation including:

  • Array type checking
  • Empty array validation
  • Invalid ID detection
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the validation method implementation
ast-grep --pattern 'function validateGetBookableFreeDays($_)' 

Length of output: 951


Script:

#!/bin/bash
# Try multiple approaches to find the validation implementation
echo "=== Searching for ValidationService class ==="
rg -l "class.*ValidationService"

echo -e "\n=== Searching for validateGetBookableFreeDays method ==="
rg "validateGetBookableFreeDays"

echo -e "\n=== Looking for array validation patterns ==="
rg "validate.*\[(.*)\]" -g "*.php"

Length of output: 5834


Script:

#!/bin/bash
echo "=== ValidationService::validateGetBookableFreeDays implementation ==="
rg -A 10 "validateGetBookableFreeDays" zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php

echo -e "\n=== Array validation methods in ValidationService ==="
ast-grep --pattern 'function validateServiceArrays($_)' zmscitizenapi/src/Zmscitizenapi/Services/Core/ValidationService.php

echo -e "\n=== Test cases for array validation ==="
rg -A 5 "validateServiceArrays|validateGetBookableFreeDays" zmscitizenapi/tests/Zmscitizenapi/Services/Core/ValidationServiceTest.php

Length of output: 1966

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: 6

♻️ Duplicate comments (2)
zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableAppointmentsListService.php (1)

64-74: 🛠️ Refactor suggestion

Add return type hint and parameter validation.

The method is missing a type hint for the parameter and could benefit from early validation.

-    public function getAvailableAppointmentsListByOffice($queryParams): AvailableAppointmentsByOffice|array
+    public function getAvailableAppointmentsListByOffice(array $queryParams): AvailableAppointmentsByOffice|array
     {
+        if (empty($queryParams['officeId'])) {
+            return ['errors' => ['Office ID is required']];
+        }
+
         $clientData = $this->extractClientData($queryParams);
zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (1)

442-450: ⚠️ Potential issue

Add validation for service counts array length.

The loop assumes $serviceCounts array has the same length as $serviceIds, which could lead to undefined offset errors.

+        if (count($serviceIds) !== count($serviceCounts)) {
+            throw new InvalidArgumentException('The number of service IDs must match the number of service counts.');
+        }
+
         $serviceNumber = 0;
         foreach ($serviceIds as $serviceId) {
🧹 Nitpick comments (6)
zmsentities/schema/citizenapi/availableAppointmentsByOffice.json (1)

19-19: Add format for timestamp integers.

The schema should specify that the integers are Unix timestamps to ensure proper validation.

             "items": {
-              "type": "integer"
+              "type": "integer",
+              "format": "unix-timestamp",
+              "minimum": 0
             }
zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (2)

567-572: Consider using early returns for better readability.

The nested conditionals make the code harder to follow. Consider restructuring with early returns.

-                        if (isset($appointment->date) && isset($appointment->scope->id)) {
-                            $timestamp = (int) $appointment->date;
-                            $scopeId = (int) $appointment->scope->id;
-
-                            if ($timestamp > $currentTimestamp) {
-                                $timestamps[$scopeId][$timestamp] = true;
-                            }
-                        }
+                        if (!isset($appointment->date, $appointment->scope->id)) {
+                            continue;
+                        }
+                        
+                        $timestamp = (int) $appointment->date;
+                        $scopeId = (int) $appointment->scope->id;
+                        
+                        if ($timestamp <= $currentTimestamp) {
+                            continue;
+                        }
+                        
+                        $timestamps[$scopeId][$timestamp] = true;

582-585: Consider using array_multisort for better performance.

When sorting multiple arrays of timestamps, array_multisort might be more efficient than sorting each array individually.

-        foreach ($appointmentTimestamps as $scopeId => &$timestamps) {
-            $timestamps = array_keys($timestamps);
-            asort($timestamps);
-        }
+        $sortedTimestamps = [];
+        foreach ($appointmentTimestamps as $scopeId => $timestamps) {
+            $sortedTimestamps[$scopeId] = array_keys($timestamps);
+        }
+        array_walk($sortedTimestamps, 'sort');
+        $appointmentTimestamps = $sortedTimestamps;
zmscitizenapi/src/Zmscitizenapi/Models/AvailableAppointmentsByOffice.php (3)

18-27: Enhance constructor documentation and validation.

The constructor's parameter documentation should specify the expected array structure.

Consider this improvement:

     /**
+     * @param array<string, array<int, array{
+     *    datetime: string,
+     *    scope: int
+     * }>> $officeAppointments Array of appointments indexed by office ID
      */
     public function __construct(array $officeAppointments = [])

29-34: Improve validation error handling.

The error message is too generic and doesn't help diagnose the actual validation failure.

Consider this improvement:

     private function ensureValid(): void
     {
         if (!$this->testValid()) {
-            throw new InvalidArgumentException('The provided data is invalid according to the schema.');
+            throw new InvalidArgumentException(sprintf(
+                'Invalid office appointments data. Validation errors: %s',
+                json_encode($this->getErrors())
+            ));
         }
     }

56-59: Specify concrete return type for jsonSerialize.

The method could use a more specific return type than mixed.

Consider this improvement:

-    public function jsonSerialize(): mixed
+    public function jsonSerialize(): array
     {
         return $this->toArray();
     }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4bd2899 and 6f47aa1.

📒 Files selected for processing (4)
  • zmscitizenapi/src/Zmscitizenapi/Models/AvailableAppointmentsByOffice.php (1 hunks)
  • zmscitizenapi/src/Zmscitizenapi/Services/Availability/AvailableAppointmentsListService.php (3 hunks)
  • zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (6 hunks)
  • zmsentities/schema/citizenapi/availableAppointmentsByOffice.json (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: call-unit-tests / zmsdb-test
  • GitHub Check: call-unit-tests / zmsapi-test
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
zmscitizenapi/src/Zmscitizenapi/Models/AvailableAppointmentsByOffice.php (1)

1-9: LGTM! File structure follows PHP best practices.

The namespace declaration, strict typing, and imports are properly organized.

Comment on lines +29 to +31
'officeIds' => isset($queryParams['officeId'])
? array_map('trim', explode(',', (string) $queryParams['officeId']))
: [],
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 array mapping for office IDs.

The current implementation splits and trims the office IDs but doesn't validate the values. Consider adding validation for numeric values and removing empty entries.

             'officeIds' => isset($queryParams['officeId'])
-                ? array_map('trim', explode(',', (string) $queryParams['officeId']))
+                ? array_filter(
+                    array_map(function($id) {
+                        $id = trim($id);
+                        return is_numeric($id) ? (int)$id : null;
+                    }, explode(',', (string) $queryParams['officeId'])),
+                    function($id) { return $id !== null; }
+                )
                 : [],
📝 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
'officeIds' => isset($queryParams['officeId'])
? array_map('trim', explode(',', (string) $queryParams['officeId']))
: [],
'officeIds' => isset($queryParams['officeId'])
? array_filter(
array_map(function($id) {
$id = trim($id);
return is_numeric($id) ? (int)$id : null;
}, explode(',', (string) $queryParams['officeId'])),
function($id) { return $id !== null; }
)
: [],

Comment on lines +15 to +16
/** @var array|null */
public array|null $officeAppointments = [];
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 property type declaration and documentation.

The property declaration has several issues:

  1. The type array|null with default [] is inconsistent. If null is allowed, when would it be null?
  2. The PHPDoc lacks comprehensive structure documentation.

Consider this improvement:

-    /** @var array|null */
-    public array|null $officeAppointments = [];
+    /**
+     * Array of appointments grouped by office ID.
+     * 
+     * @var array<string, array<int, array{
+     *    datetime: string,
+     *    scope: int
+     * }>>
+     */
+    public array $officeAppointments = [];
📝 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
/** @var array|null */
public array|null $officeAppointments = [];
/**
* Array of appointments grouped by office ID.
*
* @var array<string, array<int, array{
* datetime: string,
* scope: int
* }>>
*/
public array $officeAppointments = [];

Comment on lines +41 to +51
public function toArray(): array
{
return [
'offices' => array_map(function($appointments, $officeId) {
return [
'officeId' => $officeId,
'appointments' => $appointments
];
}, $this->officeAppointments, array_keys($this->officeAppointments))
];
}
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 type safety in serialization logic.

The array transformation could be more type-safe and robust.

Consider these improvements:

     public function toArray(): array
     {
+        if (empty($this->officeAppointments)) {
+            return ['offices' => []];
+        }
+
         return [
             'offices' => array_map(
-                function($appointments, $officeId) {
+                function(array $appointments, string $officeId): array {
                     return [
                         'officeId' => $officeId,
                         'appointments' => $appointments
                     ];
                 },
                 $this->officeAppointments,
                 array_keys($this->officeAppointments)
             )
         ];
     }
📝 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 toArray(): array
{
return [
'offices' => array_map(function($appointments, $officeId) {
return [
'officeId' => $officeId,
'appointments' => $appointments
];
}, $this->officeAppointments, array_keys($this->officeAppointments))
];
}
public function toArray(): array
{
if (empty($this->officeAppointments)) {
return ['offices' => []];
}
return [
'offices' => array_map(
function(array $appointments, string $officeId): array {
return [
'officeId' => $officeId,
'appointments' => $appointments
];
},
$this->officeAppointments,
array_keys($this->officeAppointments)
)
];
}

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

♻️ Duplicate comments (1)
zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (1)

430-457: ⚠️ Potential issue

Add validation for array lengths.

The method accesses $serviceCounts[$serviceNumber] without verifying that the arrays have matching lengths. This could lead to undefined offset errors.

Apply this diff to add validation:

    ): AvailableDays|array {
        $firstDay = DateTimeFormatHelper::getInternalDateFromISO($startDate);
        $lastDay = DateTimeFormatHelper::getInternalDateFromISO($endDate);
+
+       if (count($serviceIds) !== count($serviceCounts)) {
+           throw new InvalidArgumentException('The number of service IDs must match the number of service counts.');
+       }

        $services = [];
        $providers = [];
🧹 Nitpick comments (1)
zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (1)

510-515: Document return type behavior.

The method can return different types based on the $groupByOffice parameter. Consider adding PHPDoc to clarify when each return type is used.

+    /**
+     * Get available appointments, optionally grouped by office.
+     *
+     * @param string $date The date to check for appointments
+     * @param array $officeIds Array of office IDs
+     * @param array $serviceIds Array of service IDs
+     * @param array $serviceCounts Array of service counts
+     * @param bool|null $groupByOffice Whether to group results by office
+     * @return AvailableAppointments|AvailableAppointmentsByOffice|array Returns AvailableAppointmentsByOffice when $groupByOffice is true,
+     *         AvailableAppointments otherwise, or array with errors if validation fails
+     */
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5b47911 and e1fd3bb.

📒 Files selected for processing (1)
  • zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: call-unit-tests / zmsapi-test
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: call-unit-tests / zmsdb-test
🔇 Additional comments (3)
zmscitizenapi/src/Zmscitizenapi/Services/Core/ZmsApiFacadeService.php (3)

8-8: LGTM! New imports support office-based grouping functionality.

Also applies to: 13-13


Line range hint 554-592: LGTM! Efficient implementation of timestamp grouping.

The method effectively:

  • Groups timestamps by provider ID using array_reduce
  • Validates timestamps against current time
  • Uses references to optimize memory usage

517-525: ⚠️ Potential issue

Add validation for service arrays.

The method accesses $serviceCounts[$index] without verifying that the arrays have matching lengths.

Apply this diff to add validation:

        $requests = [];
        $providers = [];
+
+       if (count($serviceIds) !== count($serviceCounts)) {
+           throw new InvalidArgumentException('The number of service IDs must match the number of service counts.');
+       }
+
        foreach ($serviceIds as $index => $serviceId) {

Likely invalid or redundant comment.

@ThomasAFink ThomasAFink merged commit 7fdf903 into next Feb 5, 2025
23 checks passed
Fabinatix97 pushed a commit that referenced this pull request Feb 7, 2025
* add zmsapi methods to base controller

* add helper methods to base controller

* refactored into services and controllers

* remove duplicate function definitions

* move helpers from base controller to new utility helper

* add a method

* Feature mpdzbs 887 zmscitizenapi post reserve appointment and refactor (#574)

* endpoint working

* fix unit tests

* one working test for post-reserve

* some clean up

* feat(ZMS-2517): fix up response for the reserve post request

* feat(ZMS-2517): add more unit tests for validations

* feat(ZMS-2517): add more unit tests for validations

* feat(ZMS-2517): Zmscitizenapi Refactor Part 1 of 3 move controllers back to root

* feat(ZMS-2517): Zmscitizenapi Refactor Part 2 of 3 create ZmsApiFacadeService ZmsApiClientService ValidationService MapperService UtilityHelper and delete fragmented services

* feat(ZMS-2517): Zmscitizenapi Refactor Part 3 of 3 clean up validations and unit tests

---------

Co-authored-by: Thomas Fink <thomasafink@Thomass-MacBook-Air.local>

* feat(MPDZBS-877): Readd zmscitizenapi to github workflow

* feat(MPDZBS-877): Readd files lost in github history

* feat(MPDZBS-877): Readd files lost in github history

* feat(MPDZBS-877): Resolve merge conflict in zmsentities

* feat(MPDZBS-877): Readd zmscitizenapi schemas to zmsentities deleted by github commit history

* (feat MPDZBS-877): update local env cli

* Feature mpdzbs 887 zms 2518 zmscitizenapi post update appointment (#587)

* (feat MPDZBS-877) readd citizenapi to  htaccess

* feat(MPDZBS-877 ZMS-2517): Working Appointment update with too many emails exception

* feat(MPDZBS-877 ZMS-2517): Test rendering working for update appointment test

* feat(MPDZBS-877 ZMS-2517): Add 63 validation unit tests for appointment update

* feat(MPDZBS-877 ZMS-2517): Refactor exception appointmentNotFound

* feat(MPDZBS-877 ZMS-2517): Add two new edge case exception tests

* feat(MPDZBS-877 ZMS-2517): Remove error_logs

---------

Co-authored-by: Thomas Fink <thomasafink@Thomass-MacBook-Air.local>

* feat(MPDZBS-877): update .gitignore

* cleanup(MPDZBS-877): Improve security and cleanup code

* fix(MPDZBS-877): fix bin configure

* fix(MPDZBS-877): fix config.example.php

* cleanup(MPDZBS-877): merge next into feature branch

* docs(MPDZBS-877): update docs for zmscitizenapi

* clean(MPDZBS-877): change friendly captcha default endpoint to eu

* clean(MPDZBS-877): change maintenance and captcha enabled to boolean

* clean(MPDZBS-877): improve internal error handling enable middleware

* feat(MPDZBS-877): return 503 for maintenance

* feat(MPDZBS-877): add generic captcha interface

* clean(MPDZBS-877): improve validation for array ids

* feat(MPDZBS-877): improve zmscitizenapi typing

* clean(MPDZBS-877): typing overhaul using zmsentities

* clean(MPDZBS-877): typing overhaul using zmsentities

* clean(MPDZBS-877): improve telephone validation regex

* clean(MPDZBS-877): improve serviceId validation regex

* clean(MPDZBS-877): fix naming issue

* clean(MPDZBS-877): make hardcoded source name dynamic

* clean(MPDZBS-877): clean up more and change citizenapi to utf8

* clean(MPDZBS-877): improve error messaging codes and expand office api with geocoordinates and address

* clean(MPDZBS-877): cleanup syntax and error handling

* clean(MPDZBS-877): cleanup syntax and error handling

* fix(MPDZBS-877): offices and services mapper

* fix(MPDZBS-877): fix reserve appointment validation

* fix(MPDZBS-877): improve some validation for empty arrays

* feat(MPDZBS-877): Improve ThinnedProcess object and cleanup some stuff with naming (#739)

* feat(MPDZB-877): Work on thinnedprocess typing

* feat(MPDZB): Refactor part 1

* feat(MPDZB): Refactor part 1

* feat(MPDZB-877): revert to processId in parameter

* feat(MPDZBS-877): refactor thinned process to object

* feat(MPDZB-877): refactor thinned process and rename controllers

---------

Co-authored-by: Tom Fink <thomasafink@Toms-MacBook-Air.local>
Co-authored-by: DDEV User <nobody@example.com>
Co-authored-by: Thomas Fink <thomasafink@Thomass-MacBook-Air.local>

* feat(MPDZBS-877): zmscitizenapi cleanup (#740)

* feat(MPDZB-877): Work on thinnedprocess typing

* feat(MPDZB): Refactor part 1

* feat(MPDZB): Refactor part 1

* feat(MPDZB-877): revert to processId in parameter

* feat(MPDZBS-877): refactor thinned process to object

* feat(MPDZB-877): refactor thinned process and rename controllers

* feat(MPDZBs-877): clean up more junk

---------

Co-authored-by: Tom Fink <thomasafink@Toms-MacBook-Air.local>
Co-authored-by: DDEV User <nobody@example.com>
Co-authored-by: Thomas Fink <thomasafink@Thomass-MacBook-Air.local>

* feat(MPDZBs-877): clean up more stuff validation improvement

* Update zmscitizenapi/src/Zmscitizenapi/Captcha.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* feat(MPDZBs-877): clean up captcha add more tests

* feat(ZMS-3430): create db indices

* feat(MPDZBS-877): Refactor Controllers and improve move typing building models

* feat(MPDZBS-877): Refactor Utilities and Helpers

* Update zmscitizenapi/src/Zmscitizenapi/Services/MapperService.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* feat(MPDZBS-877): Fix bug

* feat(MPDZBS-877): rename scope models in zmscitizenapi

* feat(MPDZBS-877): cleanup service model

* feat(MPDZBS-877): Improve ThinnedProcess and ThinnedScope models

* fix(MPDZBS-877): swagger docs

* fix(MPDZBS-877): swagger docs

* zms-2871-2874-minus-deletion-by-location-delete-and-orthography-mail-and-notification-buttons

* fix(MPDZBS-877): set up models for Office Service and Captcha

* fix(MPDZBS-877): Improve captcha typing

* Update zmscitizenapi/src/Zmscitizenapi/Models/Captcha/AltchaCaptcha.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix(MPDZBS-877): Improve captcha typing cleanup

* fix(MPDZBS-877): Improve captcha typing cleanup

* fix(MPDZBS-877): remove status from visual response

* fix(MPDZBS-877): Improve typing for Office Service and ThinnedScope

* fix(MPDZBS-877): Improve typing for Office Service Relations

* fix(MPDZBS-877): Improve typing for ThinnedProvider

* fix(MPDZBS-877): Refactor model lists to collections

* fix(MPDZBS-877): Improve typing for Combinable

* fix(MPDZBS-877): Cleanup AltchaCaptcha class

* fix(MPDZBS-877): Improve parameters for getAvailableAppointments

* fix(MPDZBS-877): Improve typing for AvailableDays and AvailableAppointments

* fix(MPDZBS-877): Cleanup schemas

* fix(MPDZBS-877): Cleanup schema mismatch

* fix(MPDZBS-877): Optimize next loops and schema typing

* fix(MPDZBS-877): Improve schema

* fix(MPDZBS-877): Improve schema

* fix(MPDZBS-877): Improve schema and error catching

* fix(MPDZBS-877): Improve api fetching safety

* fix(MPDZBS-877): Introduce strict typing for files with logic

* fix(deps): update dependency phpoffice/phpspreadsheet to v1.29.6 (#738)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update dependency squizlabs/php_codesniffer to v3.11.2 (#751)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* fix(MPDZBS-877): Introduce schema validation into the models

* fix(MPDZBS-877): Centralize validation, set default language to german, improve exception handling

* fix(MPDZBS-877): authKeyMissMatch error exception

* fix(MPDZBS-877): cleanup some code

* fix(MPDZBS-877): cleanup collection models

* Delete zmscitizenapi/templates/.keep

* Revert "Delete zmscitizenapi/templates/.keep"

This reverts commit 7725d44.

* clean(MPDZBS-877): remove comments

* fix(MPDZBS-877): errorCode fix

* fix(MPDZBS-877): validation input date bug and add unittest plus authKeyMismatch typo and add unittest

* clean(MPDZBS-877): remove unused vars

* feat(MPDZBS-877): Improve zmsapi exception handling

* feat(MPDZBS-877): Improve contact mapping and provider mapping

* Improve exception handling

* feat(MPDZBS-877): Refactor office model

* feat(MPDZBS-877): fix ProcessFreeSlots typing

* clean(MPDZBS-877): refactor and improve contoller legibility

* fix(MPDZBS-877): improve post request validation dont get request body on null fix

* clean(MPDZBS-877): improve OfficesByServiceList controller

* clean(MPDZBS-877): correct not yet implemented controllers

* chore(deps): update dependency sass to v1.83.0 (#750)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* fix(deps): update dependency phpoffice/phpspreadsheet to v1.29.7 (#752)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* clean(MPDZBS-877): Add null checks for requests to zmsapi

* chore(deps): update dependency phpspec/prophecy-phpunit to v2.3.0 (#647)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* clean(MPDZBS-877): Improve and centralize regex patterns for ValidationService

* feat(MPDZBS-877 ZMS-2523): Improve controller typing and add caching for fetchSourceData

* fix(MPDZBS-877 ZMS-2523): fix php docker version to 8.0 from 8.0.2

* clean(MPDZBS-877 ZMS-2523): Cleanup Application

* clean(MPDZBS-877 ZMS-2523): Cleanup Application

* clean(MPDZBS-877 ZMS-2523): Improve cache logger and cache permissions

* fix(MPDZBS-877 ZMS-2520): Implement preconfirmed appointment working

* clean(MPDZBS-877 ZMS-2520): remove errorlogs

* feat(MPDZBS-877 ZMS-2519 ZMS-2521): Implement appointment confirm and cancel controllers and improve request method error handling

* feat(MPDZBS-877): remove unused import statements

* clean(MPDZBS-877): fix typing

* clean(MPDZBS-877): remove unused error message

* clean(MPDZBS-877): Refactor folder structure and move logic from controllers to services

* clean(MPDZBS-877): improve input validation

* fix(MPDZBS-877): Time check with timezone

* feat(MPDZBS-877): Implement LoggerService for logging requests and when caching is set

* clean(MPDZBS-877): Remove logger redundancy

* fix(MPDZBS-877): Add logger response max size 1MB

* clean(MPDZBS-877): improve exceptions and handling in logger middleware

* feat(MPDZBS-877): optimize logger service

* feat(MPDZBS-877): optimize logger service

* clean(MPDZBS-877): improve error body logging

* feat(MPDZBS-877): optimize logger service caching

* clean(MPDZBS-877): add unit test and clean up some stuff

* clean(MPDZBS-877): add missing import

* fix(ZMS-3500) Differentiate between editing and booking a new appointment when selecting the date (#757)

* feat(MPDZBS-877 ZMS-1232): Implement security middleware Cors Csrf Security Headers Rate Limits Request Size Limits and Request Sanitation

* feat(MPDZBS-877 ZMS-1232): Refactor contoller tests and fix cors test

* feat(MPDZBS-877 ZMS-1232): improve middleware and fix race conditions in rate limiting

* clean(MPDZBS-877 ZMS-1232): small improvements to middelware and test assertions

* clean(MPDZBS-877 ZMS-1232): reduce excessive logging

* clean(MPDZBS-877 ZMS-1232): fix race Condition LoggerService

* chore(deps): update dependency seld/jsonlint to v1.11.0 (#754)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update dependency sass to v1.83.1 (#760)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* docs(MPDZBS-877): Add README.md

* docs(MPDZBS-877): Add README.md

* docs(MPDZBS-877): Update README.md

* docs(MPDZBS-877): Update README.md

* docs(MPDZBS-877): Update README.md

* fix(MPDZBS-877): unit test

* chore(deps): update dependency core-js to v3.40.0 (#761)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* docs(MPDZBS-877): Update README.md

* docs(MPDZBS-877): Update README.md

* Update README.md

* clean(MPDZBS-877): Centralize environment variables

* fix(MPDZBS-877): CORS unit tests

* clean(MPDZBS-877): centralize zmsapi exception handling and write more tests

* clean(MPDZBS-877): remove error log

* feat(MPDZBS-877): add unit test

* feat(MPDZBS-877): add MapperServiceTest

* feat(MPDZBS-877): add LoggerServiceTest ExceptionServiceTest ValidationServiceTest

* feat(MPDZBS-877): add ZmsApiFacadeServiceTest

* feat(MPDZBS-877): add ZmsApiClientServiceTest

* feat(MPDZBS-877): add AppointmentByIdServiceTest

* feat(MPDZBS-877): add AppointmentByIdServiceTest

* feat(MPDZBS-877): add AppointmentCancelServiceTest

* feat(MPDZBS-877): add AppointmentConfirmServiceTest

* feat(MPDZBS-877): add Appointment tests

* feat(MPDZBS-877): add AppointmentUpdateServiceTest

* feat(MPDZBS-877): add AvailableAppointmentsListServiceTest and AvailableDaysListServiceTest

* feat(MPDZBS-877): add Service tests

* feat(MPDZBS-877): add captcha service and application tests

* feat(MPDZBS-877): remove unneeded test

* feat(MPDZBS-877): Add LanguageMiddleware and i18n support

* feat(MPDZBS-877): Add LanguageMiddlewareTest

* feat(ZMS-3212) Notfall für Tresen deaktiveren

* feat(MPDZBS-877): clean up language error messages

* feat(MPDZBS-877): disable csrf for now

* fix(MPDZBS-877): fix ip client helper

* fix(MPDZBS-877): only log error messages in english

* feat(MPDZBS-877): disable csrf for now

* fix(MPDZBS-877): routing methods post

* fix(MPDZBS-877): routing methods get

* fix(MPDZBS-877): customTextfield save on appointment update

* fix(MPDZBS-877): customTextfield unit test

* feat(ZMS-3449): map more data

* feat(ZMS-3449): fix mapping

* feat(MPDZBS-877): Add showAlternativeLocations to offices endpoints

* Revert "feat(MPDZBS-877): Add showAlternativeLocations to offices endpoints"

This reverts commit 63fe1a0.

* feat(MPDZBS-877 ZMS-1232 ZMS-2509 ZMS-2510 ZMS-2511 ZMS-2512 ZMS-2513 ZMS-2514 ZMS-2515 ZMS-2516 ZMS-2517 ZMS-2518 ZMS-2519 ZMS-2520 ZMS-2521 ZMS-2523 ZMS-2993): Zmscitizenapi into next (#769)

* update readmes

* refactor some functions to base controller class

* add zmsapi methods to base controller

* add helper methods to base controller

* refactored into services and controllers

* remove duplicate function definitions

* move helpers from base controller to new utility helper

* add a method

* Feature mpdzbs 887 zmscitizenapi post reserve appointment and refactor (#574)

* endpoint working

* fix unit tests

* one working test for post-reserve

* some clean up

* feat(ZMS-2517): fix up response for the reserve post request

* feat(ZMS-2517): add more unit tests for validations

* feat(ZMS-2517): add more unit tests for validations

* feat(ZMS-2517): Zmscitizenapi Refactor Part 1 of 3 move controllers back to root

* feat(ZMS-2517): Zmscitizenapi Refactor Part 2 of 3 create ZmsApiFacadeService ZmsApiClientService ValidationService MapperService UtilityHelper and delete fragmented services

* feat(ZMS-2517): Zmscitizenapi Refactor Part 3 of 3 clean up validations and unit tests

---------

Co-authored-by: Thomas Fink <thomasafink@Thomass-MacBook-Air.local>

* feat(MPDZBS-877): Readd zmscitizenapi to github workflow

* feat(MPDZBS-877): Readd files lost in github history

* feat(MPDZBS-877): Readd files lost in github history

* feat(MPDZBS-877): Resolve merge conflict in zmsentities

* feat(MPDZBS-877): Readd zmscitizenapi schemas to zmsentities deleted by github commit history

* (feat MPDZBS-877): update local env cli

* Feature mpdzbs 887 zms 2518 zmscitizenapi post update appointment (#587)

* (feat MPDZBS-877) readd citizenapi to  htaccess

* feat(MPDZBS-877 ZMS-2517): Working Appointment update with too many emails exception

* feat(MPDZBS-877 ZMS-2517): Test rendering working for update appointment test

* feat(MPDZBS-877 ZMS-2517): Add 63 validation unit tests for appointment update

* feat(MPDZBS-877 ZMS-2517): Refactor exception appointmentNotFound

* feat(MPDZBS-877 ZMS-2517): Add two new edge case exception tests

* feat(MPDZBS-877 ZMS-2517): Remove error_logs

---------

Co-authored-by: Thomas Fink <thomasafink@Thomass-MacBook-Air.local>

* feat(MPDZBS-877): update .gitignore

* cleanup(MPDZBS-877): Improve security and cleanup code

* fix(MPDZBS-877): fix bin configure

* fix(MPDZBS-877): fix config.example.php

* cleanup(MPDZBS-877): merge next into feature branch

* docs(MPDZBS-877): update docs for zmscitizenapi

* clean(MPDZBS-877): change friendly captcha default endpoint to eu

* clean(MPDZBS-877): change maintenance and captcha enabled to boolean

* clean(MPDZBS-877): improve internal error handling enable middleware

* feat(MPDZBS-877): return 503 for maintenance

* feat(MPDZBS-877): add generic captcha interface

* clean(MPDZBS-877): improve validation for array ids

* feat(MPDZBS-877): improve zmscitizenapi typing

* clean(MPDZBS-877): typing overhaul using zmsentities

* clean(MPDZBS-877): typing overhaul using zmsentities

* clean(MPDZBS-877): improve telephone validation regex

* clean(MPDZBS-877): improve serviceId validation regex

* clean(MPDZBS-877): fix naming issue

* clean(MPDZBS-877): make hardcoded source name dynamic

* clean(MPDZBS-877): clean up more and change citizenapi to utf8

* clean(MPDZBS-877): improve error messaging codes and expand office api with geocoordinates and address

* clean(MPDZBS-877): cleanup syntax and error handling

* clean(MPDZBS-877): cleanup syntax and error handling

* fix(MPDZBS-877): offices and services mapper

* fix(MPDZBS-877): fix reserve appointment validation

* fix(MPDZBS-877): improve some validation for empty arrays

* feat(MPDZBS-877): Improve ThinnedProcess object and cleanup some stuff with naming (#739)

* feat(MPDZB-877): Work on thinnedprocess typing

* feat(MPDZB): Refactor part 1

* feat(MPDZB): Refactor part 1

* feat(MPDZB-877): revert to processId in parameter

* feat(MPDZBS-877): refactor thinned process to object

* feat(MPDZB-877): refactor thinned process and rename controllers

---------

Co-authored-by: Tom Fink <thomasafink@Toms-MacBook-Air.local>
Co-authored-by: DDEV User <nobody@example.com>
Co-authored-by: Thomas Fink <thomasafink@Thomass-MacBook-Air.local>

* feat(MPDZBS-877): zmscitizenapi cleanup (#740)

* feat(MPDZB-877): Work on thinnedprocess typing

* feat(MPDZB): Refactor part 1

* feat(MPDZB): Refactor part 1

* feat(MPDZB-877): revert to processId in parameter

* feat(MPDZBS-877): refactor thinned process to object

* feat(MPDZB-877): refactor thinned process and rename controllers

* feat(MPDZBs-877): clean up more junk

---------

Co-authored-by: Tom Fink <thomasafink@Toms-MacBook-Air.local>
Co-authored-by: DDEV User <nobody@example.com>
Co-authored-by: Thomas Fink <thomasafink@Thomass-MacBook-Air.local>

* feat(MPDZBs-877): clean up more stuff validation improvement

* Update zmscitizenapi/src/Zmscitizenapi/Captcha.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* feat(MPDZBs-877): clean up captcha add more tests

* feat(MPDZBS-877): Refactor Controllers and improve move typing building models

* feat(MPDZBS-877): Refactor Utilities and Helpers

* Update zmscitizenapi/src/Zmscitizenapi/Services/MapperService.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* feat(MPDZBS-877): Fix bug

* feat(MPDZBS-877): rename scope models in zmscitizenapi

* feat(MPDZBS-877): cleanup service model

* feat(MPDZBS-877): Improve ThinnedProcess and ThinnedScope models

* fix(MPDZBS-877): swagger docs

* fix(MPDZBS-877): swagger docs

* fix(MPDZBS-877): set up models for Office Service and Captcha

* fix(MPDZBS-877): Improve captcha typing

* Update zmscitizenapi/src/Zmscitizenapi/Models/Captcha/AltchaCaptcha.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix(MPDZBS-877): Improve captcha typing cleanup

* fix(MPDZBS-877): Improve captcha typing cleanup

* fix(MPDZBS-877): remove status from visual response

* fix(MPDZBS-877): Improve typing for Office Service and ThinnedScope

* fix(MPDZBS-877): Improve typing for Office Service Relations

* fix(MPDZBS-877): Improve typing for ThinnedProvider

* fix(MPDZBS-877): Refactor model lists to collections

* fix(MPDZBS-877): Improve typing for Combinable

* fix(MPDZBS-877): Cleanup AltchaCaptcha class

* fix(MPDZBS-877): Improve parameters for getAvailableAppointments

* fix(MPDZBS-877): Improve typing for AvailableDays and AvailableAppointments

* fix(MPDZBS-877): Cleanup schemas

* fix(MPDZBS-877): Cleanup schema mismatch

* fix(MPDZBS-877): Optimize next loops and schema typing

* fix(MPDZBS-877): Improve schema

* fix(MPDZBS-877): Improve schema

* fix(MPDZBS-877): Improve schema and error catching

* fix(MPDZBS-877): Improve api fetching safety

* fix(MPDZBS-877): Introduce strict typing for files with logic

* fix(MPDZBS-877): Introduce schema validation into the models

* fix(MPDZBS-877): Centralize validation, set default language to german, improve exception handling

* fix(MPDZBS-877): authKeyMissMatch error exception

* fix(MPDZBS-877): cleanup some code

* fix(MPDZBS-877): cleanup collection models

* Delete zmscitizenapi/templates/.keep

* Revert "Delete zmscitizenapi/templates/.keep"

This reverts commit 7725d44.

* clean(MPDZBS-877): remove comments

* fix(MPDZBS-877): errorCode fix

* fix(MPDZBS-877): validation input date bug and add unittest plus authKeyMismatch typo and add unittest

* clean(MPDZBS-877): remove unused vars

* feat(MPDZBS-877): Improve zmsapi exception handling

* feat(MPDZBS-877): Improve contact mapping and provider mapping

* Improve exception handling

* feat(MPDZBS-877): Refactor office model

* feat(MPDZBS-877): fix ProcessFreeSlots typing

* clean(MPDZBS-877): refactor and improve contoller legibility

* fix(MPDZBS-877): improve post request validation dont get request body on null fix

* clean(MPDZBS-877): improve OfficesByServiceList controller

* clean(MPDZBS-877): correct not yet implemented controllers

* clean(MPDZBS-877): Add null checks for requests to zmsapi

* clean(MPDZBS-877): Improve and centralize regex patterns for ValidationService

* feat(MPDZBS-877 ZMS-2523): Improve controller typing and add caching for fetchSourceData

* fix(MPDZBS-877 ZMS-2523): fix php docker version to 8.0 from 8.0.2

* clean(MPDZBS-877 ZMS-2523): Cleanup Application

* clean(MPDZBS-877 ZMS-2523): Cleanup Application

* clean(MPDZBS-877 ZMS-2523): Improve cache logger and cache permissions

* fix(MPDZBS-877 ZMS-2520): Implement preconfirmed appointment working

* clean(MPDZBS-877 ZMS-2520): remove errorlogs

* feat(MPDZBS-877 ZMS-2519 ZMS-2521): Implement appointment confirm and cancel controllers and improve request method error handling

* feat(MPDZBS-877): remove unused import statements

* clean(MPDZBS-877): fix typing

* clean(MPDZBS-877): remove unused error message

* clean(MPDZBS-877): Refactor folder structure and move logic from controllers to services

* clean(MPDZBS-877): improve input validation

* fix(MPDZBS-877): Time check with timezone

* feat(MPDZBS-877): Implement LoggerService for logging requests and when caching is set

* clean(MPDZBS-877): Remove logger redundancy

* fix(MPDZBS-877): Add logger response max size 1MB

* clean(MPDZBS-877): improve exceptions and handling in logger middleware

* feat(MPDZBS-877): optimize logger service

* feat(MPDZBS-877): optimize logger service

* clean(MPDZBS-877): improve error body logging

* feat(MPDZBS-877): optimize logger service caching

* clean(MPDZBS-877): add unit test and clean up some stuff

* clean(MPDZBS-877): add missing import

* feat(MPDZBS-877 ZMS-1232): Implement security middleware Cors Csrf Security Headers Rate Limits Request Size Limits and Request Sanitation

* feat(MPDZBS-877 ZMS-1232): Refactor contoller tests and fix cors test

* feat(MPDZBS-877 ZMS-1232): improve middleware and fix race conditions in rate limiting

* clean(MPDZBS-877 ZMS-1232): small improvements to middelware and test assertions

* clean(MPDZBS-877 ZMS-1232): reduce excessive logging

* clean(MPDZBS-877 ZMS-1232): fix race Condition LoggerService

* docs(MPDZBS-877): Add README.md

* docs(MPDZBS-877): Add README.md

* docs(MPDZBS-877): Update README.md

* docs(MPDZBS-877): Update README.md

* docs(MPDZBS-877): Update README.md

* fix(MPDZBS-877): unit test

* docs(MPDZBS-877): Update README.md

* docs(MPDZBS-877): Update README.md

* Update README.md

* clean(MPDZBS-877): Centralize environment variables

* fix(MPDZBS-877): CORS unit tests

* clean(MPDZBS-877): centralize zmsapi exception handling and write more tests

* clean(MPDZBS-877): remove error log

* feat(MPDZBS-877): add unit test

* feat(MPDZBS-877): add MapperServiceTest

* feat(MPDZBS-877): add LoggerServiceTest ExceptionServiceTest ValidationServiceTest

* feat(MPDZBS-877): add ZmsApiFacadeServiceTest

* feat(MPDZBS-877): add ZmsApiClientServiceTest

* feat(MPDZBS-877): add AppointmentByIdServiceTest

* feat(MPDZBS-877): add AppointmentByIdServiceTest

* feat(MPDZBS-877): add AppointmentCancelServiceTest

* feat(MPDZBS-877): add AppointmentConfirmServiceTest

* feat(MPDZBS-877): add Appointment tests

* feat(MPDZBS-877): add AppointmentUpdateServiceTest

* feat(MPDZBS-877): add AvailableAppointmentsListServiceTest and AvailableDaysListServiceTest

* feat(MPDZBS-877): add Service tests

* feat(MPDZBS-877): add captcha service and application tests

* feat(MPDZBS-877): remove unneeded test

* feat(MPDZBS-877): Add LanguageMiddleware and i18n support

* feat(MPDZBS-877): Add LanguageMiddlewareTest

* feat(MPDZBS-877): clean up language error messages

* feat(MPDZBS-877): disable csrf for now

* fix(MPDZBS-877): fix ip client helper

* fix(MPDZBS-877): only log error messages in english

* feat(MPDZBS-877): disable csrf for now

* fix(MPDZBS-877): routing methods post

* fix(MPDZBS-877): routing methods get

* fix(MPDZBS-877): customTextfield save on appointment update

* fix(MPDZBS-877): customTextfield unit test

* feat(MPDZBS-877): Add showAlternativeLocations to offices endpoints

* Revert "feat(MPDZBS-877): Add showAlternativeLocations to offices endpoints"

This reverts commit 63fe1a0.

---------

Co-authored-by: Thomas Fink <thomasafink@Thomass-MacBook-Air.local>
Co-authored-by: Tom Fink <thomasafink@Toms-MacBook-Air.local>
Co-authored-by: Thomas Fink <thomasfink@Thomass-MacBook-Air.local>
Co-authored-by: DDEV User <nobody@example.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Thomas Fink <thomasafink@thomass-air.speedport.ip>

* docs(MPDZBS-877): Update README.md

* feat(ZMS-3449): adjust schema

* feat(ZMS-3449): fix object argument

* feat(ZMS-3449): fix typo

* Update .env.template

* feat(ZMS-3449): fix mapping

* feat(ZMS-3449): fix tests

* feat(ZMS-3449): fix tests

* feat(ZMS-3499) refresh queue even when losing focus

* Update .env.template

* feat(ZMS-3459): return slotTimeInMinutes

* feat(ZMS-3430): add indexes

* feat(ZMS-3430): remove indexes

* writeCanceledSlots-time shortened to 5 minutes

* Temporarily disable cors zmscitizenapi (#795)

* disable cors middleware

* Update CorsMiddlewareTest.php

* Update CorsMiddlewareTest.php

* Update bootstrap.php

* Update SecurityHeadersMiddlewareTest.php

* feat(ZMS-3519) sortierung für queueList

* feat(ZMS-3430): fix test

* feat(ZMS-3503): added logic to end emergency with checkbox

* feat(ZMS-3503): removed console.log and unesscessy function

* feat(ZMS-3503): removed console.log and unesscessy function

* feat(ZMS-3503): removed console.log and unnecessary functions

* fix(deps): update dependency phpoffice/phpspreadsheet to v1.29.8 [security] (#794)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update dependency sass to v1.83.4 (#806)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat(ZMS-3507): redirect without appointment (#775)

* fix(deps): update dependency phpoffice/phpspreadsheet to v1.29.9 [security] (#814)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat(ZMS-3503): added explanation to the function

* feat(ZMS-3499) Tabelle für die Warteschlange wird aktualisiert auch bei Mouse-Hovering

* feat(ZMS-3460): create endpoint for free appointments grouped by office (#797)

* feat(ZMS-3460): create endpoint for free appointments grouped by office

* feat(ZMS-3460): fix test

* feat(ZMS-3460): fix tests

* feat(ZMS-3460): fix tests

* feat(ZMS-3460): fix tests

* feat(ZMS-3460): fix tests

* feat(ZMS-3460): fix tests

* feat(ZMS-3460): fix tests

* feat(ZMS-3460): fix tests

* feat(ZMS-3460): fix tests

* feat(ZMS-3460): fix tests

* feat(ZMS-3460): fix route

* feat(ZMS-3460): refactoring

* feat(ZMS-3460): show provider, not scope id

* feat(ZMS-3460): fix provider id

---------

Co-authored-by: Thomas Fink <tom@Thomass-MacBook-Air.local>

* fix(ZMS): show alternative locations for offices (#820)

Co-authored-by: Thomas Fink <tom@Thomass-MacBook-Air.local>

* fix(zms): Update .env.template local env

---------

Co-authored-by: Thomas Fink <thomasafink@Thomass-MacBook-Air.local>
Co-authored-by: Tom Fink <thomasafink@Toms-MacBook-Air.local>
Co-authored-by: Thomas Fink <thomasfink@Thomass-MacBook-Air.local>
Co-authored-by: DDEV User <nobody@example.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Igor Manjencic <manjak.igor@gmail.com>
Co-authored-by: matthias1996 <matthias.lorenz@muenchen.de>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Thomas Fink <thomasafink@thomass-air.speedport.ip>
Co-authored-by: MoDaae <90261750+MoDaae@users.noreply.github.com>
Co-authored-by: mohamad.daaeboul <mohamad.daaeboul@muenchen.de>
Co-authored-by: Thomas Fink <tom@Thomass-MacBook-Air.local>
Co-authored-by: Fabian Breitling <83815772+msfb3@users.noreply.github.com>
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.

2 participants