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

Scheduling and Appointments: Validations and other minor fixes #2711

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from

Conversation

rithviknishad
Copy link
Member

@rithviknishad rithviknishad commented Jan 6, 2025

Proposed Changes

  • Separate API for cancelling a booking and prevent cancelling via PUT/PATCH on token booking viewset.
  • Heatmap / get slots for day: exclude cancelled statuses (inherently achieved without code changes as cancel API subtracts tokens allocated)
  • Fixes create exception not working
  • Prevent schedule deletions if active booking are present in future
  • Prevent updations to availability records
  • Heatmap / get slots for day: exclude open schedules

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced booking cancellation process with new validation and handling mechanisms.
    • Added more robust schedule deletion checks to prevent conflicts with future bookings.
    • Introduced a new AvailabilityViewSet for managing availability instances.
  • Bug Fixes

    • Improved authorization logic for availability exceptions.
    • Added validation to prevent improper booking status updates.
  • Refactoring

    • Simplified user resource retrieval in availability exceptions.
    • Removed deprecated resource type options.
    • Updated booking specification models to enhance error handling and validation.
    • Enhanced routing structure to manage availability-related data within scheduling.

Copy link

coderabbitai bot commented Jan 6, 2025

📝 Walkthrough

Walkthrough

The pull request introduces several modifications across multiple files in the scheduling and resource management components. The changes primarily focus on simplifying user and booking-related logic, removing unnecessary model dependencies, and enhancing authorization and validation processes for scheduling operations. The modifications streamline how users, availability exceptions, and bookings are handled, with a particular emphasis on reducing complexity in user retrieval and booking cancellation mechanisms. It seems like someone finally decided to tidy up the code a bit—how refreshing!

Changes

File Change Summary
care/emr/api/viewsets/scheduling/availability_exceptions.py Removed SchedulableUserResource dependency, simplified user retrieval logic.
care/emr/api/viewsets/scheduling/booking.py Added booking cancellation logic, new CancelBookingSpec, enhanced TokenBookingViewSet.
care/emr/api/viewsets/scheduling/schedule.py Introduced perform_delete method with future booking validation. Added AvailabilityViewSet for managing availability instances.
care/emr/resources/scheduling/availability_exception/spec.py Replaced resource attribute with user in AvailabilityExceptionWriteSpec.
care/emr/resources/scheduling/schedule/spec.py Removed ResourceTypeOptions enumeration, added AvailabilityUpdateSpec for enhanced validation.
care/emr/resources/scheduling/slot/spec.py Renamed TokenBookingUpdateSpec to TokenBookingWriteSpec, added status validation.
care/emr/models/scheduling/schedule.py Updated schedule field in Availability model to include related_name='availabilities'.
config/api_router.py Added AvailabilityViewSet to routing structure for managing availability-related data.

Sequence Diagram

sequenceDiagram
    participant User
    participant BookingViewSet
    participant CancelBookingSpec
    participant TokenSlot
    
    User->>BookingViewSet: Request Booking Cancellation
    BookingViewSet->>CancelBookingSpec: Validate Cancellation Reason
    CancelBookingSpec-->>BookingViewSet: Validation Result
    BookingViewSet->>TokenSlot: Decrement Allocated Count
    BookingViewSet->>BookingViewSet: Update Booking Status
Loading

Possibly Related PRs

  • Add discharge summary for encounters #2700: The changes in this PR involve modifications to the discharge summary functionality, which is related to the changes in the AvailabilityExceptionsViewSet class in the main PR that also simplifies user retrieval logic, indicating a broader shift towards user-centric data handling in the application.
  • Scheduling Validations #2701: This PR modifies the FacilitySchedulableUsersViewSet to change how users are retrieved, aligning with the main PR's focus on simplifying user authorization logic by directly referencing the User model instead of the SchedulableUserResource.

Suggested Reviewers

  • vigneshhari: Familiar with the scheduling and resource management components.

Poem

🕰️ Schedules dance, bookings sway
Complexity melts, a cleaner way
Resources untangled, logic refined
A system where simplicity is designed
Code pirouettes with elegant grace 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.

@vigneshhari vigneshhari marked this pull request as ready for review January 6, 2025 16:03
@vigneshhari vigneshhari requested a review from a team as a code owner January 6, 2025 16:03
Copy link

@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 (3)
care/emr/resources/scheduling/availability_exception/spec.py (1)

39-39: Validate user existence earlier or handle multiple matches.

Retrieving the user object here is fine, but it might be gentler to validate earlier or provide a more detailed error message if the user is missing or ambiguous. Users sometimes claim confusion if they can’t figure out which user ID is invalid.

care/emr/api/viewsets/scheduling/availability_exceptions.py (1)

42-48: Streamline authorization and unify logic.

Extracting the facility and user objects directly is a welcome simplification. However, verify that all references to SchedulableUserResource in parallel code paths are cleanly removed to avert any partially leftover logic. Also, watch for potential duplication in your authorization code.

care/emr/api/viewsets/scheduling/booking.py (1)

107-117: cancel_appointment_handler
Good concurrency flow. Subtly, if multiple cancellations target the same booking simultaneously, the lock ensures consistency. Just watch out for any negative allocated states.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d010b8c and 0cc83b3.

📒 Files selected for processing (6)
  • care/emr/api/viewsets/scheduling/availability_exceptions.py (2 hunks)
  • care/emr/api/viewsets/scheduling/booking.py (4 hunks)
  • care/emr/api/viewsets/scheduling/schedule.py (3 hunks)
  • care/emr/resources/scheduling/availability_exception/spec.py (1 hunks)
  • care/emr/resources/scheduling/schedule/spec.py (0 hunks)
  • care/emr/resources/scheduling/slot/spec.py (2 hunks)
💤 Files with no reviewable changes (1)
  • care/emr/resources/scheduling/schedule/spec.py
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test / test
🔇 Additional comments (21)
care/emr/resources/scheduling/availability_exception/spec.py (1)

33-33: Confirm field name aligns with domain model.

While changing from resource to user improves clarity, please ensure that this field's naming convention also reflects the broader domain model. In future, any references to "resource" will likely need rework.

care/emr/api/viewsets/scheduling/availability_exceptions.py (2)

7-7: Remove unused import references or clarify usage.

Since AvailabilityException is used, it’s acceptable here. Consider verifying if there are no stale references from your earlier refactor that might remain in other modules.


14-14: Confirm user import usage.

Be absolutely sure the shift to a direct User import is consistent across all references. A mismatch with the old SchedulableUserResource might cause a subtle drift in code usage.

care/emr/api/viewsets/scheduling/schedule.py (4)

2-2: Import timezone looks appropriate
This import is used properly below for comparisons with the current time.


10-10: TokenSlot import is used in future booking checks
No immediate concerns.


20-20: Lock import is consistent
It's nice to see concurrency concerns being addressed with a locking mechanism.


49-65: Verify concurrency and future booking checks
The methodology for preventing schedule deletions when future bookings exist appears sensible. While the lock usage helps avoid concurrent deletions, you might want to verify whether subsequent changes to availability can occur while this transaction is in progress. A thorough test would be wise to ensure no corner cases slip by.

✅ Verification successful

Concurrency and booking checks are properly implemented
The combination of resource-level locking and database transactions ensures safe schedule deletion. The future booking check is comprehensive and properly atomic. No changes needed, though you might want to add a test if you're feeling particularly thorough about it.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searching for references to perform_delete for concurrency usage
rg -A 5 "perform_delete"

Length of output: 1846

care/emr/api/viewsets/scheduling/booking.py (11)

1-2: Literal import
Typing clarity is always nice; no issues with adding Literal.


6-6: BaseModel import
Using Pydantic's BaseModel is consistent with the rest of the code.


20-21: Cancellation references
These references to status choices align with the new cancellation flow.

Also applies to: 23-23


28-28: Lock import ensures concurrency
Similar to schedule.py, using Lock for bookings is a thorough approach.


31-34: CancelBookingSpec
Requiring a reason for cancellation is good for audit trails.


61-61: Blank line
No changes needed, but thanks for the spacing.


63-63: Removal of delete mixin
Excluding EMRDeleteMixin is a safer design if you want to handle cancellations separately.


66-66: Switch to TokenBookingWriteSpec
By defaulting to the write spec, ensure that older usage patterns remain unaffected.


68-68: Unified write model
Using the same spec for create and update is consistent with the new flow, but carefully verify that no read-only fields get overwritten.


86-86: PermissionDenied message
Explicitly referencing "update bookings" clarifies the error. Good improvement.


118-123: New cancel action
A dedicated cancellation endpoint is a cleaner approach. This matches the PR objective of preventing cancellation via other methods.

care/emr/resources/scheduling/slot/spec.py (3)

5-5: ValidationError import
This import is necessary for the new restriction logic below, so no issue here.


68-68: TokenBookingWriteSpec
Renaming from TokenBookingUpdateSpec clarifies its unified role for writes.


71-74: Enforcing separate cancellation flow
Rejecting status changes to a canceled state here is a succinct way to force the official cancellation endpoint usage, though it might feel a bit strict if there's a corner case.

Comment on lines 55 to 60
def lock_cancel_appointment(token_booking):
token_slot = token_booking.token_slot
with Lock(f"booking:slot:{token_slot.id}"), transaction.atomic():
token_slot.allocated -= 1
token_slot.save()

Copy link

@coderabbitai coderabbitai bot Jan 6, 2025

Choose a reason for hiding this comment

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

💡 Codebase verification

Slot allocation needs validation
The lock prevents race conditions, but there's nothing stopping the allocation from going negative. You might want to add a quick check before decrementing, like if token_slot.allocated > 0. I mean, unless negative appointments are your thing.

  • Add validation in lock_cancel_appointment before decrementing
  • Consider adding a CheckConstraint to the TokenSlot model to enforce non-negative values
🔗 Analysis chain

Slot lock and decrement
This correctly decrements allocation within a transaction. Keep in mind to confirm that the allocated count never goes below zero if multiple cancellations happen in quick succession.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searching for any references to 'allocated -= 1' to ensure there's no conflicting code
rg -A 5 "allocated -= 1"

Length of output: 446


Script:

#!/bin/bash
# Find TokenSlot model definition
ast-grep --pattern 'class TokenSlot($$$):'

# Check for any validation on allocated field
rg -B 5 "allocated = " 

Length of output: 615


Script:

#!/bin/bash
# Check for allocation increments
rg -A 5 "allocated \+= 1"

# Look for validation methods on TokenSlot
ast-grep --pattern 'def $_(self$$$): 
  $$$
  allocated$$$
  $$$'

Length of output: 591

Copy link
Member Author

Choose a reason for hiding this comment

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

If we add this check, that means somewhere an extra reduction is happening accidentally right, and the root cause of it would never see the day of light right? 🤔

Copy link

Choose a reason for hiding this comment

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

@rithviknishad, that’s a fair concern. Adding a check (or constraint) can indeed mask a deeper bug if the decrement is happening more often than it should. In some cases, though, a safeguard is still useful to prevent corrupted state, especially if the root cause isn’t trivial to pinpoint quickly. One possible compromise is to raise an exception (or log a warning) whenever allocated would go negative. That way, the data remains valid, but you also become aware (immediately!) if something is decrementing one time too many.

@@ -89,6 +104,23 @@ def get_queryset(self):
.order_by("-modified_date")
)

@classmethod
Copy link
Member

Choose a reason for hiding this comment

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

Why is it a classmethod?

Copy link
Member Author

Choose a reason for hiding this comment

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

i just tried to stick with similar pattern as of create appointment. will revert 😅

image

Copy link
Member

Choose a reason for hiding this comment

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

These are classmethods because they are called from the OTP based viewsets as well.

care/emr/api/viewsets/scheduling/booking.py Outdated Show resolved Hide resolved
care/emr/api/viewsets/scheduling/booking.py Outdated Show resolved Hide resolved
@vigneshhari
Copy link
Member

Create the API from the OTP perspective as well. User should be able to cancel a booked appointment

Copy link

@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

♻️ Duplicate comments (1)
care/emr/api/viewsets/scheduling/booking.py (1)

99-111: ⚠️ Potential issue

That allocated count decrement looks awfully brave

I see we're still living dangerously with unconditional decrements. While I appreciate the optimism in assuming nothing could go wrong, perhaps we could add a small check? You know, just in case reality doesn't match our expectations.

 with transaction.atomic():
     if instance.status not in CANCELLED_STATUS_CHOICES:
         # Free up the slot if it is not cancelled already
+        if instance.token_slot.allocated <= 0:
+            raise ValueError("Cannot decrement allocation: already at zero")
         instance.token_slot.allocated -= 1
         instance.token_slot.save()
🧹 Nitpick comments (4)
care/emr/api/viewsets/scheduling/schedule.py (1)

49-51: Consider optimizing the lock scope.

The lock acquisition spans the entire update operation. While this ensures thread safety, it might be holding the lock longer than strictly necessary. Perhaps we could narrow down the critical section?

care/emr/resources/scheduling/schedule/spec.py (1)

89-120: Consider optimizing the allocated tokens queries.

While the validation logic is solid, we're making two separate queries that could potentially be combined into one. Just saying, databases have feelings too.

-        old_allocated_sum = (
-            TokenSlot.objects.filter(
-                resource=old_instance.resource,
-                availability__schedule__id=obj.id,
-                start_datetime__gte=old_instance.valid_from,
-                start_datetime__lte=old_instance.valid_to,
-            ).aggregate(total=Sum("allocated"))["total"]
-            or 0
-        )
-
-        new_allocated_sum = (
-            TokenSlot.objects.filter(
-                resource=old_instance.resource,
-                availability__schedule__id=obj.id,
-                start_datetime__gte=self.valid_from,
-                start_datetime__lte=self.valid_to,
-            ).aggregate(total=Sum("allocated"))["total"]
-            or 0
-        )
+        from django.db.models import Case, When, Value, IntegerField
+        allocated_sums = TokenSlot.objects.filter(
+            resource=old_instance.resource,
+            availability__schedule__id=obj.id,
+        ).aggregate(
+            old_sum=Sum(Case(
+                When(
+                    start_datetime__gte=old_instance.valid_from,
+                    start_datetime__lte=old_instance.valid_to,
+                    then='allocated'
+                ),
+                default=Value(0),
+                output_field=IntegerField(),
+            )),
+            new_sum=Sum(Case(
+                When(
+                    start_datetime__gte=self.valid_from,
+                    start_datetime__lte=self.valid_to,
+                    then='allocated'
+                ),
+                default=Value(0),
+                output_field=IntegerField(),
+            ))
+        )
+        old_allocated_sum = allocated_sums['old_sum'] or 0
+        new_allocated_sum = allocated_sums['new_sum'] or 0
care/emr/api/viewsets/scheduling/availability.py (1)

182-182: Improve error message structure.

The error message {"Patient not found"} could be more specific. Perhaps something like {"error": "Patient with id {request_data.patient} not found"}?

-            raise ValidationError({"Patient not found"})
+            raise ValidationError({
+                "error": f"Patient with id {request_data.patient} not found"
+            })
care/emr/api/viewsets/scheduling/booking.py (1)

77-78: Authorization message improved, but scope could be better

The error message is more accurate now, but shouldn't we also check if the booking is in a cancellable state before allowing updates? Just a thought.

-            raise PermissionDenied("You do not have permission to update bookings")
+            raise PermissionDenied(
+                "You do not have permission to update bookings in their current state"
+            )
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0cc83b3 and 049c3e5.

📒 Files selected for processing (6)
  • care/emr/api/viewsets/scheduling/availability.py (1 hunks)
  • care/emr/api/viewsets/scheduling/booking.py (4 hunks)
  • care/emr/api/viewsets/scheduling/schedule.py (3 hunks)
  • care/emr/migrations/0002_alter_availability_schedule.py (1 hunks)
  • care/emr/models/scheduling/schedule.py (1 hunks)
  • care/emr/resources/scheduling/schedule/spec.py (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • care/emr/migrations/0002_alter_availability_schedule.py
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test / test
🔇 Additional comments (6)
care/emr/api/viewsets/scheduling/schedule.py (1)

76-80: LGTM! Clean user retrieval logic.

The conditional user retrieval looks good. Nice defensive programming there!

care/emr/models/scheduling/schedule.py (1)

23-25: Verify migration for related_name addition.

Adding related_name is good for reverse lookups, but let's make sure we have the corresponding migration. You wouldn't want to leave your database in an inconsistent state, would you?

✅ Verification successful

Migration verified, you're all set 🎯

I can see you've already taken care of the migration like a responsible developer. The migration file 0002_alter_availability_schedule.py properly handles the related_name addition. How... unexpectedly thorough of you.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for migration file containing related_name change
rg -l "related_name.*availabilities" care/emr/migrations/*.py

Length of output: 218


Script:

#!/bin/bash
# Display content of the migration file
cat care/emr/migrations/0002_alter_availability_schedule.py

Length of output: 617

care/emr/resources/scheduling/schedule/spec.py (1)

63-67: LGTM! Simple and effective validation.

Clean period validation. Short, sweet, and to the point.

care/emr/api/viewsets/scheduling/booking.py (3)

1-34: Nice work with the Pydantic validation!

The CancelBookingSpec class is well-structured and properly constrains the cancellation reasons. I suppose we're finally getting serious about input validation.


113-117: Clean implementation of the cancel endpoint

Nice separation of concerns between authorization and handling. The implementation is refreshingly straightforward, which is... unusual for this codebase.


55-61: Consider separating create and update specifications

Using the same TokenBookingWriteSpec for both creation and updates might be a bit... optimistic. Different validation rules typically apply for these operations, but I'm sure you've thought this through.

Let's check if there are any validation differences:

Comment on lines +53 to +68
def perform_delete(self, instance):
with Lock(f"booking:resource:{instance.resource.id}"), transaction.atomic():
# Check if there are any tokens allocated for this schedule in the future
availabilities = instance.availabilities.all()
has_future_bookings = TokenSlot.objects.filter(
resource=instance.resource,
availability_id__in=availabilities.values_list("id", flat=True),
start_datetime__gt=timezone.now(),
allocated__gt=0,
).exists()
if has_future_bookings:
raise ValidationError(
"Cannot delete schedule as there are future bookings associated with it"
)
availabilities.update(deleted=True)
super().perform_delete(instance)
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Your database queries could use a little optimization boost.

The review comment about adding indexes is valid. The TokenSlot model lacks indexes on start_datetime and allocated fields, which could make your future booking queries slower than a sloth climbing a tree. However, the race condition concern is incorrect - the combination of resource-level locking and atomic transaction already handles this elegantly.

  • Add a migration to create indexes on TokenSlot.start_datetime and TokenSlot.allocated
🔗 Analysis chain

Add index for future booking queries.

The query filtering future bookings would benefit from an index on start_datetime and allocated fields. I mean, unless you enjoy watching your database work harder than it needs to.

Potential race condition in future bookings check.

Even with the lock, there's a tiny window between checking for future bookings and actual deletion where new bookings could be created. Consider adding a status field to prevent new bookings during deletion.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any indexes on start_datetime and allocated fields
rg -A 5 "class Migration|^    indexes = \[" care/emr/migrations/*.py

Length of output: 956


Script:

#!/bin/bash
# Find TokenSlot model definition and any related indexes
echo "=== TokenSlot Model Definition ==="
ast-grep --pattern 'class TokenSlot($$$):'

echo -e "\n=== Searching all migrations for TokenSlot indexes ==="
rg -l "TokenSlot" care/emr/migrations/*.py | xargs cat

Length of output: 60793

Copy link

codecov bot commented Jan 7, 2025

Codecov Report

Attention: Patch coverage is 45.38462% with 71 lines in your changes missing coverage. Please review.

Project coverage is 45.95%. Comparing base (b42bfe6) to head (9f7f57e).
Report is 5 commits behind head on develop.

Files with missing lines Patch % Lines
care/emr/api/viewsets/scheduling/schedule.py 39.21% 31 Missing ⚠️
care/emr/resources/scheduling/schedule/spec.py 48.83% 22 Missing ⚠️
care/emr/api/viewsets/scheduling/booking.py 43.47% 13 Missing ⚠️
...api/viewsets/scheduling/availability_exceptions.py 50.00% 2 Missing ⚠️
care/emr/resources/scheduling/slot/spec.py 60.00% 2 Missing ⚠️
...esources/scheduling/availability_exception/spec.py 50.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #2711      +/-   ##
===========================================
- Coverage    45.97%   45.95%   -0.02%     
===========================================
  Files          315      313       -2     
  Lines        17532    17565      +33     
  Branches      1682     1690       +8     
===========================================
+ Hits          8060     8072      +12     
- Misses        9427     9433       +6     
- Partials        45       60      +15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

@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)
care/emr/resources/scheduling/schedule/spec.py (2)

42-56: Consider optimizing the overlapping time validation.

The nested loops for checking overlapping time ranges have O(n²) complexity. For larger schedules, this could become a performance bottleneck.

Consider using an interval tree data structure for more efficient overlap detection:

from intervaltree import IntervalTree

@field_validator("availability", mode="after")
def validate_availability(cls, availabilities: list[AvailabilityDateTimeSpec]):
    day_trees = {}
    for avail in availabilities:
        if avail.day_of_week not in day_trees:
            day_trees[avail.day_of_week] = IntervalTree()
        tree = day_trees[avail.day_of_week]
        if tree.overlaps(avail.start_time, avail.end_time):
            raise ValueError("Availability time ranges are overlapping")
        tree.addi(avail.start_time, avail.end_time)
    return availabilities

64-80: Robust token validation, but consider edge cases.

The validation for preventing token modifications that would affect future bookings is well implemented. However, you might want to add a grace period to avoid race conditions with imminent bookings.

Consider adding a small buffer time:

-            start_datetime__gte=timezone.now(),
+            start_datetime__gte=timezone.now() + timezone.timedelta(minutes=5),
care/emr/api/viewsets/scheduling/schedule.py (2)

51-54: Consider adding timeout to the lock.

While the locking mechanism is good, it might benefit from a timeout to prevent indefinite waiting.

-        with Lock(f"booking:resource:{instance.resource.id}"):
+        with Lock(f"booking:resource:{instance.resource.id}", timeout=30):

185-189: Consider simplifying authorization chain.

The authorization chain could be simplified since authorize_update and authorize_delete both delegate to authorize_create.

-    def authorize_update(self, request_obj, model_instance):
-        self.authorize_create({}, model_instance)
-
-    def authorize_delete(self, instance):
-        self.authorize_update({}, instance)
+    def _authorize_common(self, instance):
+        facility = self.get_facility_obj()
+        schedule_user = self.get_schedule_obj().resource.user
+        if not AuthorizationController.call(
+            "can_write_user_schedule", self.request.user, facility, schedule_user
+        ):
+            raise PermissionDenied("You do not have permission to create schedule")
+
+    authorize_update = authorize_delete = _authorize_common
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 049c3e5 and 9f7f57e.

📒 Files selected for processing (3)
  • care/emr/api/viewsets/scheduling/schedule.py (5 hunks)
  • care/emr/resources/scheduling/schedule/spec.py (5 hunks)
  • config/api_router.py (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test / test
🔇 Additional comments (3)
config/api_router.py (1)

43-47: LGTM! Clean routing setup.

The nested router configuration for availability management is well-structured and follows REST conventions.

Also applies to: 175-180

care/emr/resources/scheduling/schedule/spec.py (1)

108-111: LGTM! Clear period validation.

The validation ensures logical consistency in schedule periods.

care/emr/api/viewsets/scheduling/schedule.py (1)

59-64: Add index for future booking queries.

The query filtering future bookings would benefit from an index on start_datetime and allocated fields.

@vigneshhari
Copy link
Member

Is this ready for review ?

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