libestg3b.rule

class libestg3b.rule.Rule(slug, description, impl, *, multiply=None, add=None, tests=[])[source]

Bases: object

Defines a situation in which an employee might receive extra pay, e.g. “on 24th of december, pay 50% more”.

Parameters:
  • slug (str) – a machine and human-ish readable name for this rule (see below).
  • description (str) – a human readable short-form description
  • impl (Callable[…, bool]) – actual matching function, accepting one, two or three parameters.
  • multiply (Optional[Decimal]) – heigth of the bonus, as a factor. Supplying 0.25 results in a pay increase of 25%.
  • add (Optional[Decimal]) – heigth of the bonus, as an absolute currency value. Either multiply or add must be given, but not both.

The actual logic of a rule is passed in via the impl parameter. This function must accept 1-3 arguments: minute, start and holidays. Refer to match() for the meaning of those parameters.

match(minute, start, holidays)[source]

For matching, a shift must be split into its individual minutes. Each of these minutes is then passed into this method. Additionally the very first minute is provided, to enable rules like (worked after midnight, but started before).

>>> from decimal import Decimal
>>> import datetime as DT
>>> from libestg3b.rule import Rule
>>> m = Rule("NIGHT", "Nachtarbeit", lambda m, f: m.hour >= 20, multiply=Decimal(2))
# Shift started at 2018-02-02 21:00 and this is the first minute: match!
>>> m.match(DT.datetime(2018, 2, 2, 21), DT.datetime(2018, 2, 2, 21), None)
True
# Shift started at 2018-02-02 20:00 and 21:00 is checked: match!
>>> m.match(DT.datetime(2018, 2, 2, 21), DT.datetime(2018, 2, 2, 20), None)
True
# Shift started at 2018-02-02 18:00 and 19:00 is checked: no match
>>> m.match(DT.datetime(2018, 2, 2, 19), DT.datetime(2018, 2, 2, 18), None)
False
# Shift started at 2018-02-02 23:00 and 01:00 on the following day is checked
# even though the start of this shift is within the timeframe "after 21:00",
# the checked minute is not, so we don't match.
>>> m.match(DT.datetime(2018, 2, 3, 1), DT.datetime(2018, 2, 2, 23), None)
False
Parameters:
  • minute (datetime) – current minute to be matched
  • start (datetime) – very fist minute in this shift
  • holidays (HolidayBase) – holidays in the currently active country (see python-holidays)
Return type:

bool

class libestg3b.rule.DayRule(slug, month, day, **kwargs)[source]

Bases: libestg3b.rule.Rule

Match, if the given minute is within the given day. This can be useful to increase pay on days, which are not official holidays, but still get a special treatment in the law (for example: 31th of December in Germany).

>>> from decimal import Decimal
>>> import datetime as DT
>>> from libestg3b.rule import DayRule
>>> m = DayRule("Helloween", 10, 31, multiply=Decimal("2"))
>>> m
<Rule: Helloween YYYY-10-31>
>>> m.match(DT.datetime(2018, 10, 31, 13), DT.datetime(2018, 10, 31, 12), None)
True
>>> m.match(DT.datetime(2018, 10, 30, 13), DT.datetime(2018, 10, 30, 12), None)
False
Parameters:
  • slug (str) – machine-readable name of this rule, see Rule
  • month (int) – only match, if shift is within this month, counted from 1 = January
  • day (int) – only match, if shift is on this day, counted from 1

Additionally all keyword arguments defined for Rule can be used.

class libestg3b.rule.DayTimeRule(slug, month, day, hour, **kwargs)[source]

Bases: libestg3b.rule.Rule

Like DayRule, but additionally require the shift to be after a certain time.

>>> from decimal import Decimal
>>> import datetime as DT
>>> from libestg3b.rule import DayTimeRule
>>> m = DayTimeRule("NEWYEARSEVE", 12, 31, 14, multiply=Decimal("1"))
>>> m
<Rule: NEWYEARSEVE YYYY-12-31 14:00+>
>>> m.match(DT.datetime(2018, 12, 31, 13), DT.datetime(2018,12, 31, 13), None)
False
>>> m.match(DT.datetime(2018, 12, 31, 14), DT.datetime(2018,12, 31, 14), None)
True
Parameters:
  • slug (str) – machine-readable name of this rule, see Rule
  • month (int) – only match, if shift is within this month, counted from 1 = January
  • day (int) – only match, if shift is on this day, counted from 1
  • hour (int) – only match, if shift is after or in this hour. Supplying 14 results in 14:00 to 24:00 to be matched.

Additionally all keyword arguments defined for Rule can be used.

class libestg3b.rule.RuleGroup(slug, description, rules)[source]

Bases: object

A collection of similar Rule instances. When the group is evaluated, only the highest matching machter is returned.

Parameters:
  • slug (str) – a machine and human-ish readable name for this rule, must not change.
  • description (str) – a short, human-readable text, explaining why the given rules are grouped together.
  • rules (Iterable[Rule]) – the initial set of rules.
append(rule, replace=False)[source]
Parameters:
  • rule (Rule) – rule to add; it must not yet exist in the group.
  • replace (bool) – if rule duplicates an existing one, overwrite it.
Return type:

None

match(minute, start, holidays)[source]

Evaluate this group. The given shift is tested using each of the stored rules. The rule with the highest bonus is the returned. If not a single one matches, None is returned.

This method is normally used by libestg3b.EStG3b, but you can use it to implement more complex scenarios yourself.

Parameters:
  • minute (datetime) – minute to evaluate (see libestgb3.EStG3b)
  • start (datetime) – the first minute in this shift (see libestgb3.EStG3b)
Return type:

Optional[Rule]

extend(rules, replace=False)[source]

Add the given rules to this group.

Parameters:
  • rules (Iterable[Rule]) –
  • replace (bool) – if one of the given rule duplicates an existing one, overwrite it instead of raising an exception.
Return type:

None