Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Track-277] AS Sort groups in report #2472

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 55 additions & 13 deletions epictrack-api/src/api/reports/anticipated_schedule_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,31 @@ def __init__(self, filters, color_intensity):
"notes",
"next_pecp_number_of_days",
"amendment_title",
"work_type_id"
"work_type_id",
"work_type"
]
group_by = "work_type"
group_order = [
"Assessment",
"Typical Amendment",
"Complex Amendment",
"Simple Amendment",
"32(5) Amendment",
"Exemption Order",
"Project Notification",
"Minister's Designation",
"CEAO's Designation",
"EAC Extension",
"EAC/Order Transfer",
"Substantial Start Decision",
"EAC/Order Cancellation",
]
group_by = "phase_name"
item_sort_key = "referral_date"
template_name = "anticipated_schedule.docx"
super().__init__(
data_keys=data_keys,
group_by=group_by,
group_sort_order=group_order,
item_sort_key=item_sort_key,
template_name=template_name,
filters=filters,
Expand All @@ -104,6 +121,7 @@ def _fetch_data(self, report_date):
if self.filters and "exclude" in self.filters:
exclude_phase_names = self.filters["exclude"]
formatted_phase_name = self._get_formatted_phase_name()
formatted_work_type = self._get_formatted_work_type_name()
ea_type_column = self._get_ea_type_column(formatted_phase_name)
responsible_minister_column = self._get_responsible_minister_column(staff_minister)

Expand Down Expand Up @@ -259,6 +277,7 @@ def _fetch_data(self, report_date):
Event.id.label("event_id"),
Work.id.label("work_id"),
Work.work_type_id.label("work_type_id"),
formatted_work_type.label("work_type"),
case(
(
and_(
Expand All @@ -270,7 +289,7 @@ def _fetch_data(self, report_date):
else_=Project.name
).label("amendment_title"),
ea_type_column,
PhaseCode.name.label("phase_name"),
formatted_phase_name.label("phase_name"),
latest_status_updates.c.posted_date.label("date_updated"),
Project.name.label("project_name"),
func.coalesce(
Expand Down Expand Up @@ -442,14 +461,37 @@ def _get_ea_type_column(self, formatted_phase_name):
def _get_formatted_phase_name(self):
"""Returns an expression for the reformatted PhaseCode.name"""
return case(
# Case for 32.5
(
func.substring(PhaseCode.name, r"\((.*?)\)") == "32.5",
"32(5) Amendment"
),
else_=func.concat(func.substring(PhaseCode.name, r"\((.*?)\)"), " Amendment"),
(
WorkType.id == WorkTypeEnum.AMENDMENT.value,
case(
# Case for 32.5
(
func.substring(PhaseCode.name, r"\((.*?)\)") == "32.5",
"32(5) Amendment"
),
else_=func.concat(func.substring(PhaseCode.name, r"\((.*?)\)"), " Amendment"),
)
),
else_=PhaseCode.name
).label("formatted_phase_name")

def _get_formatted_work_type_name(self):
"""Returns an expression for the reformatted workType.name"""
return case(
(
WorkType.id == WorkTypeEnum.AMENDMENT.value,
case(
# Case for 32.5
(
func.substring(PhaseCode.name, r"\((.*?)\)") == "32.5",
"32(5) Amendment"
),
else_=func.concat(func.substring(PhaseCode.name, r"\((.*?)\)"), " Amendment"),
)
),
else_=WorkType.name
).label("formatted_work_type")

def _get_responsible_minister_column(self, staff_minister):
"""Returns an expression for the responsible minister"""
return case(
Expand Down Expand Up @@ -531,12 +573,12 @@ def _get_referral_event_query(self, start_date):
.subquery()
)

def _update_staleness(self, data: dict, report_date: datetime) -> dict:
def _update_staleness(self, data: list, report_date: datetime) -> list:
"""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"]:
for group in data:
for work in group.get("items"):
if work.get("date_updated"):
diff = (date - work["date_updated"]).days
if diff > 10:
work["staleness"] = StalenessEnum.CRITICAL.value
Expand Down
2 changes: 2 additions & 0 deletions epictrack-api/src/api/reports/report_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ def _format_data(self, data, report_title=None):
else len(self.group_sort_order), # Move other groups last
)
)
formatted_data = [{"group": group, "items": items} for group, items in formatted_data.items()]

return formatted_data

def _deserialize_work_issues(self, work_issues):
Expand Down
Binary file not shown.
4 changes: 3 additions & 1 deletion epictrack-api/src/api/reports/resource_forecast_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,9 @@ def generate_report(self, report_date, return_type):
def _update_month_labels(self, works, start_events):
"""Update month labels in the work result"""
results = defaultdict(list)
for work_id, work_data in works.items():
for group in works:
work_id = group.get("group")
work_data = group.get("items")
work = work_data[0]
for index, month in enumerate(self.months[1:]):
month_start = month.replace(day=1)
Expand Down
6 changes: 3 additions & 3 deletions epictrack-api/src/api/reports/thirty_sixty_ninety_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,13 @@ def _format_data(self, data, report_title=None):

def _update_work_issues(self, data) -> List[WorkIssues]:
"""Combine the result with work issues"""
work_ids = set((work["work_id"] for work in data))
work_ids = set((work.get("work_id") for work in data))
work_issues = WorkIssuesService.find_work_issues_by_work_ids(work_ids)
for result_item in data:
issue_per_work = [
issue
for issue in work_issues
if issue.work_id == result_item["work_id"]
if issue.work_id == result_item.get("work_id")
and issue.is_high_priority is True
]
for issue in issue_per_work:
Expand All @@ -233,7 +233,7 @@ def _update_work_issues(self, data) -> List[WorkIssues]:
issue_per_work
)
dates = [parser.isoparse(issue["latest_update"]["posted_date"]) for issue in issues]
dates.append(result_item["status_date_updated"])
dates.append(result_item.get("status_date_updated"))

if len(dates):
result_item["oldest_update"] = min(dates)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,17 @@ import ReportHeader from "../shared/report-header/ReportHeader";
import { ETPageContainer } from "../../shared";
import { staleLevel } from "utils/uiUtils";

interface Group {
group: string;
items: any[];
}

interface ReportData {
data: Group[];
}

export default function AnticipatedEAOSchedule() {
const [reports, setReports] = React.useState({});
const [reports, setReports] = React.useState<Group[]>([]);
const [showReportDateBanner, setShowReportDateBanner] =
React.useState<boolean>(false);
const [selectedTab, setSelectedTab] = React.useState(0);
Expand All @@ -54,10 +63,10 @@ export default function AnticipatedEAOSchedule() {
}, [reportDate]);

React.useEffect(() => {
const filterTypes = Object.keys(reports).filter(
(ele, index, arr) => arr.findIndex((t) => t === ele) === index
);
setTypeFilter(filterTypes);
if (reports) {
const filterTypes: string[] = reports.map((report) => report.group);
setTypeFilter(filterTypes);
}
}, [reports]);
const fetchReportData = React.useCallback(async () => {
setResultStatus(RESULT_STATUS.LOADING);
Expand All @@ -70,7 +79,8 @@ export default function AnticipatedEAOSchedule() {
);
setResultStatus(RESULT_STATUS.LOADED);
if (reportData.status === 200) {
setReports((reportData.data as never)["data"]);
const reports = reportData.data as ReportData;
setReports(reports.data);
}

if (reportData.status === 204) {
Expand Down Expand Up @@ -117,25 +127,6 @@ export default function AnticipatedEAOSchedule() {
setSelectedTab(newValue);
};

// const staleLevel = React.useCallback(
// (staleness: string) => {
// if (staleness == StalenessEnum.CRITICAL) {
// return {
// background: Palette.error.main,
// };
// } else if (staleness == StalenessEnum.WARN) {
// return {
// background: Palette.secondary.main,
// };
// } else {
// return {
// background: Palette.success.main,
// };
// }
// },
// [reportDate]
// );

interface TabPanelProps {
children?: React.ReactNode;
dir?: string;
Expand Down Expand Up @@ -180,7 +171,7 @@ export default function AnticipatedEAOSchedule() {
showReportDateBanner={showReportDateBanner}
/>
</Grid>
{Object.keys(reports).length > 0 && (
{reports && reports.length > 0 && (
<>
<Grid item sm={2}>
<FormLabel>Select Type to Hide</FormLabel>
Expand Down Expand Up @@ -211,9 +202,15 @@ export default function AnticipatedEAOSchedule() {
)}
<Grid item sm={12}>
{resultStatus === RESULT_STATUS.LOADED &&
Object.keys(reports)
.filter((key) => !selectedTypes.includes(key))
.map((key) => {
reports &&
reports
.filter((report) => {
const groupName = report.group;
return !selectedTypes.includes(groupName);
})
.map((group, _) => {
const groupName = group.group;
const items = group.items;
return (
<>
<Accordion
Expand All @@ -225,10 +222,10 @@ export default function AnticipatedEAOSchedule() {
elevation={0}
>
<AccordionSummary expandIcon={<ArrowForwardIosSharpIcon />}>
<Typography>{key}</Typography>
<Typography>{groupName}</Typography>
</AccordionSummary>
<AccordionDetails>
{((reports as any)[key] as []).map((item, itemIndex) => {
{items.map((item, itemIndex) => {
console.log(item);
return (
<Accordion key={itemIndex} elevation={0}>
Expand Down