From 9f99245dc4959ff17e7e6ebf9a3cd8f5e699b4b0 Mon Sep 17 00:00:00 2001 From: canove Date: Fri, 8 Jan 2021 17:41:08 -0300 Subject: [PATCH] feat: add queue and assoc with whatsapps --- backend/src/controllers/QueueController.ts | 19 ++++++++ backend/src/controllers/WhatsAppController.ts | 8 ++-- backend/src/database/index.ts | 6 ++- .../20210108164404-create-queues.ts | 36 +++++++++++++++ .../20210108164504-add-queueId-to-tickets.ts | 16 +++++++ ...20210108174594-associate-whatsapp-queue.ts | 28 ++++++++++++ backend/src/models/Queue.ts | 44 +++++++++++++++++++ backend/src/models/Whatsapp.ts | 8 +++- backend/src/models/WhatsappQueue.ts | 29 ++++++++++++ backend/src/routes/index.ts | 2 + backend/src/routes/queueRoutes.ts | 12 +++++ .../WhatsappService/CreateWhatsAppService.ts | 4 ++ .../WhatsappService/ListWhatsAppsService.ts | 7 ++- .../WhatsappService/UpdateWhatsAppService.ts | 5 ++- 14 files changed, 217 insertions(+), 7 deletions(-) create mode 100644 backend/src/controllers/QueueController.ts create mode 100644 backend/src/database/migrations/20210108164404-create-queues.ts create mode 100644 backend/src/database/migrations/20210108164504-add-queueId-to-tickets.ts create mode 100644 backend/src/database/migrations/20210108174594-associate-whatsapp-queue.ts create mode 100644 backend/src/models/Queue.ts create mode 100644 backend/src/models/WhatsappQueue.ts create mode 100644 backend/src/routes/queueRoutes.ts diff --git a/backend/src/controllers/QueueController.ts b/backend/src/controllers/QueueController.ts new file mode 100644 index 0000000..412840f --- /dev/null +++ b/backend/src/controllers/QueueController.ts @@ -0,0 +1,19 @@ +import { Request, Response } from "express"; +import Queue from "../models/Queue"; + +// import { getIO } from "../libs/socket"; +// import AppError from "../errors/AppError"; + +export const index = async (req: Request, res: Response): Promise => { + const queues = await Queue.findAll(); + + return res.status(200).json(queues); +}; + +export const store = async (req: Request, res: Response): Promise => { + const { name, color } = req.body; + + const queue = await Queue.create({ name, color }); + + return res.status(200).json(queue); +}; diff --git a/backend/src/controllers/WhatsAppController.ts b/backend/src/controllers/WhatsAppController.ts index 531bfe7..2ccad1f 100644 --- a/backend/src/controllers/WhatsAppController.ts +++ b/backend/src/controllers/WhatsAppController.ts @@ -11,6 +11,7 @@ import UpdateWhatsAppService from "../services/WhatsappService/UpdateWhatsAppSer interface WhatsappData { name: string; + queueIds: number[]; status?: string; isDefault?: boolean; } @@ -22,15 +23,16 @@ export const index = async (req: Request, res: Response): Promise => { }; export const store = async (req: Request, res: Response): Promise => { - const { name, status, isDefault }: WhatsappData = req.body; + const { name, status, isDefault, queueIds }: WhatsappData = req.body; const { whatsapp, oldDefaultWhatsapp } = await CreateWhatsAppService({ name, status, - isDefault + isDefault, + queueIds }); - StartWhatsAppSession(whatsapp); + // StartWhatsAppSession(whatsapp); const io = getIO(); io.emit("whatsapp", { diff --git a/backend/src/database/index.ts b/backend/src/database/index.ts index 9fb351d..9903d7e 100644 --- a/backend/src/database/index.ts +++ b/backend/src/database/index.ts @@ -6,6 +6,8 @@ import Ticket from "../models/Ticket"; import Whatsapp from "../models/Whatsapp"; import ContactCustomField from "../models/ContactCustomField"; import Message from "../models/Message"; +import Queue from "../models/Queue"; +import WhatsappQueue from "../models/WhatsappQueue"; // eslint-disable-next-line const dbConfig = require("../config/database"); @@ -20,7 +22,9 @@ const models = [ Message, Whatsapp, ContactCustomField, - Setting + Setting, + Queue, + WhatsappQueue ]; sequelize.addModels(models); diff --git a/backend/src/database/migrations/20210108164404-create-queues.ts b/backend/src/database/migrations/20210108164404-create-queues.ts new file mode 100644 index 0000000..41681d5 --- /dev/null +++ b/backend/src/database/migrations/20210108164404-create-queues.ts @@ -0,0 +1,36 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("Queues", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + name: { + type: DataTypes.STRING, + allowNull: false, + unique: true + }, + color: { + type: DataTypes.STRING, + allowNull: false, + unique: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("Queues"); + } +}; diff --git a/backend/src/database/migrations/20210108164504-add-queueId-to-tickets.ts b/backend/src/database/migrations/20210108164504-add-queueId-to-tickets.ts new file mode 100644 index 0000000..6122b32 --- /dev/null +++ b/backend/src/database/migrations/20210108164504-add-queueId-to-tickets.ts @@ -0,0 +1,16 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.addColumn("Tickets", "queueId", { + type: DataTypes.INTEGER, + references: { model: "Queues", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL" + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.removeColumn("Tickets", "queueId"); + } +}; diff --git a/backend/src/database/migrations/20210108174594-associate-whatsapp-queue.ts b/backend/src/database/migrations/20210108174594-associate-whatsapp-queue.ts new file mode 100644 index 0000000..0e08f71 --- /dev/null +++ b/backend/src/database/migrations/20210108174594-associate-whatsapp-queue.ts @@ -0,0 +1,28 @@ +import { QueryInterface, DataTypes } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("WhatsappQueues", { + whatsappId: { + type: DataTypes.INTEGER, + primaryKey: true + }, + queueId: { + type: DataTypes.INTEGER, + primaryKey: true + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("WhatsappQueues"); + } +}; diff --git a/backend/src/models/Queue.ts b/backend/src/models/Queue.ts new file mode 100644 index 0000000..1178329 --- /dev/null +++ b/backend/src/models/Queue.ts @@ -0,0 +1,44 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement, + AllowNull, + Unique, + BelongsToMany +} from "sequelize-typescript"; + +import Whatsapp from "./Whatsapp"; +import WhatsappQueue from "./WhatsappQueue"; + +@Table +class Queue extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @AllowNull(false) + @Unique + @Column + name: string; + + @AllowNull(false) + @Unique + @Column + color: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; + + @BelongsToMany(() => Whatsapp, () => WhatsappQueue) + whatsapps: Array; +} + +export default Queue; diff --git a/backend/src/models/Whatsapp.ts b/backend/src/models/Whatsapp.ts index 099b0db..ba6febb 100644 --- a/backend/src/models/Whatsapp.ts +++ b/backend/src/models/Whatsapp.ts @@ -10,9 +10,12 @@ import { Default, AllowNull, HasMany, - Unique + Unique, + BelongsToMany } from "sequelize-typescript"; +import Queue from "./Queue"; import Ticket from "./Ticket"; +import WhatsappQueue from "./WhatsappQueue"; @Table class Whatsapp extends Model { @@ -57,6 +60,9 @@ class Whatsapp extends Model { @HasMany(() => Ticket) tickets: Ticket[]; + + @BelongsToMany(() => Queue, () => WhatsappQueue) + queues: Array; } export default Whatsapp; diff --git a/backend/src/models/WhatsappQueue.ts b/backend/src/models/WhatsappQueue.ts new file mode 100644 index 0000000..17479cc --- /dev/null +++ b/backend/src/models/WhatsappQueue.ts @@ -0,0 +1,29 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + ForeignKey +} from "sequelize-typescript"; +import Queue from "./Queue"; +import Whatsapp from "./Whatsapp"; + +@Table +class WhatsappQueue extends Model { + @ForeignKey(() => Whatsapp) + @Column + whatsappId: number; + + @ForeignKey(() => Queue) + @Column + queueId: number; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; +} + +export default WhatsappQueue; diff --git a/backend/src/routes/index.ts b/backend/src/routes/index.ts index 2abafa8..7043f61 100644 --- a/backend/src/routes/index.ts +++ b/backend/src/routes/index.ts @@ -8,6 +8,7 @@ import ticketRoutes from "./ticketRoutes"; import whatsappRoutes from "./whatsappRoutes"; import messageRoutes from "./messageRoutes"; import whatsappSessionRoutes from "./whatsappSessionRoutes"; +import queueRoutes from "./queueRoutes"; const routes = Router(); @@ -20,5 +21,6 @@ routes.use(whatsappRoutes); routes.use(messageRoutes); routes.use(messageRoutes); routes.use(whatsappSessionRoutes); +routes.use(queueRoutes); export default routes; diff --git a/backend/src/routes/queueRoutes.ts b/backend/src/routes/queueRoutes.ts new file mode 100644 index 0000000..51e793d --- /dev/null +++ b/backend/src/routes/queueRoutes.ts @@ -0,0 +1,12 @@ +import { Router } from "express"; +import isAuth from "../middleware/isAuth"; + +import * as QueueController from "../controllers/QueueController"; + +const queueRoutes = Router(); + +queueRoutes.get("/queue", isAuth, QueueController.index); + +queueRoutes.post("/queue", isAuth, QueueController.store); + +export default queueRoutes; diff --git a/backend/src/services/WhatsappService/CreateWhatsAppService.ts b/backend/src/services/WhatsappService/CreateWhatsAppService.ts index 118343e..fc2f1b2 100644 --- a/backend/src/services/WhatsappService/CreateWhatsAppService.ts +++ b/backend/src/services/WhatsappService/CreateWhatsAppService.ts @@ -5,6 +5,7 @@ import Whatsapp from "../../models/Whatsapp"; interface Request { name: string; + queueIds: number[]; status?: string; isDefault?: boolean; } @@ -17,6 +18,7 @@ interface Response { const CreateWhatsAppService = async ({ name, status = "OPENING", + queueIds, isDefault = false }: Request): Promise => { const schema = Yup.object().shape({ @@ -68,6 +70,8 @@ const CreateWhatsAppService = async ({ isDefault }); + await whatsapp.$set("queues", queueIds); + return { whatsapp, oldDefaultWhatsapp }; }; diff --git a/backend/src/services/WhatsappService/ListWhatsAppsService.ts b/backend/src/services/WhatsappService/ListWhatsAppsService.ts index 2213530..5a1817a 100644 --- a/backend/src/services/WhatsappService/ListWhatsAppsService.ts +++ b/backend/src/services/WhatsappService/ListWhatsAppsService.ts @@ -1,7 +1,12 @@ +import Queue from "../../models/Queue"; import Whatsapp from "../../models/Whatsapp"; const ListWhatsAppsService = async (): Promise => { - const whatsapps = await Whatsapp.findAll(); + const whatsapps = await Whatsapp.findAll({ + include: [ + { model: Queue, as: "queues", attributes: ["id", "name", "color"] } + ] + }); return whatsapps; }; diff --git a/backend/src/services/WhatsappService/UpdateWhatsAppService.ts b/backend/src/services/WhatsappService/UpdateWhatsAppService.ts index 2fe79cc..04c3c72 100644 --- a/backend/src/services/WhatsappService/UpdateWhatsAppService.ts +++ b/backend/src/services/WhatsappService/UpdateWhatsAppService.ts @@ -9,6 +9,7 @@ interface WhatsappData { status?: string; session?: string; isDefault?: boolean; + queueIds?: number[]; } interface Request { @@ -30,7 +31,7 @@ const UpdateWhatsAppService = async ({ isDefault: Yup.boolean() }); - const { name, status, isDefault, session } = whatsappData; + const { name, status, isDefault, session, queueIds = [] } = whatsappData; try { await schema.validate({ name, status, isDefault }); @@ -63,6 +64,8 @@ const UpdateWhatsAppService = async ({ isDefault }); + await whatsapp.$set("queues", queueIds); + return { whatsapp, oldDefaultWhatsapp }; };