#127: IHKPage.java
plugins/org.projectforge.plugins.ihk/src/main/java/org/projectforge/plugins/ihk/IHKPage.java Apache Wicket page — UI for generating IHK weekly training reports from timesheet data. Source: plugins/org.projectforge.plugins.ihk/src/main/java/org/projectforge/plugins/ihk/IHKPage.java 171 lines · 119 code · 29 comments · 23 blank
The main page of the IHK plugin — allows trainees (Auszubildende) to select a week, view their timesheet entries, and export them as an IHK-compliant Excel weekly report. Part of the dual vocational training (Duale Ausbildung) workflow mandated by German law.
Architecture
Extends AbstractStandardFormPage (ProjectForge's Wicket base page) and implements ISelectCallerPage (for quick-select calendar widget). The page contains an IHKForm component in its body.
Lifecycle:
1. Constructor: creates IHKForm, initializes it, adds a LogViewer link to content menu
2. select(): handles quick-select calendar clicks — sets the date range to the clicked date's week (Monday–Sunday)
3. export(): queries timesheets for the selected week, validates descriptions exist, delegates to IHKExporter to generate the Excel file, triggers download
4. edit(): navigates to TimesheetEditPage for fixing missing descriptions
Key Methods
| Method | Lines | Purpose |
|---|
findTimesheets() | ~20 | Builds a TimesheetFilter for the selected week (Monday 00:00 to Sunday 23:59:59.999), queries TimesheetDao |
export(boolean) | ~35 | Validates timesheet descriptions, delegates to IHKExporter, triggers file download via DownloadUtils |
select(String, Object) | ~10 | Calendar quick-select handler — sets week range from clicked date |
Validation Flow
The export() method has two validation gates:
1. No timesheets found: If findTimesheets() returns empty, shows error "plugins.ihk.noitemsfound"
2. Missing descriptions: IHK requires every timesheet entry to have a description. If any entry has description == null, shows error "plugins.ihk.nodescriptionfound" and displays the list of offending entries. User can then call export(true) to bypass (at their own risk).
This two-stage validation is a UX pattern: first fail-fast with a polite error, then show exactly which entries need fixing, and provide an escape hatch for cases where the description truly isn't needed.
Git History
868d6abb7 2025 → 2026
63081666f 2024→2025
1b50060c3 BaseDao: get→find, save→insert, getList→select, load→select
b6092df09 2023→2024
e7e0786b4 IHK-Plugin: added comments, error outputs, fixed xlsx writing
b9c16aafa PROJECTFORGE-3720 IHK-Plugin: Download-Error fix, static functions fix
5d41efc41 LogViewer in IHK-Plugin
65b67f1b9 using getLocalDate
f8ea4cacc final fixing DocNr, updated creator/updater
dfa308efd Changed variable names
31126b8f9 Changed variable names, added error messages
9a186ba10 ihk plugin removed unused imports
6d44a7fd9 changing Filename and merged
83ced0b86 Ihk less manuality (#141)
723b47df2 MMAUSIHK-12 MMAUSIHK-6: timesheet creation with Merlin
9522de0eb Added list for timesheets with missing description
a253f3092 IHK exports fixed
b209e00ba PFDay.from → from, PFDateTime.from → from
45cad02e9 IHK-Plugin added (initial)
4cd7c8e69 Replace DateHolder/DayHolder with PFDateTime
9ebb88522 Initial commit
Key Commits
45cad02e9 — Plugin creation: The IHK plugin was added as a replacement for the older "Ihk-Export" plugin. It generates Excel reports directly from ProjectForge timesheets for German vocational training compliance.
9522de0eb — Missing description list: Added the validation step that checks for empty timesheet descriptions and shows them to the user. Before this, missing descriptions would silently produce an incomplete report.
5d41efc41 — LogViewer integration: Each plugin gets a dedicated log subscription via IHKPlugin.ensureUserLogSubscription(). The LogViewer link in the content menu lets users inspect plugin-specific log output without leaving the IHK page.
83ced0b86 — Less manuality (#141): Streamlined the UX to reduce manual steps in the report generation workflow.
Gotcha — Timezone handling: The week range calculation uses ThreadLocalUserContext.getTimeZone() to ensure Monday–Sunday boundaries are computed in the user's timezone. Using server timezone would cause off-by-one-day errors for users in different timezones. Commit bf872fc9a (PROJECTFORGE-2524) specifically fixed a timezone bug in the IHK export.
Why Wicket and not React? The IHK plugin is one of the older plugins that still uses Apache Wicket for its UI. Newer plugins use the REST+React stack. The IHKPage remains on Wicket because: (a) it's a single-page form with no complex interactivity, (b) the plugin is low-traffic (only used by trainees, not all employees), and (c) migration effort vs. benefit didn't justify rewriting it.