mirror of
https://github.com/cheveguerra/whaticket-community.git
synced 2026-04-17 19:37:02 +00:00
add quick answers
This commit is contained in:
117
backend/src/controllers/QuickAnswerController.ts
Normal file
117
backend/src/controllers/QuickAnswerController.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import * as Yup from "yup";
|
||||
import { Request, Response } from "express";
|
||||
import { getIO } from "../libs/socket";
|
||||
|
||||
import ListQuickAnswerService from "../services/QuickAnswerService/ListQuickAnswerService";
|
||||
import CreateQuickAnswerService from "../services/QuickAnswerService/CreateQuickAnswerService";
|
||||
import ShowQuickAnswerService from "../services/QuickAnswerService/ShowQuickAnswerService";
|
||||
import UpdateQuickAnswerService from "../services/QuickAnswerService/UpdateQuickAnswerService";
|
||||
import DeleteQuickAnswerService from "../services/QuickAnswerService/DeleteQuickAnswerService";
|
||||
|
||||
import AppError from "../errors/AppError";
|
||||
|
||||
type IndexQuery = {
|
||||
searchParam: string;
|
||||
pageNumber: string;
|
||||
};
|
||||
|
||||
interface QuickAnswerData {
|
||||
shortcut: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||
const { searchParam, pageNumber } = req.query as IndexQuery;
|
||||
|
||||
const { quickAnswers, count, hasMore } = await ListQuickAnswerService({
|
||||
searchParam,
|
||||
pageNumber
|
||||
});
|
||||
|
||||
return res.json({ quickAnswers, count, hasMore });
|
||||
};
|
||||
|
||||
export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||
const newQuickAnswer: QuickAnswerData = req.body;
|
||||
|
||||
const QuickAnswerSchema = Yup.object().shape({
|
||||
shortcut: Yup.string().required(),
|
||||
message: Yup.string().required()
|
||||
});
|
||||
|
||||
try {
|
||||
await QuickAnswerSchema.validate(newQuickAnswer);
|
||||
} catch (err) {
|
||||
throw new AppError(err.message);
|
||||
}
|
||||
|
||||
const quickAnswer = await CreateQuickAnswerService({
|
||||
...newQuickAnswer
|
||||
});
|
||||
|
||||
const io = getIO();
|
||||
io.emit("quickAnswer", {
|
||||
action: "create",
|
||||
quickAnswer
|
||||
});
|
||||
|
||||
return res.status(200).json(quickAnswer);
|
||||
};
|
||||
|
||||
export const show = async (req: Request, res: Response): Promise<Response> => {
|
||||
const { quickAnswerId } = req.params;
|
||||
|
||||
const quickAnswer = await ShowQuickAnswerService(quickAnswerId);
|
||||
|
||||
return res.status(200).json(quickAnswer);
|
||||
};
|
||||
|
||||
export const update = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<Response> => {
|
||||
const quickAnswerData: QuickAnswerData = req.body;
|
||||
|
||||
const schema = Yup.object().shape({
|
||||
shortcut: Yup.string(),
|
||||
message: Yup.string()
|
||||
});
|
||||
|
||||
try {
|
||||
await schema.validate(quickAnswerData);
|
||||
} catch (err) {
|
||||
throw new AppError(err.message);
|
||||
}
|
||||
|
||||
const { quickAnswerId } = req.params;
|
||||
|
||||
const quickAnswer = await UpdateQuickAnswerService({
|
||||
quickAnswerData,
|
||||
quickAnswerId
|
||||
});
|
||||
|
||||
const io = getIO();
|
||||
io.emit("quickAnswer", {
|
||||
action: "update",
|
||||
quickAnswer
|
||||
});
|
||||
|
||||
return res.status(200).json(quickAnswer);
|
||||
};
|
||||
|
||||
export const remove = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<Response> => {
|
||||
const { quickAnswerId } = req.params;
|
||||
|
||||
await DeleteQuickAnswerService(quickAnswerId);
|
||||
|
||||
const io = getIO();
|
||||
io.emit("quickAnswer", {
|
||||
action: "delete",
|
||||
quickAnswerId
|
||||
});
|
||||
|
||||
return res.status(200).json({ message: "Quick Answer deleted" });
|
||||
};
|
||||
@@ -9,6 +9,7 @@ import Message from "../models/Message";
|
||||
import Queue from "../models/Queue";
|
||||
import WhatsappQueue from "../models/WhatsappQueue";
|
||||
import UserQueue from "../models/UserQueue";
|
||||
import QuickAnswer from "../models/QuickAnswer";
|
||||
|
||||
// eslint-disable-next-line
|
||||
const dbConfig = require("../config/database");
|
||||
@@ -26,7 +27,8 @@ const models = [
|
||||
Setting,
|
||||
Queue,
|
||||
WhatsappQueue,
|
||||
UserQueue
|
||||
UserQueue,
|
||||
QuickAnswer
|
||||
];
|
||||
|
||||
sequelize.addModels(models);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { QueryInterface, DataTypes } from "sequelize";
|
||||
|
||||
module.exports = {
|
||||
up: (queryInterface: QueryInterface) => {
|
||||
return queryInterface.createTable("quickAnswers", {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
shortcut: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: false
|
||||
},
|
||||
message: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: false
|
||||
},
|
||||
createdAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false
|
||||
},
|
||||
updatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
down: (queryInterface: QueryInterface) => {
|
||||
return queryInterface.dropTable("quickAnswers");
|
||||
}
|
||||
};
|
||||
32
backend/src/models/QuickAnswer.ts
Normal file
32
backend/src/models/QuickAnswer.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
Table,
|
||||
Column,
|
||||
DataType,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
Model,
|
||||
PrimaryKey,
|
||||
AutoIncrement
|
||||
} from "sequelize-typescript";
|
||||
|
||||
@Table
|
||||
class QuickAnswer extends Model<QuickAnswer> {
|
||||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column
|
||||
id: number;
|
||||
|
||||
@Column(DataType.TEXT)
|
||||
shortcut: string;
|
||||
|
||||
@Column(DataType.TEXT)
|
||||
message: string;
|
||||
|
||||
@CreatedAt
|
||||
createdAt: Date;
|
||||
|
||||
@UpdatedAt
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export default QuickAnswer;
|
||||
@@ -9,6 +9,7 @@ import whatsappRoutes from "./whatsappRoutes";
|
||||
import messageRoutes from "./messageRoutes";
|
||||
import whatsappSessionRoutes from "./whatsappSessionRoutes";
|
||||
import queueRoutes from "./queueRoutes";
|
||||
import quickAnswerRoutes from "./quickAnswerRoutes";
|
||||
|
||||
const routes = Router();
|
||||
|
||||
@@ -22,5 +23,6 @@ routes.use(messageRoutes);
|
||||
routes.use(messageRoutes);
|
||||
routes.use(whatsappSessionRoutes);
|
||||
routes.use(queueRoutes);
|
||||
routes.use(quickAnswerRoutes);
|
||||
|
||||
export default routes;
|
||||
|
||||
30
backend/src/routes/quickAnswerRoutes.ts
Normal file
30
backend/src/routes/quickAnswerRoutes.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import express from "express";
|
||||
import isAuth from "../middleware/isAuth";
|
||||
|
||||
import * as QuickAnswerController from "../controllers/QuickAnswerController";
|
||||
|
||||
const quickAnswerRoutes = express.Router();
|
||||
|
||||
quickAnswerRoutes.get("/quickAnswers", isAuth, QuickAnswerController.index);
|
||||
|
||||
quickAnswerRoutes.get(
|
||||
"/quickAnswers/:quickAnswerId",
|
||||
isAuth,
|
||||
QuickAnswerController.show
|
||||
);
|
||||
|
||||
quickAnswerRoutes.post("/quickAnswers", isAuth, QuickAnswerController.store);
|
||||
|
||||
quickAnswerRoutes.put(
|
||||
"/quickAnswers/:quickAnswerId",
|
||||
isAuth,
|
||||
QuickAnswerController.update
|
||||
);
|
||||
|
||||
quickAnswerRoutes.delete(
|
||||
"/quickAnswers/:quickAnswerId",
|
||||
isAuth,
|
||||
QuickAnswerController.remove
|
||||
);
|
||||
|
||||
export default quickAnswerRoutes;
|
||||
@@ -0,0 +1,26 @@
|
||||
import AppError from "../../errors/AppError";
|
||||
import QuickAnswer from "../../models/QuickAnswer";
|
||||
|
||||
interface Request {
|
||||
shortcut: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
const CreateQuickAnswerService = async ({
|
||||
shortcut,
|
||||
message
|
||||
}: Request): Promise<QuickAnswer> => {
|
||||
const nameExists = await QuickAnswer.findOne({
|
||||
where: { shortcut }
|
||||
});
|
||||
|
||||
if (nameExists) {
|
||||
throw new AppError("ERR__SHORTCUT_DUPLICATED");
|
||||
}
|
||||
|
||||
const quickAnswer = await QuickAnswer.create({ shortcut, message });
|
||||
|
||||
return quickAnswer;
|
||||
};
|
||||
|
||||
export default CreateQuickAnswerService;
|
||||
@@ -0,0 +1,16 @@
|
||||
import QuickAnswer from "../../models/QuickAnswer";
|
||||
import AppError from "../../errors/AppError";
|
||||
|
||||
const DeleteQuickAnswerService = async (id: string): Promise<void> => {
|
||||
const quickAnswer = await QuickAnswer.findOne({
|
||||
where: { id }
|
||||
});
|
||||
|
||||
if (!quickAnswer) {
|
||||
throw new AppError("ERR_NO_QUICK_ANSWER_FOUND", 404);
|
||||
}
|
||||
|
||||
await quickAnswer.destroy();
|
||||
};
|
||||
|
||||
export default DeleteQuickAnswerService;
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Sequelize } from "sequelize";
|
||||
import QuickAnswer from "../../models/QuickAnswer";
|
||||
|
||||
interface Request {
|
||||
searchParam?: string;
|
||||
pageNumber?: string;
|
||||
}
|
||||
|
||||
interface Response {
|
||||
quickAnswers: QuickAnswer[];
|
||||
count: number;
|
||||
hasMore: boolean;
|
||||
}
|
||||
|
||||
const ListQuickAnswerService = async ({
|
||||
searchParam = "",
|
||||
pageNumber = "1"
|
||||
}: Request): Promise<Response> => {
|
||||
const whereCondition = {
|
||||
message: Sequelize.where(
|
||||
Sequelize.fn("LOWER", Sequelize.col("message")),
|
||||
"LIKE",
|
||||
`%${searchParam.toLowerCase().trim()}%`
|
||||
)
|
||||
};
|
||||
const limit = 20;
|
||||
const offset = limit * (+pageNumber - 1);
|
||||
|
||||
const { count, rows: quickAnswers } = await QuickAnswer.findAndCountAll({
|
||||
where: whereCondition,
|
||||
limit,
|
||||
offset,
|
||||
order: [["message", "ASC"]]
|
||||
});
|
||||
|
||||
const hasMore = count > offset + quickAnswers.length;
|
||||
|
||||
return {
|
||||
quickAnswers,
|
||||
count,
|
||||
hasMore
|
||||
};
|
||||
};
|
||||
|
||||
export default ListQuickAnswerService;
|
||||
@@ -0,0 +1,14 @@
|
||||
import QuickAnswer from "../../models/QuickAnswer";
|
||||
import AppError from "../../errors/AppError";
|
||||
|
||||
const ShowQuickAnswerService = async (id: string): Promise<QuickAnswer> => {
|
||||
const quickAnswer = await QuickAnswer.findByPk(id);
|
||||
|
||||
if (!quickAnswer) {
|
||||
throw new AppError("ERR_NO_QUICK_ANSWERS_FOUND", 404);
|
||||
}
|
||||
|
||||
return quickAnswer;
|
||||
};
|
||||
|
||||
export default ShowQuickAnswerService;
|
||||
@@ -0,0 +1,40 @@
|
||||
import QuickAnswer from "../../models/QuickAnswer";
|
||||
import AppError from "../../errors/AppError";
|
||||
|
||||
interface QuickAnswerData {
|
||||
shortcut?: string;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
interface Request {
|
||||
quickAnswerData: QuickAnswerData;
|
||||
quickAnswerId: string;
|
||||
}
|
||||
|
||||
const UpdateQuickAnswerService = async ({
|
||||
quickAnswerData,
|
||||
quickAnswerId
|
||||
}: Request): Promise<QuickAnswer> => {
|
||||
const { shortcut, message } = quickAnswerData;
|
||||
|
||||
const quickAnswer = await QuickAnswer.findOne({
|
||||
where: { id: quickAnswerId },
|
||||
attributes: ["id", "shortcut", "message"]
|
||||
});
|
||||
|
||||
if (!quickAnswer) {
|
||||
throw new AppError("ERR_NO_QUICK_ANSWERS_FOUND", 404);
|
||||
}
|
||||
await quickAnswer.update({
|
||||
shortcut,
|
||||
message
|
||||
});
|
||||
|
||||
await quickAnswer.reload({
|
||||
attributes: ["id", "shortcut", "message"]
|
||||
});
|
||||
|
||||
return quickAnswer;
|
||||
};
|
||||
|
||||
export default UpdateQuickAnswerService;
|
||||
Reference in New Issue
Block a user