Merge branch 'main' of https://code.sdsdev.co.kr/SDSRV-IDP/sbt-idp into enhancment/accuracy_calculation

This commit is contained in:
dx-tan 2024-02-06 11:11:21 +07:00
commit b0a1bb1e6f
6 changed files with 1170 additions and 295 deletions

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@
"react-chartjs-2": "^5.2.0", "react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-json-view-lite": "^1.2.1", "react-json-view-lite": "^1.2.1",
"react-office-viewer": "^1.0.4",
"react-router-dom": "^6.6.1", "react-router-dom": "^6.6.1",
"styled-components": "^5.3.6", "styled-components": "^5.3.6",
"uuid": "^9.0.0" "uuid": "^9.0.0"

View File

@ -133,7 +133,7 @@ const columns: TableColumnsType<DataType> = [
key: 'snImeiAAR', key: 'snImeiAAR',
width: '130px', width: '130px',
render: (_, record) => { render: (_, record) => {
const isAbnormal = record.snImeiAAR * 100 < 98; const isAbnormal = record.snImeiAAR * 100 < 95;
return ( return (
<span style={{ color: isAbnormal ? 'red' : '' }}> <span style={{ color: isAbnormal ? 'red' : '' }}>
{(record.snImeiAAR * 100)?.toFixed(2)} {(record.snImeiAAR * 100)?.toFixed(2)}

View File

@ -131,33 +131,33 @@ const ReportTable: React.FC = () => {
}, },
}, },
{ {
title: 'Avg Accuracy', title: 'Avg. Accuracy',
dataIndex: 'Avg Accuracy', dataIndex: 'Avg. Accuracy',
key: 'Avg Accuracy', key: 'Avg. Accuracy',
render: (_, record) => { render: (_, record) => {
const isAbnormal = record['Avg Accuracy'] * 100 < 98; const isAbnormal = record['Avg. Accuracy'] * 100 < 98;
return ( return (
<span style={{ color: isAbnormal ? 'red' : '' }}> <span style={{ color: isAbnormal ? 'red' : '' }}>
{record['Avg Accuracy'] && {record['Avg. Accuracy'] &&
(Number(record['Avg Accuracy']) * 100)?.toFixed(2)} (Number(record['Avg. Accuracy']) * 100)?.toFixed(2)}
</span>
);
},
},
{
title: 'Avg Client Request Time',
dataIndex: 'Avg. Client Request Time',
key: 'Avg. Client Request Time',
render: (_, record) => {
const isAbnormal = record['Avg Client Request Time'] > 2;
return (
<span style={{ color: isAbnormal ? 'red' : '' }}>
{record['Avg Client Request Time'] &&
Number(record['Avg Client Request Time'])?.toFixed(2)}
</span> </span>
); );
}, },
}, },
// {
// title: 'Avg Client Request Time',
// dataIndex: 'Avg. Client Request Time',
// key: 'Avg. Client Request Time',
// render: (_, record) => {
// const isAbnormal = record['Avg Client Request Time'] > 2;
// return (
// <span style={{ color: isAbnormal ? 'red' : '' }}>
// {record['Avg Client Request Time'] &&
// Number(record['Avg Client Request Time'])?.toFixed(2)}
// </span>
// );
// },
// },
{ {
title: 'Avg. OCR Processing Time', title: 'Avg. OCR Processing Time',
dataIndex: 'Avg. OCR Processing Time', dataIndex: 'Avg. OCR Processing Time',

View File

@ -3,8 +3,6 @@ import { t } from '@lingui/macro';
import { import {
Button, Button,
Space, Space,
Table,
TableColumnsType,
Tooltip, Tooltip,
Typography, Typography,
} from 'antd'; } from 'antd';
@ -12,10 +10,11 @@ import { SbtPageHeader } from 'components/page-header';
import { Dayjs } from 'dayjs'; import { Dayjs } from 'dayjs';
import { ReportDetailList, ReportItemDetail } from 'models'; import { ReportDetailList, ReportItemDetail } from 'models';
import { useReportDetailList } from 'queries/report'; import { useReportDetailList } from 'queries/report';
import { useState } from 'react'; import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { downloadReport } from 'request/report'; import { downloadReport } from 'request/report';
import styled from 'styled-components'; import styled from 'styled-components';
import { SheetViewer } from "react-office-viewer"
export interface ReportFormValues { export interface ReportFormValues {
dateRange: [Dayjs, Dayjs]; dateRange: [Dayjs, Dayjs];
@ -33,225 +32,14 @@ const HeaderContainer = styled(Space)`
margin-bottom: 16px; margin-bottom: 16px;
`; `;
const ReportInformationContainer = styled.div`
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
padding: 16px;
border-radius: 10px;
width: 100%;
height: 400px;
`;
const columns: TableColumnsType<ReportItemDetail> = [
{
title: 'Request ID',
dataIndex: 'Request ID',
key: 'Request ID',
width: 100,
render: (value, record, index) => {
const shortenedValue =
String(value).length > 20
? String(value).substring(0, 20) + '...'
: String(value);
return <Tooltip title={value}>{shortenedValue}</Tooltip>;
},
},
{
title: 'Redemption Number',
dataIndex: 'Redemption Number',
key: 'Redemption Number',
},
{
title: 'Image type',
dataIndex: 'Image type',
key: 'Image type',
},
{
title: 'IMEI_user submitted',
dataIndex: 'IMEI_user submitted',
key: 'IMEI_user submitted',
},
{
title: 'IMEI_OCR retrieved',
dataIndex: 'IMEI_OCR retrieved',
key: 'IMEI_OCR retrieved',
},
{
title: 'IMEI1 Accuracy',
dataIndex: 'IMEI1 Accuracy',
key: 'IMEI1 Accuracy',
render: (_, record) => {
const isAbnormal = Number(record['IMEI1 Accuracy']) * 100 < 25;
return (
<span style={{ color: isAbnormal ? 'red' : '' }}>
{record['IMEI1 Accuracy'] &&
(Number(record['IMEI1 Accuracy']) * 100).toFixed(2)}
</span>
);
},
},
{
title: 'Invoice_Purchase Date_Consumer',
dataIndex: 'Invoice_Purchase Date_Consumer',
key: 'Invoice_Purchase Date_Consumer',
},
{
title: 'Invoice_Purchase Date_OCR',
dataIndex: 'Invoice_Purchase Date_OCR',
key: 'Invoice_Purchase Date_OCR',
},
{
title: 'Invoice_Purchase Date Accuracy',
dataIndex: 'Invoice_Purchase Date Accuracy',
key: 'Invoice_Purchase Date Accuracy',
render: (_, record) => {
const isAbnormal =
Number(record['Invoice_Purchase Date Accuracy']) * 100 < 25;
return (
<span style={{ color: isAbnormal ? 'red' : '' }}>
{record['Invoice_Purchase Date Accuracy'] &&
(Number(record['Invoice_Purchase Date Accuracy']) * 100).toFixed(2)}
</span>
);
},
},
{
title: 'Invoice_Retailer_Consumer',
dataIndex: 'Invoice_Retailer_Consumer',
key: 'Invoice_Retailer_Consumer',
},
{
title: 'Invoice_Retailer_OCR',
dataIndex: 'Invoice_Retailer_OCR',
key: 'Invoice_Retailer_OCR',
},
{
title: 'Invoice_Retailer Accuracy',
dataIndex: 'Invoice_Retailer Accuracy',
key: 'Invoice_Retailer Accuracy',
render: (_, record) => {
const isAbnormal = Number(record['Invoice_Retailer Accuracy']) * 100 < 25;
return (
<span style={{ color: isAbnormal ? 'red' : '' }}>
{record['Invoice_Retailer Accuracy'] &&
(Number(record['Invoice_Retailer Accuracy']) * 100).toFixed(2)}
</span>
);
},
},
{
title: 'Retailer_Revised Accuracy',
dataIndex: 'Retailer_Revised Accuracy',
key: 'Retailer_Revised Accuracy',
render: (_, record) => {
const isAbnormal = Number(record['Retailer_Revised Accuracy']) * 100 < 25;
return (
<span style={{ color: isAbnormal ? 'red' : '' }}>
{record['Retailer_Revised Accuracy'] &&
(Number(record['Retailer_Revised Accuracy']) * 100).toFixed(2)}
</span>
);
},
},
{
title: 'OCR Image Accuracy',
dataIndex: 'OCR Image Accuracy',
key: 'OCR Image Accuracy',
render: (_, record) => {
const isAbnormal = Number(record['OCR Image Accuracy']) * 100 < 25;
return (
<span style={{ color: isAbnormal ? 'red' : '' }}>
{record['OCR Image Accuracy'] &&
(Number(record['OCR Image Accuracy']) * 100).toFixed(2)}
</span>
);
},
},
{
title: 'OCR Image Speed (seconds)',
dataIndex: 'OCR Image Speed (seconds)',
key: 'OCR Image Speed (seconds)',
render: (_, record) => {
const isAbnormal = Number(record['OCR Image Speed (seconds)']) > 2;
return (
<span style={{ color: isAbnormal ? 'red' : '' }}>
{record['OCR Image Speed (seconds)'] &&
Number(record['OCR Image Speed (seconds)']).toFixed(2)}
</span>
);
},
sorter: (a, b) =>
a['OCR Image Speed (seconds)'] - b['OCR Image Speed (seconds)'],
},
{
title: 'Reviewed',
dataIndex: 'Reviewed',
key: 'Reviewed',
},
{
title: 'Bad Image Reasons',
dataIndex: 'Bad Image Reasons',
key: 'Bad Image Reasons',
},
{
title: 'Countermeasures',
dataIndex: 'Countermeasures',
key: 'Countermeasures',
},
{
title: 'IMEI_Revised Accuracy',
dataIndex: 'IMEI_Revised Accuracy',
key: 'IMEI_Revised Accuracy',
render: (_, record) => {
const isAbnormal = Number(record['IMEI_Revised Accuracy']) * 100 < 25;
return (
<span style={{ color: isAbnormal ? 'red' : '' }}>
{record['IMEI_Revised Accuracy'] &&
(Number(record['IMEI_Revised Accuracy']) * 100).toFixed(2)}
</span>
);
},
},
{
title: 'Purchase Date_Revised Accuracy',
dataIndex: 'Purchase Date_Revised Accuracy',
key: 'Purchase Date_Revised Accuracy',
render: (_, record) => {
const isAbnormal =
Number(record['Purchase Date_Revised Accuracy']) * 100 < 25;
return (
<span style={{ color: isAbnormal ? 'red' : '' }}>
{record['Purchase Date_Revised Accuracy'] &&
(Number(record['Purchase Date_Revised Accuracy']) * 100).toFixed(2)}
</span>
);
},
},
{
title: 'Retailer_Revised Accuracy',
dataIndex: 'Retailer_Revised Accuracy',
key: 'Retailer_Revised Accuracy',
render: (_, record) => {
const isAbnormal = Number(record['Retailer_Revised Accuracy']) * 100 < 25;
return (
<span style={{ color: isAbnormal ? 'red' : '' }}>
{record['Retailer_Revised Accuracy'] &&
(Number(record['Retailer_Revised Accuracy']) * 100).toFixed(2)}
</span>
);
},
},
];
const ReportDetail = () => { const ReportDetail = () => {
const [error, setError] = useState(null);
const [fileObject, setFileObject] = useState(null);
const [pagination, setPagination] = useState({ const [pagination, setPagination] = useState({
page: 1, page: 1,
page_size: 10, page_size: 10,
}); });
const { id } = useParams<{ id: string }>(); const { id } = useParams<{ id: string }>();
const { isLoading, data } = useReportDetailList({ const { isLoading, data } = useReportDetailList({
report_id: id, report_id: id,
page: pagination.page, page: pagination.page,
@ -271,6 +59,26 @@ const ReportDetail = () => {
URL.revokeObjectURL(anchorElement.href); URL.revokeObjectURL(anchorElement.href);
}; };
// Download and show report
useEffect(() => {
try {
downloadReport(id, (fileDetails) => {
if (!fileDetails?.file) {
setError("The report has not been ready to preview.");
}
var blob = new Blob(
[fileDetails.file],
{type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,"}
);
let blobUrl = URL.createObjectURL(blob);
setFileObject(blobUrl);
});
} catch (error) {
setError("The report has not been ready to preview.");
console.log(error);
}
}, []);
const handleBack = () => { const handleBack = () => {
window.history.back(); window.history.back();
}; };
@ -330,28 +138,9 @@ const ReportDetail = () => {
</Typography.Title> </Typography.Title>
</HeaderContainer> </HeaderContainer>
<ReportContainer> <ReportContainer>
<Table {(fileObject && !error) && <SheetViewer file={fileObject} />}
loading={isLoading} {(!fileObject && !error) && <Typography.Title level={5}>Loading...</Typography.Title>}
columns={columns} {error && <Typography.Title level={5}>{error}</Typography.Title>}
dataSource={report_data?.report_detail}
bordered
size='small'
pagination={{
current: pagination.page,
pageSize: pagination.page_size,
total: report_data?.page.count,
showTotal: (total, range) =>
`${range[0]}-${range[1]} of ${total} items`,
onChange: (page, pageSize) => {
setPagination({
page,
page_size: pageSize || 10,
});
},
showSizeChanger: false,
}}
scroll={{ x: 2000 }}
/>
</ReportContainer> </ReportContainer>
</> </>
); );

View File

@ -86,7 +86,7 @@ export async function getOverViewReport(params?: DashboardOverviewParams) {
} }
} }
export async function downloadReport(report_id: string) { export async function downloadReport(report_id: string, downloadFinishedCallback?: (fileDetails: any) => void) {
try { try {
const response = await API.get(`/ctel/get_report_file/${report_id}/`, { const response = await API.get(`/ctel/get_report_file/${report_id}/`, {
responseType: 'blob', // Important responseType: 'blob', // Important
@ -94,19 +94,29 @@ export async function downloadReport(report_id: string) {
let filename = "report.xlsx"; let filename = "report.xlsx";
try { try {
let basename = response.headers['content-disposition'].split('filename=')[1].split('.')[0]; let basename = response.headers['content-disposition'].split('filename=')[1].split('.')[0];
let extension = response.headers['content-disposition'].split('.')[1].split(';')[0]; if (basename[0] == '_') {
filename = `${basename}.${extension}` basename = basename.substring(1);
}
filename = `${basename}.xlsx`
} catch(err) { } catch(err) {
console.log(err); console.log(err);
} }
const file = new Blob([response.data], { const file = new Blob([response.data], {
type: 'application/vnd.ms-excel', type: 'application/vnd.ms-excel',
}); });
downloadFinishedCallback && downloadFinishedCallback({
file: file,
filename: filename,
});
return { return {
file: file, file: file,
filename: filename, filename: filename,
} }
} catch (error) { } catch (error) {
downloadFinishedCallback && downloadFinishedCallback({
file: null,
filename: null,
});
notification.error({ notification.error({
message: `${error?.message}`, message: `${error?.message}`,
}); });
@ -123,8 +133,10 @@ export async function downloadDashboardReport(duration='30d', subsidiary='ALL')
let filename = "report.xlsx"; let filename = "report.xlsx";
try { try {
let basename = response.headers['content-disposition'].split('filename=')[1].split('.')[0]; let basename = response.headers['content-disposition'].split('filename=')[1].split('.')[0];
let extension = response.headers['content-disposition'].split('.')[1].split(';')[0]; if (basename[0] == '_') {
filename = `${basename}.${extension}` basename = basename.substring(1);
}
filename = `${basename}.xlsx`
} catch(err) { } catch(err) {
console.log(err); console.log(err);
} }