altadesk-task-analytics 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- altadesk_task_analytics-1.0.0/PKG-INFO +17 -0
- altadesk_task_analytics-1.0.0/README.md +14 -0
- altadesk_task_analytics-1.0.0/altadesk_task_analytics/__init__.py +4 -0
- altadesk_task_analytics-1.0.0/altadesk_task_analytics/task_analytics.py +134 -0
- altadesk_task_analytics-1.0.0/altadesk_task_analytics.egg-info/PKG-INFO +17 -0
- altadesk_task_analytics-1.0.0/altadesk_task_analytics.egg-info/SOURCES.txt +8 -0
- altadesk_task_analytics-1.0.0/altadesk_task_analytics.egg-info/dependency_links.txt +1 -0
- altadesk_task_analytics-1.0.0/altadesk_task_analytics.egg-info/top_level.txt +1 -0
- altadesk_task_analytics-1.0.0/setup.cfg +4 -0
- altadesk_task_analytics-1.0.0/setup.py +16 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: altadesk-task-analytics
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A task analytics library for AltaDesk cloud task management system
|
|
5
|
+
Author: X23219505
|
|
6
|
+
Author-email: x23219505@student.ncirl.ie
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Dynamic: author
|
|
11
|
+
Dynamic: author-email
|
|
12
|
+
Dynamic: classifier
|
|
13
|
+
Dynamic: description
|
|
14
|
+
Dynamic: requires-python
|
|
15
|
+
Dynamic: summary
|
|
16
|
+
|
|
17
|
+
A custom Python library that provides task prioritisation, deadline tracking and analytics calculations for the AltaDesk cloud-based task management system.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# AltaDesk Task Analytics
|
|
2
|
+
|
|
3
|
+
A custom Python library for task prioritisation, deadline tracking and analytics.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
pip install altadesk-task-analytics
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
from altadesk_task_analytics import TaskAnalytics
|
|
12
|
+
|
|
13
|
+
analytics = TaskAnalytics(tasks)
|
|
14
|
+
report = analytics.generate_report()
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
from datetime import datetime, timezone, date
|
|
2
|
+
from typing import List, Dict, Any, Optional
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
# Priority weights used for score calculation
|
|
8
|
+
PRIORITY_WEIGHT = {"high": 3, "medium": 2, "low": 1}
|
|
9
|
+
URGENCY_THRESHOLD_DAYS = 3
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TaskAnalytics:
|
|
13
|
+
|
|
14
|
+
def __init__(self, tasks: List[Dict[str, Any]]):
|
|
15
|
+
if not isinstance(tasks, list):
|
|
16
|
+
raise TypeError("tasks must be a list of dicts")
|
|
17
|
+
self._tasks = tasks
|
|
18
|
+
self._today = date.today()
|
|
19
|
+
|
|
20
|
+
def get_priority_score(self, task_id: str) -> Optional[float]:
|
|
21
|
+
# Combines priority weight with urgency multiplier
|
|
22
|
+
task = self._find_task(task_id)
|
|
23
|
+
if task is None:
|
|
24
|
+
return None
|
|
25
|
+
base = PRIORITY_WEIGHT.get(task.get("priority", "low"), 1)
|
|
26
|
+
urgency = self._urgency_multiplier(task.get("deadline", ""))
|
|
27
|
+
return round(base * urgency, 2)
|
|
28
|
+
|
|
29
|
+
def get_sorted_tasks(self) -> List[Dict[str, Any]]:
|
|
30
|
+
# Returns tasks sorted by highest priority score first
|
|
31
|
+
def sort_key(task):
|
|
32
|
+
base = PRIORITY_WEIGHT.get(task.get("priority", "low"), 1)
|
|
33
|
+
urgency = self._urgency_multiplier(task.get("deadline", ""))
|
|
34
|
+
return base * urgency
|
|
35
|
+
return sorted(self._tasks, key=sort_key, reverse=True)
|
|
36
|
+
|
|
37
|
+
def get_overdue_tasks(self) -> List[Dict[str, Any]]:
|
|
38
|
+
# Returns tasks past their deadline that are not done
|
|
39
|
+
overdue = []
|
|
40
|
+
for task in self._tasks:
|
|
41
|
+
if task.get("status") == "done":
|
|
42
|
+
continue
|
|
43
|
+
days = self._days_remaining(task.get("deadline", ""))
|
|
44
|
+
if days is not None and days < 0:
|
|
45
|
+
overdue.append(task)
|
|
46
|
+
return overdue
|
|
47
|
+
|
|
48
|
+
def get_upcoming_tasks(self, within_days: int = 7) -> List[Dict[str, Any]]:
|
|
49
|
+
# Returns tasks due within the specified number of days
|
|
50
|
+
upcoming = []
|
|
51
|
+
for task in self._tasks:
|
|
52
|
+
if task.get("status") == "done":
|
|
53
|
+
continue
|
|
54
|
+
days = self._days_remaining(task.get("deadline", ""))
|
|
55
|
+
if days is not None and 0 <= days <= within_days:
|
|
56
|
+
upcoming.append({**task, "_days_remaining": days})
|
|
57
|
+
upcoming.sort(key=lambda t: t["_days_remaining"])
|
|
58
|
+
return upcoming
|
|
59
|
+
|
|
60
|
+
def generate_report(self) -> Dict[str, Any]:
|
|
61
|
+
# Generates a full analytics summary for the dashboard
|
|
62
|
+
total = len(self._tasks)
|
|
63
|
+
|
|
64
|
+
by_status = {"todo": 0, "in_progress": 0, "done": 0}
|
|
65
|
+
for task in self._tasks:
|
|
66
|
+
status = task.get("status", "todo")
|
|
67
|
+
by_status[status] = by_status.get(status, 0) + 1
|
|
68
|
+
|
|
69
|
+
by_priority = {"high": 0, "medium": 0, "low": 0}
|
|
70
|
+
for task in self._tasks:
|
|
71
|
+
p = task.get("priority", "low")
|
|
72
|
+
by_priority[p] = by_priority.get(p, 0) + 1
|
|
73
|
+
|
|
74
|
+
overdue = self.get_overdue_tasks()
|
|
75
|
+
done_count = by_status.get("done", 0)
|
|
76
|
+
completion_rate = round((done_count / total * 100), 1) if total else 0.0
|
|
77
|
+
|
|
78
|
+
scores = [self.get_priority_score(t["task_id"]) for t in self._tasks
|
|
79
|
+
if self.get_priority_score(t["task_id"]) is not None]
|
|
80
|
+
avg_score = round(sum(scores) / len(scores), 2) if scores else 0.0
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
"total": total,
|
|
84
|
+
"by_status": by_status,
|
|
85
|
+
"by_priority": by_priority,
|
|
86
|
+
"overdue_count": len(overdue),
|
|
87
|
+
"completion_rate": completion_rate,
|
|
88
|
+
"avg_priority_score": avg_score,
|
|
89
|
+
"upcoming_7days": self.get_upcoming_tasks(within_days=7),
|
|
90
|
+
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@staticmethod
|
|
94
|
+
def is_urgent(task: Dict[str, Any]) -> bool:
|
|
95
|
+
if task.get("status") == "done":
|
|
96
|
+
return False
|
|
97
|
+
days = TaskAnalytics._days_remaining_static(task.get("deadline", ""))
|
|
98
|
+
if days is None:
|
|
99
|
+
return False
|
|
100
|
+
return days <= URGENCY_THRESHOLD_DAYS
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def from_raw_scan(cls, scan_response: Dict) -> "TaskAnalytics":
|
|
104
|
+
items = scan_response.get("Items", [])
|
|
105
|
+
return cls(items)
|
|
106
|
+
|
|
107
|
+
def _find_task(self, task_id: str) -> Optional[Dict[str, Any]]:
|
|
108
|
+
for task in self._tasks:
|
|
109
|
+
if task.get("task_id") == task_id:
|
|
110
|
+
return task
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
def _days_remaining(self, deadline_str: str) -> Optional[int]:
|
|
114
|
+
return TaskAnalytics._days_remaining_static(deadline_str)
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def _days_remaining_static(deadline_str: str) -> Optional[int]:
|
|
118
|
+
if not deadline_str:
|
|
119
|
+
return None
|
|
120
|
+
try:
|
|
121
|
+
deadline_date = date.fromisoformat(deadline_str[:10])
|
|
122
|
+
return (deadline_date - date.today()).days
|
|
123
|
+
except ValueError:
|
|
124
|
+
return None
|
|
125
|
+
|
|
126
|
+
def _urgency_multiplier(self, deadline_str: str) -> float:
|
|
127
|
+
# Multiplier increases as deadline approaches
|
|
128
|
+
days = self._days_remaining(deadline_str)
|
|
129
|
+
if days is None: return 1.0
|
|
130
|
+
if days < 0: return 3.0
|
|
131
|
+
if days <= 3: return 2.5
|
|
132
|
+
if days <= 7: return 2.0
|
|
133
|
+
if days <= 14: return 1.5
|
|
134
|
+
return 1.0
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: altadesk-task-analytics
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A task analytics library for AltaDesk cloud task management system
|
|
5
|
+
Author: X23219505
|
|
6
|
+
Author-email: x23219505@student.ncirl.ie
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Dynamic: author
|
|
11
|
+
Dynamic: author-email
|
|
12
|
+
Dynamic: classifier
|
|
13
|
+
Dynamic: description
|
|
14
|
+
Dynamic: requires-python
|
|
15
|
+
Dynamic: summary
|
|
16
|
+
|
|
17
|
+
A custom Python library that provides task prioritisation, deadline tracking and analytics calculations for the AltaDesk cloud-based task management system.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
altadesk_task_analytics/__init__.py
|
|
4
|
+
altadesk_task_analytics/task_analytics.py
|
|
5
|
+
altadesk_task_analytics.egg-info/PKG-INFO
|
|
6
|
+
altadesk_task_analytics.egg-info/SOURCES.txt
|
|
7
|
+
altadesk_task_analytics.egg-info/dependency_links.txt
|
|
8
|
+
altadesk_task_analytics.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
altadesk_task_analytics
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="altadesk-task-analytics",
|
|
5
|
+
version="1.0.0",
|
|
6
|
+
author="X23219505",
|
|
7
|
+
author_email="x23219505@student.ncirl.ie",
|
|
8
|
+
description="A task analytics library for AltaDesk cloud task management system",
|
|
9
|
+
long_description="A custom Python library that provides task prioritisation, deadline tracking and analytics calculations for the AltaDesk cloud-based task management system.",
|
|
10
|
+
packages=find_packages(),
|
|
11
|
+
python_requires=">=3.8",
|
|
12
|
+
classifiers=[
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Operating System :: OS Independent",
|
|
15
|
+
],
|
|
16
|
+
)
|