feat: deduct vendor-country bank holidays from billable days#47
Closed
Sajjon wants to merge 1 commit into
Closed
Conversation
Add an opt-in `off_on_bank_holidays` flag to invoice ServiceFees. When set, public holidays in the vendor's country are deducted from billable working days for day- and hour-granularity rates (monthly/fortnightly fixed rates are unaffected). Holidays are fetched from the free Nager.Date API and cached to disk (~/.klirr/cached_holidays.ron), mirroring the existing exchange-rate fetch+cache pattern, so repeat runs work offline. The vendor's free-text country is mapped to an ISO 3166-1 alpha-2 code via a name->code table (Sweden/Sverige->SE, England/UK->GB, USA->US, ...). Resolution degrades gracefully: an unmappable country or a failed lookup logs a warning and skips the deduction rather than failing PDF generation. The flag defaults to false and deserializes from legacy RON (serde default), preserving prior behavior. - foundation: CountryCode + resolver, BankHolidays newtype, BankHolidaysFetcher (new `bank-holidays` feature), holiday-aware working-day counting. - core-invoice: ServiceFees flag, resolve_bank_holidays wired into prepare. - cli: yes/no prompt in the service-fees wizard. Note: the render-typst fixture image tests are environment-sensitive (imagemagick) and fail identically on a clean main on this machine; they are unaffected by this change (samples use the default flag=false). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #47 +/- ##
==========================================
- Coverage 97.07% 95.96% -1.11%
==========================================
Files 104 108 +4
Lines 2287 2452 +165
==========================================
+ Hits 2220 2353 +133
- Misses 67 99 +32 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an opt-in
off_on_bank_holidaysflag to invoiceServiceFees. When enabled, public holidays in the vendor's country are deducted from billable working days for day- and **hour-**granularity rates (monthly/fortnightly fixed rates are unaffected — a fixed monthly fee doesn't shrink for a holiday).Closes the feature request to be "off on bank holidays".
Feasibility outcome
AvailableCountriesendpoint). Sweden is fully covered by the global API; the Swedish-specificdryg.netis not needed.py-holidays-rscrate (beta, 1★ — supply-chain risk).Design (mirrors existing patterns)
~/.klirr/cached_holidays.ron, keyedISO country → year; repeat runs work offline.countrystring is resolved via a curated alias table (Sweden/Sverige→SE,England/UK→GB,USA→US, ~45 countries).falseand deserializes from legacy RON via#[serde(default)].Changes by crate
CountryCodenewtype + resolver;BankHolidaysnewtype;BankHolidaysFetcherbehind a newbank-holidaysfeature;working_days_between/quantity_in_periodnow skip holiday dates (holidays on weekends are no-ops).ServiceFees.off_on_bank_holidays;resolve_bank_holidayswired intoprepare_invoice_input_data.Tests
None).working_days_betweendeducting a known holiday; holiday-on-weekend no-op; hours = days×8 deduction.ServiceFeeslegacy-RON deserialization (no field →false).All unit + doc tests pass; clippy clean for new code.
🤖 Generated with Claude Code