Skip to content

Commit

Permalink
add in status and issue staleness to 30-60-90 reports
Browse files Browse the repository at this point in the history
  • Loading branch information
tom0827 committed Jul 16, 2024
1 parent eb7737f commit c5d0558
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 15 deletions.
10 changes: 1 addition & 9 deletions epictrack-api/src/api/reports/anticipated_schedule_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from api.models.work import Work, WorkStateEnum
from api.models.work_phase import WorkPhase
from api.models.work_status import WorkStatus
from api.utils.constants import CANADA_TIMEZONE
from api.utils.constants import CANADA_TIMEZONE, StalenessEnum

from .cdog_client import CDOGClient
from .report_factory import ReportFactory
Expand All @@ -34,14 +34,6 @@
# pylint:disable=not-callable


class StalenessEnum(Enum):
"""Status update staleness level ENUM"""

CRITICAL = "CRITICAL"
WARN = "WARN"
GOOD = "GOOD"


class EAAnticipatedScheduleReport(ReportFactory):
"""EA Anticipated Schedule Report Generator"""

Expand Down
54 changes: 52 additions & 2 deletions epictrack-api/src/api/reports/thirty_sixty_ninety_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
from api.models.special_field import EntityEnum
from api.models.work import WorkStateEnum
from api.models.work_issues import WorkIssues
from api.schemas.response.work_response import WorkIssuesResponseSchema
from api.services.special_field import SpecialFieldService
from api.services.work_issues import WorkIssuesService
from api.schemas import response as res
from api.utils.constants import CANADA_TIMEZONE, StalenessEnum

from .report_factory import ReportFactory

Expand Down Expand Up @@ -53,6 +55,7 @@ def __init__(self, filters, color_intensity):
"event_title",
"event_date",
"project_id",
"date_updated",
]
super().__init__(data_keys, filters=filters, color_intensity=color_intensity)
self.report_date = None
Expand Down Expand Up @@ -82,6 +85,33 @@ def __init__(self, filters, color_intensity):
.all()
)

def _get_latest_status_update_query(self):
"""Create and return the subquery to find latest status update."""
status_update_max_date_query = (
db.session.query(
WorkStatus.work_id,
func.max(WorkStatus.posted_date).label("max_posted_date"),
)
.filter(WorkStatus.is_approved.is_(True))
.group_by(WorkStatus.work_id)
.subquery()
)
return (
WorkStatus.query.filter(
WorkStatus.is_approved.is_(True),
WorkStatus.is_active.is_(True),
WorkStatus.is_deleted.is_(False),
)
.join(
status_update_max_date_query,
and_(
WorkStatus.work_id == status_update_max_date_query.c.work_id,
WorkStatus.posted_date == status_update_max_date_query.c.max_posted_date,
),
)
.subquery()
)

def _fetch_data(self, report_date):
"""Fetches the relevant data for EA 30-60-90 Report"""
max_date = report_date + timedelta(days=90)
Expand All @@ -96,6 +126,7 @@ def _fetch_data(self, report_date):
)
next_pecp_query = self._get_next_pcp_query(report_date, max_date)
valid_event_ids = self._get_valid_event_ids(report_date, max_date)
latest_status_updates = self._get_latest_status_update_query()

results_qry = (
Work.query.filter(
Expand All @@ -118,6 +149,7 @@ def _fetch_data(self, report_date):
EventConfiguration,
EventConfiguration.id == Event.event_configuration_id,
)
.outerjoin(latest_status_updates, latest_status_updates.c.work_id == Work.id)
.outerjoin(
next_pecp_query,
and_(
Expand All @@ -141,10 +173,11 @@ def _fetch_data(self, report_date):
+ func.cast(func.concat(Event.number_of_days, " DAYS"), INTERVAL)
).label("anticipated_decision_date"),
Work.report_description.label("work_short_description"),
WorkStatus.description.label("work_status_text"),
Event.notes.label("decision_information"),
Event.description.label("event_description"),
next_pecp_query.c.topic.label("pecp_explanation"),
latest_status_updates.c.posted_date.label("date_updated"),
latest_status_updates.c.description.label("work_status_text"),
Work.id.label("work_id"),
Event.id.label("event_id"),
Event.name.label("event_title"),
Expand All @@ -156,7 +189,6 @@ def _fetch_data(self, report_date):
)
)

# print(results_qry.statement.compile(compile_kwargs={"literal_binds": True}))
return results_qry.all()

def _format_data(self, data):
Expand Down Expand Up @@ -245,6 +277,7 @@ def generate_report(
self.report_date = report_date.astimezone(utc)
data = self._fetch_data(report_date)
data = self._format_data(data)
data = self._update_staleness(data, report_date)
if return_type == "json" and data:
return {"data": data}, None
if not data:
Expand Down Expand Up @@ -507,3 +540,20 @@ def _get_project_special_history(self, data: List[dict]) -> Dict[int, List]:
entity_ids=project_ids_by_period[period],
)
return periods

def _update_staleness(self, data: dict, report_date: datetime) -> dict:
"""Calculate the staleness based on report date"""
date = report_date.astimezone(CANADA_TIMEZONE)
for _, work_type_data in data.items():
for work in work_type_data:
if work["date_updated"]:
diff = (date - work["date_updated"]).days
if diff > 10:
work["status_staleness"] = StalenessEnum.CRITICAL.value
elif diff > 5:
work["status_staleness"] = StalenessEnum.WARN.value
else:
work["status_staleness"] = StalenessEnum.GOOD.value
else:
work["status_staleness"] = StalenessEnum.CRITICAL.value
return data
8 changes: 8 additions & 0 deletions epictrack-api/src/api/utils/constants.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""File representing constants used in the application"""

from enum import Enum
from pytz import timezone

from api.models.project import Project, ProjectStateEnum
Expand Down Expand Up @@ -40,3 +41,10 @@
}

CANADA_TIMEZONE = timezone("US/Pacific")

class StalenessEnum(Enum):
"""Status update staleness level ENUM"""

CRITICAL = "CRITICAL"
WARN = "WARN"
GOOD = "GOOD"
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export default function ThirtySixtyNinety() {
}
}, [reportDate]);

const isStaleIndicatorRequired = (reportItem: any) => {
const isIssueStaleIndicatorRequired = (reportItem: any) => {
return (reportItem["work_issues"] as []).some(
(workIssue) => stalenessLevel(workIssue) === StalenessEnum.CRITICAL
);
Expand Down Expand Up @@ -162,6 +162,34 @@ export default function ThirtySixtyNinety() {
</div>
);
}

const overallStalenessLevel = (
status_staleness: string,
work_issues: any
) => {
const issuesStaleness = new Set(
work_issues.map((issue: any) => issue.staleness)
);

if (
status_staleness === StalenessEnum.CRITICAL ||
issuesStaleness.has(StalenessEnum.CRITICAL)
) {
return StalenessEnum.CRITICAL;
} else if (
status_staleness === StalenessEnum.WARN ||
issuesStaleness.has(StalenessEnum.WARN)
) {
return StalenessEnum.WARN;
} else if (
status_staleness === StalenessEnum.GOOD ||
issuesStaleness.has(StalenessEnum.GOOD)
) {
return StalenessEnum.GOOD;
}
return StalenessEnum.CRITICAL;
};

return (
<ETPageContainer
direction="row"
Expand Down Expand Up @@ -194,6 +222,32 @@ export default function ThirtySixtyNinety() {
<Accordion key={itemIndex}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography>
<Chip
style={{
marginRight: "0.5rem",
borderRadius: "4px",
fontSize: "12px",
width: "100px",
...staleLevel(
overallStalenessLevel(
item["status_staleness"],
item["work_issues"]
)
),
}}
label={
<>
<b>
{item["date_updated"]
? dateUtils.formatDate(
item["date_updated"],
DISPLAY_DATE_FORMAT
)
: "Needs Status"}
</b>
</>
}
/>
{item["project_name"]} - {item["event_title"]}:
{dateUtils.formatDate(
item["event_date"],
Expand All @@ -209,7 +263,22 @@ export default function ThirtySixtyNinety() {
>
<Tab label="Basic" />
<Tab label="Work Short Description" />
<Tab label="Status" />
<Tab
sx={{
display: "flex",
flexDirection: "row",
gap: "0.5rem",
}}
label={
<>
Status
{item["status_staleness"] ===
StalenessEnum.CRITICAL && (
<IndicatorIcon />
)}
</>
}
/>
<Tab
sx={{
display: "flex",
Expand All @@ -219,7 +288,7 @@ export default function ThirtySixtyNinety() {
label={
<>
Issues
{isStaleIndicatorRequired(item) && (
{isIssueStaleIndicatorRequired(item) && (
<IndicatorIcon />
)}
</>
Expand Down
1 change: 0 additions & 1 deletion epictrack-web/src/utils/uiUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { StalenessEnum } from "constants/application-constant";
import { Palette } from "styles/theme";

const staleLevel = (staleness: string) => {
console.log(staleness);
if (staleness == StalenessEnum.CRITICAL) {
return {
background: Palette.error.main,
Expand Down

0 comments on commit c5d0558

Please sign in to comment.