Criação de opção de exportar para CSV relatório detalhado
parent
7baed2a7da
commit
df59d8af43
|
@ -3,6 +3,7 @@
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import AppError from "../errors/AppError";
|
import AppError from "../errors/AppError";
|
||||||
import ShowTicketReport from "../services/TicketServices/ShowTicketReport";
|
import ShowTicketReport from "../services/TicketServices/ShowTicketReport";
|
||||||
|
import ShowMessageReport from "../services/MessageServices/ShowMessageReport";
|
||||||
|
|
||||||
|
|
||||||
type IndexQuery = {
|
type IndexQuery = {
|
||||||
|
@ -20,12 +21,29 @@ export const reportUserByDateStartDateEnd = async (req: Request, res: Response):
|
||||||
|
|
||||||
const { userId, startDate, endDate } = req.query as IndexQuery
|
const { userId, startDate, endDate } = req.query as IndexQuery
|
||||||
|
|
||||||
const data_query = await ShowTicketReport(userId, startDate, endDate);
|
const data_query = await ShowTicketReport(userId, startDate, endDate);
|
||||||
|
|
||||||
return res.status(200).json(data_query);
|
return res.status(200).json(data_query);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const reportMessagesUserByDateStartDateEnd = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
|
||||||
|
if (req.user.profile !== "master" && req.user.profile !== "admin") {
|
||||||
|
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { userId, startDate, endDate } = req.query as IndexQuery
|
||||||
|
|
||||||
|
const data_query_messages = await ShowMessageReport(userId, startDate, endDate);
|
||||||
|
|
||||||
|
return res.status(200).json(data_query_messages);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,4 +9,6 @@ const reportRoutes = express.Router();
|
||||||
|
|
||||||
reportRoutes.get("/reports", isAuth, ReportController.reportUserByDateStartDateEnd);
|
reportRoutes.get("/reports", isAuth, ReportController.reportUserByDateStartDateEnd);
|
||||||
|
|
||||||
|
reportRoutes.get("/reports/messages", isAuth, ReportController.reportMessagesUserByDateStartDateEnd);
|
||||||
|
|
||||||
export default reportRoutes;
|
export default reportRoutes;
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
import Ticket from "../../models/Ticket";
|
||||||
|
import AppError from "../../errors/AppError";
|
||||||
|
import Contact from "../../models/Contact";
|
||||||
|
import User from "../../models/User";
|
||||||
|
import Queue from "../../models/Queue";
|
||||||
|
|
||||||
|
import Message from "../../models/Message";
|
||||||
|
import { userInfo } from "os";
|
||||||
|
|
||||||
|
import { Op, where } from "sequelize";
|
||||||
|
|
||||||
|
import { Sequelize } from "sequelize";
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import { startOfDay, endOfDay, parseISO, getDate} from "date-fns";
|
||||||
|
import { string } from "yup/lib/locale";
|
||||||
|
import Whatsapp from "../../models/Whatsapp";
|
||||||
|
|
||||||
|
//Report by user, startDate, endDate
|
||||||
|
const ShowMessageReport = async (id: string | number, startDate: string, endDate: string): Promise<Message[]> => {
|
||||||
|
|
||||||
|
let where_clause_user = {}
|
||||||
|
|
||||||
|
let where_clause = {
|
||||||
|
createdAt: {
|
||||||
|
[Op.gte]: startDate+' 00:00:00.000000',
|
||||||
|
[Op.lte]: endDate +' 23:59:59.999999'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if(id=='0'){
|
||||||
|
|
||||||
|
// where_clause_user = {
|
||||||
|
// createdAt: {
|
||||||
|
// [Op.gte]: startDate+' 00:00:00.000000',
|
||||||
|
// [Op.lte]: endDate +' 23:59:59.999999'
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
where_clause_user = {
|
||||||
|
userid: id,
|
||||||
|
// createdAt: {
|
||||||
|
// [Op.gte]: startDate+' 00:00:00.000000',
|
||||||
|
// [Op.lte]: endDate +' 23:59:59.999999'
|
||||||
|
// },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const messages = await Message.findAll({
|
||||||
|
|
||||||
|
where: where_clause ,
|
||||||
|
|
||||||
|
attributes: ['id', 'body', 'read', 'mediaType','fromMe', 'mediaUrl', [Sequelize.fn("DATE_FORMAT",Sequelize.col("Message.createdAt"),"%d/%m/%Y %H:%i:%s"),"createdAt"]],
|
||||||
|
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Ticket,
|
||||||
|
where: where_clause_user,
|
||||||
|
required:true,
|
||||||
|
|
||||||
|
attributes: ['id', 'status'],
|
||||||
|
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Contact,
|
||||||
|
attributes: ['name', 'number']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: User,
|
||||||
|
attributes: ['name', 'email']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Queue,
|
||||||
|
attributes: ['name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Whatsapp,
|
||||||
|
attributes: ['name']
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
order: [
|
||||||
|
['createdAt', 'ASC']
|
||||||
|
]
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (!messages) {
|
||||||
|
throw new AppError("ERR_NO_MESSAGES_FOUND", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
return messages;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ShowMessageReport;
|
|
@ -3,19 +3,7 @@ import React, { useState, useRef} from "react";
|
||||||
import { CSVLink } from "react-csv";
|
import { CSVLink } from "react-csv";
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
|
|
||||||
/*const headers = [
|
|
||||||
{ label: "First Name", key: "firstname" },
|
|
||||||
{ label: "Last Name", key: "lastname" },
|
|
||||||
{ label: "Email", key: "email" }
|
|
||||||
];
|
|
||||||
|
|
||||||
const data = [
|
|
||||||
{ firstname: "Ahmed", lastname: "Tomi", email: "ah@smthing.co.com" },
|
|
||||||
{ firstname: "Raed", lastname: "Labes", email: "rl@smthing.co.com" },
|
|
||||||
{ firstname: "Yezzi", lastname: "Min l3b", email: "ymin@cocococo.com" }
|
|
||||||
];*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const ExportCSV = (props) => {
|
const ExportCSV = (props) => {
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,81 @@
|
||||||
import React, { useState, useEffect, useReducer, useContext} from "react";
|
import React, { useState, useEffect, useReducer, useContext, useRef} from "react";
|
||||||
import MainContainer from "../../components/MainContainer";
|
import MainContainer from "../../components/MainContainer";
|
||||||
import api from "../../services/api";
|
import api from "../../services/api";
|
||||||
import SelectField from "../../components/Report/SelectField";
|
import SelectField from "../../components/Report/SelectField";
|
||||||
//import { data } from '../../components/Report/MTable/data';
|
//import { data } from '../../components/Report/MTable/data';
|
||||||
import DatePicker1 from '../../components/Report/DatePicker'
|
import DatePicker1 from '../../components/Report/DatePicker'
|
||||||
import DatePicker2 from '../../components/Report/DatePicker'
|
import DatePicker2 from '../../components/Report/DatePicker'
|
||||||
//import { Button } from "@material-ui/core";
|
|
||||||
import MTable from "../../components/Report/MTable";
|
import MTable from "../../components/Report/MTable";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext";
|
import { AuthContext } from "../../context/Auth/AuthContext";
|
||||||
import { Can } from "../../components/Can";
|
import { Can } from "../../components/Can";
|
||||||
|
|
||||||
|
import { Button } from "@material-ui/core";
|
||||||
|
|
||||||
|
|
||||||
|
// test del
|
||||||
|
|
||||||
|
// import ExportCSV from '../../components/Report/ExportCSV'
|
||||||
|
|
||||||
|
import { CSVLink } from "react-csv";
|
||||||
|
|
||||||
|
let columns = [
|
||||||
|
{
|
||||||
|
key: 'ticket.whatsapp.name',
|
||||||
|
label: 'Loja',
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
label: 'id Mensagem',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'ticket.id',
|
||||||
|
label: 'id Conversa',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'ticket.contact.name',
|
||||||
|
label: 'Cliente',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'ticket.user.name',
|
||||||
|
label: 'Atendente',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'body',
|
||||||
|
label: 'Mensagem',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'fromMe',
|
||||||
|
label: 'Sentido',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'createdAt',
|
||||||
|
label: 'Criada',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'ticket.contact.number',
|
||||||
|
label: 'Telefone cliente',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'ticket.queue.name',
|
||||||
|
label: 'Fila',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'ticket.status',
|
||||||
|
label: 'Status',
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const reducerQ = (state, action) =>{
|
const reducerQ = (state, action) =>{
|
||||||
|
|
||||||
|
@ -106,7 +170,7 @@ Item.propTypes = {
|
||||||
|
|
||||||
|
|
||||||
let columnsData = [
|
let columnsData = [
|
||||||
{ title: 'Whatsapp', field: 'whatsapp.name' },
|
{ title: 'Unidade', field: 'whatsapp.name' },
|
||||||
{ title: 'Atendente', field: 'user.name' },
|
{ title: 'Atendente', field: 'user.name' },
|
||||||
{ title: 'Contato', field: 'contact.number' },
|
{ title: 'Contato', field: 'contact.number' },
|
||||||
{ title: 'Nome', field: 'contact.name' },
|
{ title: 'Nome', field: 'contact.name' },
|
||||||
|
@ -157,6 +221,8 @@ let columnsData = [
|
||||||
|
|
||||||
|
|
||||||
const Report = () => {
|
const Report = () => {
|
||||||
|
|
||||||
|
const csvLink = useRef()
|
||||||
|
|
||||||
const { user: userA } = useContext(AuthContext);
|
const { user: userA } = useContext(AuthContext);
|
||||||
|
|
||||||
|
@ -172,6 +238,9 @@ const Report = () => {
|
||||||
const [userId, setUser] = useState(null)
|
const [userId, setUser] = useState(null)
|
||||||
const [query, dispatchQ] = useReducer(reducerQ, [])
|
const [query, dispatchQ] = useReducer(reducerQ, [])
|
||||||
|
|
||||||
|
const [dataCSV, setDataCSV] = useState([])
|
||||||
|
const [isMount, setIsMount] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch({ type: "RESET" });
|
dispatch({ type: "RESET" });
|
||||||
dispatchQ({ type: "RESET" })
|
dispatchQ({ type: "RESET" })
|
||||||
|
@ -221,7 +290,9 @@ const Report = () => {
|
||||||
|
|
||||||
//setLoading(false);
|
//setLoading(false);
|
||||||
|
|
||||||
console.log('dataQuery: ', dataQuery.data)
|
// console.log('dataQuery: ', dataQuery.data)
|
||||||
|
|
||||||
|
console.log()
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
@ -253,8 +324,68 @@ const textFieldSelectUser = (data) => {
|
||||||
|
|
||||||
setUser(data)
|
setUser(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// test del
|
||||||
|
|
||||||
|
const handleCSVMessages = () =>{
|
||||||
|
|
||||||
|
// setLoading(true);
|
||||||
|
|
||||||
|
const fetchQueries = async () => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const dataQuery = await api.get("/reports/messages", {params: {userId, startDate, endDate },});
|
||||||
|
|
||||||
|
// console.log('dataQuery messages: ', dataQuery.data)
|
||||||
|
|
||||||
|
if(dataQuery.data.length > 0){
|
||||||
|
|
||||||
|
let dataCSVFormat = dataQuery.data ;
|
||||||
|
|
||||||
|
for(var i = 0; i<dataCSVFormat.length; i++){
|
||||||
|
if(dataCSVFormat[i].fromMe){
|
||||||
|
dataCSVFormat[i].fromMe = 'Atendente'
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
dataCSVFormat[i].fromMe = 'Cliente'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('dataCSVFormat: ', dataCSVFormat)
|
||||||
|
|
||||||
|
setDataCSV(dataCSVFormat)
|
||||||
|
// setDataCSV(dataQuery.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setLoading(false);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchQueries();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
if(isMount){
|
||||||
|
setIsMount(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
csvLink.current.link.click()
|
||||||
|
|
||||||
|
}, [dataCSV]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
|
@ -274,7 +405,24 @@ const textFieldSelectUser = (data) => {
|
||||||
<Item><DatePicker2 func={datePicker2Value} minDate={false} startEmpty={false} title={'Data fim'}/></Item>
|
<Item><DatePicker2 func={datePicker2Value} minDate={false} startEmpty={false} title={'Data fim'}/></Item>
|
||||||
|
|
||||||
<Item sx={{ gridColumn: '4 / 5' }}>
|
<Item sx={{ gridColumn: '4 / 5' }}>
|
||||||
{/* <Button size="small" variant="contained" onClick={()=>{handleQuery()}}>GO</Button>*/}
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
onClick={(e) => handleCSVMessages()}
|
||||||
|
>
|
||||||
|
{"CSV ALL"}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<CSVLink
|
||||||
|
data={dataCSV}
|
||||||
|
headers={columns}
|
||||||
|
filename= {'Relatorio_detalhado_atendimento_atendentes.csv'}
|
||||||
|
target={'_blank'}
|
||||||
|
ref={csvLink}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
</Item>
|
</Item>
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -16,7 +16,7 @@ import toastError from "../../errors/toastError";
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext";
|
import { AuthContext } from "../../context/Auth/AuthContext";
|
||||||
import { Can } from "../../components/Can";
|
import { Can } from "../../components/Can";
|
||||||
|
|
||||||
import Button from "@material-ui/core/Button";
|
// import Button from "@material-ui/core/Button";
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
root: {
|
root: {
|
||||||
|
|
Loading…
Reference in New Issue