Holiday struct gains Country (ISO-3166) + Regime ('UPC' | 'EPO' | "")
fields. AppliesTo(country, regime) is the matching rule the new lookup
methods filter through: a row matches when its Country equals the
court's country OR its Regime equals the court's regime. UPC LD München
(DE+UPC) sees DE federal + UPC vacations; LG München (DE+"") sees only
DE federal; UPC LD Paris (FR+UPC) sees FR + UPC. germanFederalHolidays
fallback now country-tagged 'DE' so the per-country filter applies it
only to DE-jurisdictional callers.
Public service methods (IsHoliday, IsNonWorkingDay, AdjustForNonWorking
Days, AdjustForNonWorkingDaysWithReason, findVacationBlock) all take
(country, regime). Cache stays year-keyed — single DB hit per year, all
courts touching that year share it.
New CourtService loads paliad.courts once + answers Lookup(id),
CountryRegime(id, defaultCountry, defaultRegime), All(), ByCourtType(t).
FristenrechnerService.CalcOptions / CalcRuleParams gain CourtID;
EventDeadlineService.Calculate gains courtID. When courtID is empty,
DefaultsForJurisdiction maps the proceeding's existing jurisdiction
column to a sensible (country, regime) default — UPC proceedings get
(DE, UPC), everything else gets DE-only — preserving today's behaviour
for callers that don't yet send a court.
Tests: new TestAppliesTo_CountryRegimeFilter + TestAppliesTo_Rules
cover the cross-product of (DE court / UPC LD München / UPC LD Paris /
LG München) × (DE federal / UPC vacation / FR holiday). Existing tests
threaded through with ('DE', 'UPC') to preserve behaviour they were
written to lock.
90 lines
2.7 KiB
Go
90 lines
2.7 KiB
Go
package services
|
|
|
|
import (
|
|
"time"
|
|
|
|
"mgit.msbls.de/m/paliad/internal/models"
|
|
)
|
|
|
|
// CalculatedDeadline is one computed deadline (rule + due date + adjustment info).
|
|
type CalculatedDeadline struct {
|
|
RuleCode string `json:"rule_code"`
|
|
RuleID string `json:"rule_id"`
|
|
Title string `json:"title"`
|
|
DueDate string `json:"due_date"` // YYYY-MM-DD, after holiday/weekend adjust
|
|
OriginalDueDate string `json:"original_due_date"` // YYYY-MM-DD, before adjust
|
|
WasAdjusted bool `json:"was_adjusted"`
|
|
}
|
|
|
|
// DeadlineCalculator turns rules into dates given a trigger event.
|
|
type DeadlineCalculator struct {
|
|
holidays *HolidayService
|
|
}
|
|
|
|
// NewDeadlineCalculator wires the calculator to the holiday service.
|
|
func NewDeadlineCalculator(holidays *HolidayService) *DeadlineCalculator {
|
|
return &DeadlineCalculator{holidays: holidays}
|
|
}
|
|
|
|
// CalculateEndDate applies a single rule's duration + timing to the event date,
|
|
// then bumps forward off non-working days for the given (country, regime).
|
|
// Returns (adjusted, original, didAdjust).
|
|
func (c *DeadlineCalculator) CalculateEndDate(eventDate time.Time, rule models.DeadlineRule, country, regime string) (time.Time, time.Time, bool) {
|
|
endDate := eventDate
|
|
|
|
timing := "after"
|
|
if rule.Timing != nil {
|
|
timing = *rule.Timing
|
|
}
|
|
|
|
sign := 1
|
|
if timing == "before" {
|
|
sign = -1
|
|
}
|
|
|
|
switch rule.DurationUnit {
|
|
case "days":
|
|
endDate = endDate.AddDate(0, 0, sign*rule.DurationValue)
|
|
case "weeks":
|
|
endDate = endDate.AddDate(0, 0, sign*rule.DurationValue*7)
|
|
case "months":
|
|
endDate = endDate.AddDate(0, sign*rule.DurationValue, 0)
|
|
}
|
|
|
|
original := endDate
|
|
adjusted, _, wasAdjusted := c.holidays.AdjustForNonWorkingDays(endDate, country, regime)
|
|
return adjusted, original, wasAdjusted
|
|
}
|
|
|
|
// CalculateFromRules calculates deadlines for a slice of rules using the
|
|
// given (country, regime) for non-working-day adjustment. Rules with
|
|
// duration == 0 (court-set hearings, decisions) return the event date itself.
|
|
func (c *DeadlineCalculator) CalculateFromRules(eventDate time.Time, rules []models.DeadlineRule, country, regime string) []CalculatedDeadline {
|
|
results := make([]CalculatedDeadline, 0, len(rules))
|
|
for _, r := range rules {
|
|
var adjusted, original time.Time
|
|
var wasAdjusted bool
|
|
|
|
if r.DurationValue > 0 {
|
|
adjusted, original, wasAdjusted = c.CalculateEndDate(eventDate, r, country, regime)
|
|
} else {
|
|
adjusted, original = eventDate, eventDate
|
|
}
|
|
|
|
code := ""
|
|
if r.Code != nil {
|
|
code = *r.Code
|
|
}
|
|
|
|
results = append(results, CalculatedDeadline{
|
|
RuleCode: code,
|
|
RuleID: r.ID.String(),
|
|
Title: r.Name,
|
|
DueDate: adjusted.Format("2006-01-02"),
|
|
OriginalDueDate: original.Format("2006-01-02"),
|
|
WasAdjusted: wasAdjusted,
|
|
})
|
|
}
|
|
return results
|
|
}
|