Skip to content

Conversation

anwarpatelnoori
Copy link
Contributor

@anwarpatelnoori anwarpatelnoori commented Jul 19, 2025

Closes #3362

Please provide enough information so that others can review your pull request:

  • Shift field is already present in Employee Attendance DocType.
  • Shift field is not used in filters while fetching employees
  • But while marking the attendance the field is used
  • So I added another _get_unmarked_attendance_with_shift() to fetch the employees based on shift assignment

Explain the details for making this change. What existing problem does the pull request solve?
If ERPNext setup has over 4,000 employees, and their HR team uses the Employee Attendance Tool exclusively to mark attendance.

  • Each shift contains around 1,000+ employees.
    
  • Currently, the tool fetches employees from all shifts, regardless of which shift is being assigned .
    
  • As a result, HR staff have to manually remove employees who are not part of the target shift before proceeding.
    
  • This process is time-consuming given the volume of employees.
    
  • A shift-based filter would significantly improve efficiency and accuracy when marking attendance.
    
image > Screenshots/GIFs

Added Filter By Shift check box in filters section and made Shift reqd
image

Filter.By.Shift.mp4

Summary by CodeRabbit

  • New Features

    • Added a "Filter by Shift" option to the Employee Attendance Tool; when enabled, Shift becomes required and can be used to narrow results.
  • Bug Fixes

    • Employee lists now correctly show unmarked attendance only for employees on the selected shift (via assignment or default).
  • Tests

    • Added tests to validate shift-based filtering of unmarked attendance.

no-docs

@anwarpatelnoori
Copy link
Contributor Author

@asmitahase can you review and give feed back

asmitahase
asmitahase previously approved these changes Jul 30, 2025
Comment on lines +73 to +74
if filter_by_shift:
unmarked_attendance = _get_unmarked_attendance_with_shift(unmarked_attendance, shift, date)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Implementing filter by shift this way has one consequence of fetching employees with empty default shift if filter_by_shift is checked but shift isn't set. For other filters like company, department etc, if there's no value for filters all employees are fetched.

Comment on lines 94 to 101
shift_assigned_employees = frappe.get_list(
'Shift Assignment',
filters = {
'shift_type': shift,
'start_date': ['<=', frappe.utils.getdate(date)],
},
fields=['employee']
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

One more caveat is, because we're getting data from two different doctypes, get_list isn't enough to ensure all the filters are "and"ed e.g if someone wants to fetch employees from department A and shift B, it won't be ensured because shift assignment may have employees belonging to different department.

It's better to use query builder to select employees in this case. And while we're half way there, might as well use that to separate unmarked and half day marked employees too. I'll contribute to this. Looks good enough for now.

Copy link
Contributor Author

@anwarpatelnoori anwarpatelnoori Jul 30, 2025

Choose a reason for hiding this comment

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

Thanks for your feedback! @asmitahase . The cases you mentioned are already covered in the current filter logic.

  1. The employee_list is first filtered to get the unmarked attendance through the _get_unmarked_attendance function, which ensures that all necessary conditions (such as department, grades or other filters) are applied.
  2. Using the same filtered unmarked_attendance, I'm further refining it by checking the shift assignments (both default shifts and shift assignments). This ensures that only employees assigned to the relevant shift are included.

Please correct me if I’m wrong in the current logic. Should I work on the requested changes if the filtering with shift logic is incorrect?

@asmitahase
Copy link
Collaborator

hey @anwarpatelnoori could you fix the linter errors.
here's a guideline for semantic commit messages https://gist.github.com/joshbuchea/6f47e86d2510bce28f8e7f42ae84c716

@anwarpatelnoori
Copy link
Contributor Author

Ok I will do this👍

Copy link
Contributor

coderabbitai bot commented Aug 5, 2025

Walkthrough

Adds shift-based filtering to the Employee Attendance Tool. DocType: new "Filter by Shift" checkbox and "Shift" field now has mandatory_depends_on on that checkbox. Client JS now sends shift and filter_by_shift when loading employees. Server: get_employees gains shift and filter_by_shift parameters and uses a new helper _get_unmarked_attendance_with_shift to filter unmarked attendance by shift (assignments and default_shift). A unit test for the helper was added (duplicated test present).


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 39c8001 and 0d18fa8.

📒 Files selected for processing (1)
  • hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary

🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
  • 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 explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

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

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.

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

🧹 Nitpick comments (2)
hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py (1)

157-157: Remove whitespace from blank lines.

Static analysis detected whitespace on blank lines that should be removed.

-	
+

Also applies to: 183-183

hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.py (1)

94-101: Consider adding end_date validation for shift assignments.

The current query only checks start_date <= date but doesn't validate that the assignment hasn't expired. This could include employees with expired shift assignments.

 shift_assigned_employees = frappe.get_list(
 	'Shift Assignment',
 	filters = {
 		'shift_type': shift,
 		'start_date': ['<=', frappe.utils.getdate(date)],
+		'end_date': ['>=', frappe.utils.getdate(date)],
 	},
 	fields=['employee']
 )

Alternatively, you could use:

+		'end_date': ['is', 'null'],  # For open-ended assignments

Or use an OR condition to handle both cases.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 58469d2 and 286c026.

📒 Files selected for processing (4)
  • hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.js (1 hunks)
  • hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.json (3 hunks)
  • hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.py (3 hunks)
  • hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py (2 hunks)
🧰 Additional context used
🪛 Ruff (0.12.2)
hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py

157-157: Blank line contains whitespace

Remove whitespace from blank line

(W293)


183-183: Blank line contains whitespace

Remove whitespace from blank line

(W293)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (5)
hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.js (1)

50-51: LGTM! Clean integration of shift filtering parameters.

The addition of shift and filter_by_shift parameters to the server call is correctly implemented and integrates well with the existing load_employees function.

hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.json (2)

106-106: Good UX improvement with conditional mandatory logic.

Making the shift field mandatory only when filter_by_shift is checked addresses the UX concern from previous reviews about confusing users who don't need shift filtering.


178-183: Well-defined checkbox field for shift filtering.

The filter_by_shift checkbox field is properly configured with appropriate defaults and labeling.

hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.py (2)

26-27: LGTM! Clean function signature extension.

The new parameters are properly typed and integrate well with the existing function signature.


92-120: LGTM! Solid filtering logic implementation.

The function correctly handles both shift assignments and default shifts, combines them efficiently using a set for deduplication, and filters the unmarked attendance appropriately.

@anwarpatelnoori
Copy link
Contributor Author

anwarpatelnoori commented Aug 7, 2025

hey @anwarpatelnoori could you fix the linter errors. here's a guideline for semantic commit messages https://gist.github.com/joshbuchea/6f47e86d2510bce28f8e7f42ae84c716

@asmitahase, As there were lot of git conflicts , I have discarded all the commits and re opened PR and the updated the commit message according to semantic system .
Please review

@anwarpatelnoori
Copy link
Contributor Author

@asmitahase

@asmitahase
Copy link
Collaborator

asmitahase commented Aug 11, 2025

hey @anwarpatelnoori,
The linter check is still failing, please setup pre-commit locally, and then run pre-commit run on staged changes before commiting. You'll find the process in the PR guidelines.
Also you'll need to rebase the branch because I am not able to pull your PR on my local

@asmitahase
Copy link
Collaborator

@Mergifyio rebase

Copy link
Contributor

mergify bot commented Aug 11, 2025

rebase

✅ Branch has been successfully rebased

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 (3)
hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py (3)

158-164: Fix the invalid end_time value.

The shift type creation still has an invalid end_time value of "end_time" which should be a proper time string format.

-		"end_time":"end_time",
+		"end_time": "17:00:00",

181-181: Fix the default_shift assignment syntax.

The default_shift field assignment is missing the proper reference to the shift name. It should reference self.shift.name instead of the shift object directly.

-		"default_shift": self.shift,
+		"default_shift": self.shift.name,

211-211: Fix the shift name mismatch.

The shift variable is set to "Morning Shift" but the actual shift created is named "Shift 1". This will cause the test to fail as the filtering function won't find any employees with the "Morning Shift" name.

-	shift = "Morning Shift"
+	shift = self.shift.name
🧹 Nitpick comments (2)
hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py (2)

165-194: Consider using more descriptive employee names.

While the current implementation works, the employee names could be more descriptive to better reflect their role in the test scenario.

-		"first_name": "Morning Shift Assigned",
+		"first_name": "Shift Assignment Employee",
-		"first_name": "Test Default Shift",
+		"first_name": "Default Shift Employee", 
-		"first_name": "Test Not Assigned",
+		"first_name": "No Shift Employee",

196-203: Improve shift assignment reference consistency.

The shift assignment should use self.shift.name for consistency with other shift references in the codebase.

-		"shift_type": self.shift,
+		"shift_type": self.shift.name,
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ee18a3c and 3816638.

📒 Files selected for processing (4)
  • hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.js (1 hunks)
  • hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.json (3 hunks)
  • hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.py (3 hunks)
  • hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.js
  • hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.json
  • hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.py
🧰 Additional context used
🧬 Code Graph Analysis (1)
hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py (1)
hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.py (1)
  • _get_unmarked_attendance_with_shift (92-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (2)
hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py (2)

14-14: LGTM! Import addition is correct.

The import of _get_unmarked_attendance_with_shift is properly added to enable testing of the new shift-based filtering functionality.


214-220: Test logic and assertions are well-structured.

The test correctly validates that only employees with the specified shift (either through shift assignment or default shift) are returned by the filtering function. The assertions properly check for inclusion and exclusion of the expected employees.

@anwarpatelnoori
Copy link
Contributor Author

Thanks for response @asmitahase . I have fixed the linter errors in local and pushed the changes
image

@asmitahase
Copy link
Collaborator

Shift 1 is used in other tests too. Just reuse the same shift name instead of creating new one.
https://github.com/frappe/hrms/actions/runs/16878928798/job/47810659468?pr=3363

@anwarpatelnoori
Copy link
Contributor Author

@asmitahase updated

@asmitahase asmitahase merged commit f4b8f7d into frappe:develop Aug 11, 2025
8 checks passed
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.

Employee Attendance Tool Doctype needs shift wise filter for fetching unmarked Employees

2 participants