Merge branch 'main' of https://code.sdsdev.co.kr/SDSRV-IDP/sbt-idp into enhancment/accuracy_calculation
This commit is contained in:
commit
b0a1bb1e6f
1135
cope2n-fe/package-lock.json
generated
1135
cope2n-fe/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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"
|
||||||
|
@ -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)}
|
||||||
|
@ -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',
|
||||||
|
@ -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>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user