diff --git a/.gitignore b/.gitignore index 600d2d3..0dc7b4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -.vscode \ No newline at end of file +/.vscode \ No newline at end of file diff --git a/backend/src/app.js b/backend/src/app.js index 3b62358..35bde72 100644 --- a/backend/src/app.js +++ b/backend/src/app.js @@ -1,21 +1,20 @@ require("express-async-errors"); -require("dotenv/config"); require("./database"); const express = require("express"); const path = require("path"); const Youch = require("youch"); const cors = require("cors"); -// const sequelize = require("./database/"); const multer = require("multer"); -// const wBot = require("./libs/wbot"); -// const wbotMessageListener = require("./services/wbotMessageListener"); -// const wbotMonitor = require("./services/wbotMonitor"); +const wBot = require("./libs/wbot"); +const wbotMessageListener = require("./services/wbotMessageListener"); +const wbotMonitor = require("./services/wbotMonitor"); -// const MessagesRoutes = require("./routes/messages"); -// const ContactsRoutes = require("./routes/contacts"); +const MessagesRoutes = require("./routes/messages"); +const ContactsRoutes = require("./routes/contacts"); const AuthRoutes = require("./routes/auth"); -// const WhatsRoutes = require("./routes/whatsapp"); +const TicketsRoutes = require("./routes/tickets"); +const WhatsRoutes = require("./routes/whatsapp"); const app = express(); @@ -34,14 +33,10 @@ app.use(multer({ storage: fileStorage }).single("media")); app.use("/public", express.static(path.join(__dirname, "public"))); app.use("/auth", AuthRoutes); - -app.listen(process.env.PORT, () => { - console.log(`Server started on port: ${process.env.PORT}`); -}); - -// app.use(MessagesRoutes); -// app.use(ContactsRoutes); -// app.use(WhatsRoutes); +app.use(ContactsRoutes); +app.use(TicketsRoutes); +app.use(MessagesRoutes); +app.use(WhatsRoutes); app.use(async (err, req, res, next) => { if (process.env.NODE_ENV === "development") { @@ -53,33 +48,32 @@ app.use(async (err, req, res, next) => { return res.status(500).json({ error: "Internal server error" }); }); -// sequelize -// .sync() -// .then(() => { -// const server = app.listen(process.env.PORT); -// const io = require("./libs/socket").init(server); -// io.on("connection", socket => { -// console.log("Client Connected"); -// socket.on("joinChatBox", contactId => { -// socket.join(contactId); -// }); +const server = app.listen(process.env.PORT, () => { + console.log(`Server started on port: ${process.env.PORT}`); +}); -// socket.on("joinNotification", () => { -// console.log("chat entrou no canal de notificações"); -// socket.join("notification"); -// }); +const io = require("./libs/socket").init(server); +io.on("connection", socket => { + console.log("Client Connected"); + socket.on("joinChatBox", ticketId => { + console.log("A client joined in a ticket channel"); + socket.join(ticketId); + }); -// socket.on("disconnect", () => { -// console.log("Client disconnected"); -// }); -// }); + socket.on("joinNotification", () => { + console.log("A client joined notification channel"); + socket.join("notification"); + }); -// wBot.init().then(() => { -// wbotMessageListener(); -// wbotMonitor(); -// }); -// console.log("Server started on", process.env.PORT); -// }) -// .catch(err => { -// console.log(err); -// }); + socket.on("disconnect", () => { + console.log("Client disconnected"); + }); +}); + +wBot + .init() + .then(() => { + wbotMessageListener(); + wbotMonitor(); + }) + .catch(err => console.log(err)); diff --git a/backend/src/config/database.js b/backend/src/config/database.js index 808817e..654fd21 100644 --- a/backend/src/config/database.js +++ b/backend/src/config/database.js @@ -11,5 +11,5 @@ module.exports = { database: process.env.DB_NAME, username: process.env.DB_USER, password: process.env.DB_PASS, - logging: true, + logging: false, }; diff --git a/backend/src/controllers/ContactController copy.js b/backend/src/controllers/ContactController copy.js new file mode 100644 index 0000000..4e74310 --- /dev/null +++ b/backend/src/controllers/ContactController copy.js @@ -0,0 +1,67 @@ +const Contact = require("../models/Contact"); +const Message = require("../models/Message"); +const Sequelize = require("sequelize"); +const { getIO } = require("../libs/socket"); +const { getWbot } = require("../libs/wbot"); + +exports.index = async (req, res) => { + const { searchParam = "" } = req.query; + + const lowerSerachParam = searchParam.toLowerCase(); + + const whereCondition = { + name: Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("name")), + "LIKE", + "%" + lowerSerachParam + "%" + ), + }; + + //todo >> add contact number to search where condition + + const contacts = await Contact.findAll({ + where: whereCondition, + attributes: { + include: [ + [ + Sequelize.literal(`( + SELECT COUNT(*) + FROM messages AS message + WHERE + message.contactId = contact.id + AND + message.read = 0 + + )`), + "unreadMessages", + ], + ], + }, + order: [["updatedAt", "DESC"]], + }); + + return res.json(contacts); +}; + +exports.store = async (req, res) => { + const wbot = getWbot(); + const io = getIO(); + const { number, name } = req.body; + + const result = await wbot.isRegisteredUser(`55${number}@c.us`); + + if (!result) { + return res + .status(400) + .json({ error: "The suplied number is not a valid Whatsapp number" }); + } + const profilePicUrl = await wbot.getProfilePicUrl(`55${number}@c.us`); + + const contact = await Contact.create({ + name, + number: `55${number}`, + profilePicUrl, + }); + + res.status(200).json(contact); +}; diff --git a/backend/src/controllers/ContactController.js b/backend/src/controllers/ContactController.js index 4e74310..de46f8b 100644 --- a/backend/src/controllers/ContactController.js +++ b/backend/src/controllers/ContactController.js @@ -1,67 +1,44 @@ const Contact = require("../models/Contact"); -const Message = require("../models/Message"); -const Sequelize = require("sequelize"); -const { getIO } = require("../libs/socket"); -const { getWbot } = require("../libs/wbot"); +// const Message = require("../models/Message"); +// const Sequelize = require("sequelize"); +// const { getIO } = require("../libs/socket"); +// const { getWbot } = require("../libs/wbot"); exports.index = async (req, res) => { - const { searchParam = "" } = req.query; + // const { searchParam = "" } = req.query; - const lowerSerachParam = searchParam.toLowerCase(); + // const lowerSerachParam = searchParam.toLowerCase(); - const whereCondition = { - name: Sequelize.where( - Sequelize.fn("LOWER", Sequelize.col("name")), - "LIKE", - "%" + lowerSerachParam + "%" - ), - }; + // const whereCondition = { + // name: Sequelize.where( + // Sequelize.fn("LOWER", Sequelize.col("name")), + // "LIKE", + // "%" + lowerSerachParam + "%" + // ), + // }; //todo >> add contact number to search where condition - const contacts = await Contact.findAll({ - where: whereCondition, - attributes: { - include: [ - [ - Sequelize.literal(`( - SELECT COUNT(*) - FROM messages AS message - WHERE - message.contactId = contact.id - AND - message.read = 0 - - )`), - "unreadMessages", - ], - ], - }, - order: [["updatedAt", "DESC"]], - }); + const contacts = await Contact.findAll(); return res.json(contacts); }; exports.store = async (req, res) => { - const wbot = getWbot(); - const io = getIO(); - const { number, name } = req.body; + // const wbot = getWbot(); + // const io = getIO(); + // const { number, name } = req.body; - const result = await wbot.isRegisteredUser(`55${number}@c.us`); + // const result = await wbot.isRegisteredUser(`55${number}@c.us`); - if (!result) { - return res - .status(400) - .json({ error: "The suplied number is not a valid Whatsapp number" }); - } - const profilePicUrl = await wbot.getProfilePicUrl(`55${number}@c.us`); + // if (!result) { + // return res + // .status(400) + // .json({ error: "The suplied number is not a valid Whatsapp number" }); + // } + // const profilePicUrl = await wbot.getProfilePicUrl(`55${number}@c.us`); - const contact = await Contact.create({ - name, - number: `55${number}`, - profilePicUrl, - }); + const { number, name } = await Contact.create(req.body); - res.status(200).json(contact); + res.status(200).json({ number, name }); }; diff --git a/backend/src/controllers/MessageController.js b/backend/src/controllers/MessageController.js index 472e5ed..e6053a7 100644 --- a/backend/src/controllers/MessageController.js +++ b/backend/src/controllers/MessageController.js @@ -1,64 +1,71 @@ const Message = require("../models/Message"); const Contact = require("../models/Contact"); +const Ticket = require("../models/Ticket"); const { getIO } = require("../libs/socket"); const { getWbot } = require("../libs/wbot"); const Sequelize = require("sequelize"); const { MessageMedia } = require("whatsapp-web.js"); -const setMessagesAsRead = async contactId => { +const setMessagesAsRead = async ticketId => { const io = getIO(); await Message.update( { read: true }, { where: { - contactId: contactId, + ticketId: ticketId, read: false, }, } ); - io.to("notification").emit("contact", { + io.to("notification").emit("ticket", { action: "updateUnread", - contactId: contactId, + ticketId: ticketId, }); }; exports.index = async (req, res, next) => { - const wbot = getWbot(); - const io = getIO(); + // const wbot = getWbot(); + // const io = getIO(); - const { contactId } = req.params; + const { ticketId } = req.params; const { searchParam = "", pageNumber = 1 } = req.query; - const lowerSerachParam = searchParam.toLowerCase(); - const whereCondition = { - messageBody: Sequelize.where( - Sequelize.fn("LOWER", Sequelize.col("messageBody")), + body: Sequelize.where( + Sequelize.fn("LOWER", Sequelize.col("body")), "LIKE", - "%" + lowerSerachParam + "%" + "%" + searchParam.toLowerCase() + "%" ), }; let limit = 20; let offset = limit * (pageNumber - 1); - const contact = await Contact.findByPk(contactId); - if (!contact) { - return res.status(400).json({ error: "No contact found with this ID" }); + const ticket = await Ticket.findByPk(ticketId, { + include: [ + { + model: Contact, + attributes: ["name", "number", "profilePicUrl"], + }, + ], + }); + + if (!ticket) { + return res.status(400).json({ error: "No ticket found with this ID" }); } - await setMessagesAsRead(contactId); + await setMessagesAsRead(ticketId); - const contactMessages = await contact.getMessages({ + const ticketMessages = await ticket.getMessages({ where: whereCondition, limit, offset, order: [["createdAt", "DESC"]], }); - const serializedMessages = contactMessages.map(message => { + const serializedMessages = ticketMessages.map(message => { return { ...message.dataValues, mediaUrl: `${ @@ -71,7 +78,8 @@ exports.index = async (req, res, next) => { return res.json({ messages: serializedMessages.reverse(), - contact: contact, + ticket: ticket, + contact: ticket.Contact, }); }; @@ -79,12 +87,20 @@ exports.store = async (req, res, next) => { const wbot = getWbot(); const io = getIO(); - const { contactId } = req.params; + const { ticketId } = req.params; const message = req.body; const media = req.file; let sentMessage; - const contact = await Contact.findByPk(contactId); + const ticket = await Ticket.findByPk(ticketId, { + include: [ + { + model: Contact, + attributes: ["number"], + }, + ], + }); + if (media) { const newMedia = MessageMedia.fromFilePath(req.file.path); message.mediaUrl = req.file.filename.replace(/\s/g, ""); @@ -94,17 +110,20 @@ exports.store = async (req, res, next) => { message.mediaType = "other"; } - sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, newMedia); + sentMessage = await wbot.sendMessage( + `${ticket.Contact.number}@c.us`, + newMedia + ); } else { sentMessage = await wbot.sendMessage( - `${contact.number}@c.us`, - message.messageBody + `${ticket.Contact.number}@c.us`, + message.body ); } message.id = sentMessage.id.id; - const newMessage = await contact.createMessage(message); + const newMessage = await ticket.createMessage(message); const serialziedMessage = { ...newMessage.dataValues, @@ -115,11 +134,12 @@ exports.store = async (req, res, next) => { }`, }; - io.to(contactId).emit("appMessage", { + io.to(ticketId).emit("appMessage", { action: "create", message: serialziedMessage, }); - await setMessagesAsRead(contactId); - return res.json({ message: "Mensagem enviada" }); + await setMessagesAsRead(ticketId); + + return res.json({ message: "Mensagem enviada", newMessage, ticket }); }; diff --git a/backend/src/controllers/TicketController.js b/backend/src/controllers/TicketController.js new file mode 100644 index 0000000..6154685 --- /dev/null +++ b/backend/src/controllers/TicketController.js @@ -0,0 +1,76 @@ +const Sequelize = require("sequelize"); + +const Ticket = require("../models/Ticket"); +const Contact = require("../models/Contact"); + +exports.index = async (req, res) => { + const tickets = await Ticket.findAll({ + include: [ + { + model: Contact, + attributes: ["name", "number", "profilePicUrl"], + }, + ], + attributes: { + include: [ + [ + Sequelize.literal(`( + SELECT COUNT(*) + FROM Messages AS message + WHERE + message.ticketId = Ticket.id + AND + message.read = 0 + + )`), + "unreadMessages", + ], + ], + }, + }); + + return res.json(tickets); +}; + +exports.store = async (req, res) => { + const ticket = await Ticket.create(req.body); + + res.status(200).json(ticket); +}; + +exports.update = async (req, res) => { + const { ticketId } = req.params; + + const ticket = await Ticket.findByPk(ticketId, { + include: [ + { + model: Contact, + attributes: ["name", "number", "profilePicUrl"], + }, + ], + attributes: { + include: [ + [ + Sequelize.literal(`( + SELECT COUNT(*) + FROM Messages AS message + WHERE + message.ticketId = Ticket.id + AND + message.read = 0 + + )`), + "unreadMessages", + ], + ], + }, + }); + + if (!ticket) { + return res.status(400).json({ error: "No ticket found with this ID" }); + } + + await ticket.update(req.body); + + res.status(200).json(ticket); +}; diff --git a/backend/src/controllers/WhatsAppSessionController.js b/backend/src/controllers/WhatsAppSessionController.js new file mode 100644 index 0000000..717302a --- /dev/null +++ b/backend/src/controllers/WhatsAppSessionController.js @@ -0,0 +1,23 @@ +const Whatsapp = require("../models/Whatsapp"); +// const { getIO } = require("../libs/socket"); +// const { getWbot, init } = require("../libs/wbot"); + +exports.show = async (req, res, next) => { + const { sessionId } = req.params; + const dbSession = await Whatsapp.findByPk(sessionId); + + if (!dbSession) { + return res.status(200).json({ message: "Session not found" }); + } + + return res.status(200).json(dbSession); +}; + +// exports.getContacts = async (req, res, next) => { +// const io = getIO(); +// const wbot = getWbot(); + +// const phoneContacts = await wbot.getContacts(); + +// return res.status(200).json(phoneContacts); +// }; diff --git a/backend/src/controllers/whatsapp.js b/backend/src/controllers/whatsapp.js deleted file mode 100644 index 6397c8e..0000000 --- a/backend/src/controllers/whatsapp.js +++ /dev/null @@ -1,22 +0,0 @@ -const Whatsapp = require("../models/Whatsapp"); -const { getIO } = require("../libs/socket"); -const { getWbot, init } = require("../libs/wbot"); - -exports.getSession = async (req, res, next) => { - const dbSession = await Whatsapp.findOne({ where: { id: 1 } }); - - if (!dbSession) { - return res.status(200).json({ message: "Session not found" }); - } - - return res.status(200).json(dbSession); -}; - -exports.getContacts = async (req, res, next) => { - const io = getIO(); - const wbot = getWbot(); - - const phoneContacts = await wbot.getContacts(); - - return res.status(200).json(phoneContacts); -}; diff --git a/backend/src/database/index.js b/backend/src/database/index.js index b2416d8..74c6d1d 100644 --- a/backend/src/database/index.js +++ b/backend/src/database/index.js @@ -2,8 +2,12 @@ const Sequelize = require("sequelize"); const dbConfig = require("../config/database"); const User = require("../models/User"); +const Contact = require("../models/Contact"); +const Ticket = require("../models/Ticket"); +const Message = require("../models/Message"); +const Whatsapp = require("../models/Whatsapp"); -const models = [User]; +const models = [User, Contact, Ticket, Message, Whatsapp]; class Database { constructor() { @@ -13,7 +17,9 @@ class Database { init() { this.sequelize = new Sequelize(dbConfig); - models.map(model => model.init(this.sequelize)); + models + .map(model => model.init(this.sequelize)) + .map(model => model.associate && model.associate(this.sequelize.models)); } } diff --git a/backend/src/database/migrations/20200717133438-create-users.js b/backend/src/database/migrations/20200717133438-create-users.js index 9685381..7c046a9 100644 --- a/backend/src/database/migrations/20200717133438-create-users.js +++ b/backend/src/database/migrations/20200717133438-create-users.js @@ -34,6 +34,6 @@ module.exports = { }, down: queryInterface => { - return queryInterface.dropTable("users"); + return queryInterface.dropTable("Users"); }, }; diff --git a/backend/src/database/migrations/20200717144403-create-contacts.js b/backend/src/database/migrations/20200717144403-create-contacts.js new file mode 100644 index 0000000..7ad2b4f --- /dev/null +++ b/backend/src/database/migrations/20200717144403-create-contacts.js @@ -0,0 +1,38 @@ +"use strict"; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable("Contacts", { + id: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false, + }, + name: { + type: Sequelize.STRING, + allowNull: false, + }, + number: { + type: Sequelize.STRING, + allowNull: false, + unique: true, + }, + profilePicUrl: { + type: Sequelize.STRING, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + }, + }); + }, + + down: queryInterface => { + return queryInterface.dropTable("Contacts"); + }, +}; diff --git a/backend/src/database/migrations/20200717145643-create-tickets.js b/backend/src/database/migrations/20200717145643-create-tickets.js new file mode 100644 index 0000000..81648e3 --- /dev/null +++ b/backend/src/database/migrations/20200717145643-create-tickets.js @@ -0,0 +1,46 @@ +"use strict"; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable("Tickets", { + id: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false, + }, + status: { + type: Sequelize.STRING, + defaultValue: "pending", + allowNull: false, + }, + lastMessage: { + type: Sequelize.STRING, + }, + contactId: { + type: Sequelize.INTEGER, + references: { model: "Contacts", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + }, + userId: { + type: Sequelize.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL", + }, + createdAt: { + type: Sequelize.DATE(6), + allowNull: false, + }, + updatedAt: { + type: Sequelize.DATE(6), + allowNull: false, + }, + }); + }, + + down: queryInterface => { + return queryInterface.dropTable("Tickets"); + }, +}; diff --git a/backend/src/database/migrations/20200717151645-create-messages.js b/backend/src/database/migrations/20200717151645-create-messages.js new file mode 100644 index 0000000..e410e41 --- /dev/null +++ b/backend/src/database/migrations/20200717151645-create-messages.js @@ -0,0 +1,58 @@ +"use strict"; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable("Messages", { + id: { + type: Sequelize.STRING, + primaryKey: true, + allowNull: false, + }, + body: { + type: Sequelize.TEXT, + allowNull: false, + }, + ack: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 0, + }, + read: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + mediaType: { + type: Sequelize.STRING, + }, + mediaUrl: { + type: Sequelize.STRING, + }, + userId: { + type: Sequelize.INTEGER, + references: { model: "Users", key: "id" }, + onUpdate: "CASCADE", + onDelete: "SET NULL", + }, + ticketId: { + type: Sequelize.INTEGER, + references: { model: "Tickets", key: "id" }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + allowNull: false, + }, + createdAt: { + type: Sequelize.DATE(6), + allowNull: false, + }, + updatedAt: { + type: Sequelize.DATE(6), + allowNull: false, + }, + }); + }, + + down: queryInterface => { + return queryInterface.dropTable("Messages"); + }, +}; diff --git a/backend/src/database/migrations/20200717170223-create-whatsapps.js b/backend/src/database/migrations/20200717170223-create-whatsapps.js new file mode 100644 index 0000000..d60e90e --- /dev/null +++ b/backend/src/database/migrations/20200717170223-create-whatsapps.js @@ -0,0 +1,41 @@ +"use strict"; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable("Whatsapps", { + id: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false, + }, + session: { + type: Sequelize.TEXT, + }, + qrcode: { + type: Sequelize.TEXT, + }, + status: { + type: Sequelize.STRING, + }, + battery: { + type: Sequelize.STRING, + }, + plugged: { + type: Sequelize.BOOLEAN, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + }, + }); + }, + + down: queryInterface => { + return queryInterface.dropTable("Whatsapps"); + }, +}; diff --git a/backend/src/models/Contact.js b/backend/src/models/Contact.js index 3eae5fb..aa6609b 100644 --- a/backend/src/models/Contact.js +++ b/backend/src/models/Contact.js @@ -1,19 +1,24 @@ const Sequelize = require("sequelize"); -const sequelize = require("../database"); +class Contact extends Sequelize.Model { + static init(sequelize) { + super.init( + { + name: { type: Sequelize.STRING }, + number: { type: Sequelize.STRING }, + profilePicUrl: { type: Sequelize.STRING }, + }, + { + sequelize, + } + ); -const Message = require("./Message"); + return this; + } -const Contact = sequelize.define("contact", { - name: { type: Sequelize.STRING(100), allowNull: false }, - number: { type: Sequelize.STRING(15), allowNull: false }, - profilePicUrl: { type: Sequelize.STRING(200) }, - lastMessage: { type: Sequelize.TEXT }, -}); - -Contact.hasMany(Message, { - onDelete: "CASCADE", - onUpdate: "RESTRICT", -}); + static associate(models) { + this.hasMany(models.Ticket, { foreignKey: "contactId" }); + } +} module.exports = Contact; diff --git a/backend/src/models/Message.js b/backend/src/models/Message.js index ea47387..af5e3e7 100644 --- a/backend/src/models/Message.js +++ b/backend/src/models/Message.js @@ -1,22 +1,27 @@ const Sequelize = require("sequelize"); -const sequelize = require("../database"); -const Message = sequelize.define("message", { - id: { - type: Sequelize.STRING(50), - allowNull: false, - primaryKey: true, - }, - createdAt: { - allowNull: false, - type: Sequelize.DATE(6), - }, - userId: { type: Sequelize.INTEGER, defaultValue: 0 }, - ack: { type: Sequelize.INTEGER, defaultValue: 0 }, - messageBody: { type: Sequelize.TEXT, allowNull: false }, - read: { type: Sequelize.BOOLEAN, defaultValue: false }, - mediaUrl: { type: Sequelize.STRING(250) }, - mediaType: { type: Sequelize.STRING(250) }, -}); +class Message extends Sequelize.Model { + static init(sequelize) { + super.init( + { + ack: { type: Sequelize.INTEGER, defaultValue: 0 }, + read: { type: Sequelize.BOOLEAN, defaultValue: false }, + body: { type: Sequelize.TEXT }, + mediaUrl: { type: Sequelize.STRING }, + mediaType: { type: Sequelize.STRING }, + }, + { + sequelize, + } + ); + + return this; + } + + static associate(models) { + this.belongsTo(models.Ticket, { foreignKey: "ticketId" }); + this.belongsTo(models.User, { foreignKey: "userId" }); + } +} module.exports = Message; diff --git a/backend/src/models/Ticket.js b/backend/src/models/Ticket.js new file mode 100644 index 0000000..5056dfd --- /dev/null +++ b/backend/src/models/Ticket.js @@ -0,0 +1,25 @@ +const Sequelize = require("sequelize"); + +class Ticket extends Sequelize.Model { + static init(sequelize) { + super.init( + { + status: { type: Sequelize.STRING, defaultValue: "pending" }, + lastMessage: { type: Sequelize.STRING }, + }, + { + sequelize, + } + ); + + return this; + } + + static associate(models) { + this.belongsTo(models.Contact, { foreignKey: "contactId" }); + this.belongsTo(models.User, { foreignKey: "userId" }); + this.hasMany(models.Message, { foreignKey: "ticketId" }); + } +} + +module.exports = Ticket; diff --git a/backend/src/models/Whatsapp.js b/backend/src/models/Whatsapp.js index fbb7d39..d60604a 100644 --- a/backend/src/models/Whatsapp.js +++ b/backend/src/models/Whatsapp.js @@ -1,13 +1,22 @@ const Sequelize = require("sequelize"); -const sequelize = require("../database"); +class Whatsapp extends Sequelize.Model { + static init(sequelize) { + super.init( + { + session: { type: Sequelize.TEXT }, + qrcode: { type: Sequelize.TEXT }, + status: { type: Sequelize.STRING }, + battery: { type: Sequelize.STRING }, + plugged: { type: Sequelize.BOOLEAN }, + }, + { + sequelize, + } + ); -const Whatsapp = sequelize.define("whatsapp", { - session: { type: Sequelize.TEXT() }, - qrcode: { type: Sequelize.TEXT() }, - status: { type: Sequelize.STRING(60) }, - battery: { type: Sequelize.STRING(20) }, - plugged: { type: Sequelize.BOOLEAN() }, -}); + return this; + } +} module.exports = Whatsapp; diff --git a/backend/src/routes/messages.js b/backend/src/routes/messages.js index dfb3811..0a88edc 100644 --- a/backend/src/routes/messages.js +++ b/backend/src/routes/messages.js @@ -5,8 +5,8 @@ const MessageController = require("../controllers/MessageController"); const routes = express.Router(); -routes.get("/messages/:contactId", isAuth, MessageController.index); +routes.get("/messages/:ticketId", isAuth, MessageController.index); -routes.post("/messages/:contactId", isAuth, MessageController.store); +routes.post("/messages/:ticketId", isAuth, MessageController.store); module.exports = routes; diff --git a/backend/src/routes/tickets.js b/backend/src/routes/tickets.js new file mode 100644 index 0000000..ba500e5 --- /dev/null +++ b/backend/src/routes/tickets.js @@ -0,0 +1,14 @@ +const express = require("express"); +const isAuth = require("../middleware/is-auth"); + +const TicketController = require("../controllers/TicketController"); + +const routes = express.Router(); + +routes.get("/tickets", isAuth, TicketController.index); + +routes.post("/tickets", isAuth, TicketController.store); + +routes.put("/tickets/:ticketId", isAuth, TicketController.update); + +module.exports = routes; diff --git a/backend/src/routes/whatsapp.js b/backend/src/routes/whatsapp.js index aea0d1f..ac8b232 100644 --- a/backend/src/routes/whatsapp.js +++ b/backend/src/routes/whatsapp.js @@ -1,12 +1,17 @@ const express = require("express"); const isAuth = require("../middleware/is-auth"); -const WhatsappController = require("../controllers/whatsapp"); +const WhatsAppSessionController = require("../controllers/WhatsAppSessionController"); const routes = express.Router(); -routes.get("/whatsapp/session", isAuth, WhatsappController.getSession); +routes.get( + "/whatsapp/session/:sessionId", + isAuth, + WhatsAppSessionController.show +); -routes.get("/whatsapp/contacts", isAuth, WhatsappController.getContacts); // fetch contacts in user cellphone, not in use +// fetch contacts in user cellphone, not in use +// routes.get("/whatsapp/contacts", isAuth, WhatsappController.getContacts); module.exports = routes;