Library for processing attendance plan data into time-segmented DataFrames
Project description
Shift Counter
A Python library for processing attendance plan data into time-segmented DataFrames. This library takes JSON attendance data and converts it into a structured pandas DataFrame with 30-minute time segments, making it easy to analyze working hours by different shift types.
Installation
pip install shift-counter
Features
- Processes attendance data into 30-minute segments
- Classifies shifts into different types (Normal, VD, Red, Vacation)
- Handles timezone-aware timestamps
- Aggregates overlapping shifts
- Compatible with Tria HR API output format
Usage
Basic Usage
from shift_counter import ShiftCounter, ShiftType
# Initialize counter
counter = ShiftCounter()
# Add individual shifts
counter.add_shift(
from_time="2025-01-08T08:00:00+01:00",
to_time="2025-01-08T16:00:00+01:00",
unit_id=120,
shift_type=ShiftType.NORMAL
)
# Get resulting DataFrame
df = counter.get_dataframe()
Processing Attendance Plan
# Process complete attendance plan (e.g., from Tria HR API)
attendance_plan = {
"data": [{
"shifts": [{
"date_time_from": "2025-01-08T08:00:00+01:00",
"date_time_to": "2025-01-08T16:00:00+01:00",
"name": "VD"
}],
"absences": [{
"date_time_from": "2025-01-09T08:00:00+01:00",
"date_time_to": "2025-01-09T16:00:00+01:00"
}]
}]
}
counter = ShiftCounter()
counter.count_attendance_plan(attendance_plan)
Output Format
The resulting DataFrame contains the following columns:
department_id: Integer identifier for the organizational unitdetail_level: Granularity of the data (always 'hour')time_segment: Start time of the 30-minute segmentextraction_date: When the data was processedhours_normal: Regular shift hourshours_vd: Variable day shift hourshours_red: Red shift hourshours_vacation: Vacation/leave hours
Each row represents a 30-minute segment, with hours columns showing 0.5 for each shift type present in that segment.
Integration with Tria HR API
While this library can be used independently, it's designed to work seamlessly with data from the Tria HR API:
from triahr import TriaHRAPI
from shift_counter import ShiftCounter
# Get attendance data
api = TriaHRAPI.from_config()
attendance = api.attendance_plan(
date_from="2025-01-01",
date_to="2025-01-31",
unit_id=120
)
# Process into DataFrame
counter = ShiftCounter()
counter.count_attendance_plan(attendance)
df = counter.get_dataframe()
Unit Organization
The library includes a UnitOrganiser class for managing and mapping organizational units:
from shift_counter import UnitOrganiser, UnitFilter
import pandas as pd
# Create DataFrame with store mappings from sales database
stores_df = pd.DataFrame({
'tria_id': [1],
'but_num_business_unit': [2097]
})
# Initialize organiser with store mappings
organiser = UnitOrganiser(stores_list=stores_df)
# Get organization units from API
api = TriaHRAPI.from_config()
org_units = api.organization_units(company_id=1)
# Create filter to get active departments from specific stores
unit_filter = UnitFilter()\
.constraint(name="parent_unit_id", keep=True, value=[1, 2])\
.constraint(name="departments", keep=True)\
.constraint(name="deactivated", keep=False, value=[True])
# Apply filter
filtered_units = organiser.filter_organization_units(
organization_units=org_units,
unit_filter=unit_filter
)
# Add units to organiser and map them to sales database stores
organiser.add_department(filtered_units)
# Get resulting DataFrame with mapped units
mapped_units = organiser.get_dataframe()
Filter Examples
The UnitFilter class allows for flexible unit filtering using method chaining:
# Get only active stores
filter_active_stores = UnitFilter()\
.constraint(name="stores", keep=True)\
.constraint(name="deactivated", keep=False, value=[True])
# Get departments from specific stores
filter_specific_deps = UnitFilter()\
.constraint(name="parent_unit_id", keep=True, value=[1, 2])\
.constraint(name="departments", keep=True)
# Get both stores and departments, excluding deactivated
filter_all_active = UnitFilter()\
.constraint(name="stores", keep=True)\
.constraint(name="departments", keep=True)\
.constraint(name="deactivated", keep=False, value=[True])
# Get specific units by ID
filter_specific_units = UnitFilter()\
.constraint(name="id", keep=True, value=[1, 2, 3])
Available filter constraints:
stores: Match store units (no parent_unit_id or parent_unit_id=0)departments: Match department units (has parent_unit_id)id: Match specific unit IDsparent_unit_id: Match units with specific parent unit IDsdeactivated: Match units based on their deactivation status
The resulting DataFrame contains:
department_id: Unit ID from Tria HRdepartment_name: Full name of the unitextraction_date: When the data was processedstore_department_id: Parent unit ID (null for stores)store_id: Mapped store ID from sales databasedeactivated: Whether the unit is deactivated
Error Handling
The library automatically handles:
- Timezone conversions
- Overlapping shifts
- Missing or invalid shift types
- Data type consistency
- Store-department mappings
Requirements
- Python ≥ 3.7
- pandas ≥ 1.0.0
License
MIT License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file shift_counter-1.1.4.tar.gz.
File metadata
- Download URL: shift_counter-1.1.4.tar.gz
- Upload date:
- Size: 9.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52c0a292087888340e9ee2d7c04dbd802883cb0b730fa9a06e32b162fff3edb4
|
|
| MD5 |
45d2647500f7043c08a82040def0ae20
|
|
| BLAKE2b-256 |
fcec8d9e7d7d9d7ef8d2790a3413531e8255401242e8c01398e81bdbbf6e5112
|
File details
Details for the file shift_counter-1.1.4-py3-none-any.whl.
File metadata
- Download URL: shift_counter-1.1.4-py3-none-any.whl
- Upload date:
- Size: 9.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8a07b072f4a7de70f186b7a8288c5a944173aa6a65b0994dc891807d916be95
|
|
| MD5 |
e901ecbcd8bd88204823665880a29829
|
|
| BLAKE2b-256 |
b66f53f1c2b7bd8741fedca557c8bbb5583303853970046f12f2074488fd0c12
|