feat: add work assignment doctype with member hour tracking (LAN-885)#294
feat: add work assignment doctype with member hour tracking (LAN-885)#294MarcCon wants to merge 48 commits into
Conversation
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Good start!
I think in the requirements I read that each Organization should be able to specify a number of working hours per year and we need to track the members´ actual working hours against that. And, ideally, also allow carrying over excess working hours to the next year.
Let's also add the Work Assignment to the connections in the LANDA Member form.
My idea would be to add a DocType "Organization Work Hours" with a child table to show members of the organization with their hours from the Work Assignment DocType and validate them against the target hours. |
|
See my alternative proposal in LAN-885 |
|
@MarcCon exactly, die Rechte haben gefehlt, sodass niemand buchen kann. Das müsste noch gefixt werden. |
|
Ah habs falsch verstanden, alles klar. |
|
Die offenen Issues sind erledigt, ich teste es noch als normaler Nutzer durch. Edit: In beiden Reports kann ich in den Filtern auch nur den eigenen Verein auswählen und ansehen. |
|
@greptile |
|
@greptile |
| def create_yearly_negative_entries(): | ||
| """Create negative Work Ledger Entries for all members based on expected work hours per year.""" | ||
|
|
||
| organizations = frappe.get_list( | ||
| "Organization", | ||
| filters={"expected_work_hours_per_year": [">", 0]}, | ||
| fields=["name", "expected_work_hours_per_year"], | ||
| ) | ||
|
|
||
| if not organizations: | ||
| return | ||
|
|
||
| # Get all active members for each organization | ||
| for org in organizations: | ||
| members = frappe.get_list( | ||
| "LANDA Member", | ||
| filters={"organization": org.name}, | ||
| fields=["name"], | ||
| ) | ||
|
|
||
| for member in members: | ||
| ledger_entry = frappe.new_doc("Work Ledger Entry") | ||
| ledger_entry.member = member.name | ||
| ledger_entry.organization = org.name | ||
| ledger_entry.date = f"{now_datetime().year}-01-01" | ||
| ledger_entry.hours_change = -org.expected_work_hours_per_year | ||
| ledger_entry.insert() |
There was a problem hiding this comment.
No idempotency guard in
create_yearly_negative_entries
If this function runs more than once for the same year — scheduler restart, a manual frappe bench execute call during maintenance, or a test run — every member in every qualifying organisation gets duplicate negative entries. Because there is no check for an existing entry dated {year}-01-01 without a work_assignment, the second run silently doubles every member's annual obligation. The corruption is permanent and would require manual clean-up per member.
A safe guard would be to skip creating entries for any member that already has a no-work_assignment entry on {year}-01-01 for the current run year.
This PR enables tracking of work hours for members through work assignments.
Features:
Open Questions:
Do we need a hourly account for a member? It is not necessary for the report.