From e754178d8dacd8d7736beb79e690df040603170e Mon Sep 17 00:00:00 2001 From: Landry Date: Wed, 14 Feb 2024 07:27:45 -0800 Subject: [PATCH] Refactor of api calls, removed db calls and unessary views --- index.js | 303 ++++++-------------- views/contacts.ejs | 14 - views/contacts/index.ejs | 24 -- views/messages/index.ejs | 69 ++++- views/opportunities/index.ejs | 0 views/partials/navbar.ejs | 69 ++--- views/properties.ejs | 14 - views/properties/index.ejs | 0 views/propertyContacts/index.ejs | 0 views/worktickets/index.ejs | 29 -- views/worktickets/show.ejs | 27 -- views/workticketvisits/index.ejs | 27 -- views/workticketvisits/show.ejs | 20 -- views/workticketvisits/workticketvisits.ejs | 33 --- 14 files changed, 172 insertions(+), 457 deletions(-) delete mode 100644 views/contacts.ejs delete mode 100644 views/contacts/index.ejs delete mode 100644 views/opportunities/index.ejs delete mode 100644 views/properties.ejs delete mode 100644 views/properties/index.ejs delete mode 100644 views/propertyContacts/index.ejs delete mode 100644 views/worktickets/index.ejs delete mode 100644 views/worktickets/show.ejs delete mode 100644 views/workticketvisits/index.ejs delete mode 100644 views/workticketvisits/show.ejs delete mode 100644 views/workticketvisits/workticketvisits.ejs diff --git a/index.js b/index.js index c01fc74..e262d8d 100644 --- a/index.js +++ b/index.js @@ -12,6 +12,7 @@ const PropertyModel = require('./models/property'); const PropertyContactModel = require('./models/propertyContact'); + require('dotenv').config(); @@ -25,18 +26,18 @@ const opportunity = require('./models/opportunity'); mongoose.connect('mongodb://127.0.0.1:27017/test') -.then(()=>{ - console.log("Connection Open") -}) -.catch(err =>{ - console.log("ERROR") - console.log(err) -}); + .then(() => { + console.log("Connection Open") + }) + .catch(err => { + console.log("ERROR") + console.log(err) + }); const db = mongoose.connection; db.on("error", console.error.bind(console, "connection error")); -db.once("open", ()=>{ +db.once("open", () => { console.log("Database connected"); }); @@ -52,15 +53,15 @@ sgMail.setApiKey(process.env.SENDGRID_API_KEY); app.use(express.static(path.join(__dirname, 'public'))) app.set('view engine', 'ejs'); -app.set('views', path.join(__dirname,'/views')); +app.set('views', path.join(__dirname, '/views')); //index route -app.get('/', (req, res)=>{ -res.render('home') +app.get('/', (req, res) => { + res.render('home') }) //POST Authorize route to gain access -app.post('/authorize', async (req, res)=>{ +app.post('/authorize', async (req, res) => { try { const { ASPIRE_API_CLIENT_ID, ASPIRE_API_SECRET_KEY } = process.env; const tokenUrl = 'https://cloud-api.youraspire.com/Authorization'; @@ -77,228 +78,104 @@ app.post('/authorize', async (req, res)=>{ } }); -//WORK TICKET VISIT ROUTES -// api GET WORK TICKET VISITS -app.get('/api/workticketvisits', async (req, res) => { +/**** MESSAGING FEATURE ROUTES ****/ +app.get('/data-for-messages', async (req, res) => { try { - const { ASPIRE_API_CLIENT_ID, ASPIRE_TOKEN, ASPIRE_REFRESH_TOKEN } = process.env; - const apiUrl = `https://cloud-api.youraspire.com/WorkTicketVisits?%24select=WorkTicketVisitID%2CWorkTicketID%2CScheduledDate&%24filter=ScheduledDate%20gt%202024-01-29`; - const headers = { - 'Authorization': `Bearer ${ASPIRE_TOKEN }`, - 'Client-ID': ASPIRE_API_CLIENT_ID, - 'Content-Type': 'application/json', - }; - const response = await axios.get(apiUrl, { headers }); - const workticketvisits = response.data; - //save to database before going to client - // therefore logic to have databse filter logic beofre going to client - - res.render('./workticketvisits', { workticketvisits }); - - } catch (error) { - res.status(500).json({ error: error.message }); - } -}); - -//API - GET - WORK TICKETS -app.get('/api/worktickets', async (req, res) => { - try { - const { ASPIRE_API_CLIENT_ID, ASPIRE_TOKEN, ASPIRE_REFRESH_TOKEN } = process.env; - const apiUrl = `https://cloud-api.youraspire.com/WorkTickets`; - - - const headers = { - 'Authorization': `Bearer ${ASPIRE_TOKEN }`, - 'Client-ID': ASPIRE_API_CLIENT_ID, - 'Content-Type': 'application/json', - }; - - - const response = await axios.get(apiUrl, { headers }); - const workTickets = response.data; - // await tickets.save(); - res.json({ workTickets }); - } catch (error) { - res.status(500).json({ error: error.message }); - } -}); - -// GET ALL OPPORTUNITIES -app.get('/api/opportunities', async (req, res) => { - try { - const { ASPIRE_API_CLIENT_ID, ASPIRE_TOKEN, ASPIRE_REFRESH_TOKEN } = process.env; - const apiUrl = `https://cloud-api.youraspire.com/opportunities`; - const headers = { - 'Authorization': `Bearer ${ASPIRE_TOKEN}`, - 'Client-ID': ASPIRE_API_CLIENT_ID, - 'Content-Type': 'application/json', - }; - const response = await axios.get(apiUrl, { headers }); - const opportunities = response.data; - // await tickets.save(); - res.json({ opportunities }); - } catch (error) { - res.status(500).json({ error: error.message }); - } -}); - -//INDEX - GET ALL customer contacts -app.get('api/contacts', async (req, res) => { - try { - const { ASPIRE_API_CLIENT_ID, ASPIRE_API_SECRET_KEY, ASPIRE_TOKEN, ASPIRE_REFRESH_TOKEN } = process.env; - - // Implement logic to fetch appointment data using Axios and API keys - const apiUrl = `https://cloud-api.youraspire.com/Contacts?$filter=ContactTypeName eq 'Customer' and LastName ne 'Employee'&$select=FirstName,LastName,Email,CompanyName`; // Replace with the actual API endpoint - const headers = { - 'Authorization': `Bearer ${ASPIRE_TOKEN}`, - 'Client-ID': ASPIRE_API_CLIENT_ID, - 'Content-Type': 'application/json', - }; - - const response = await axios.get(apiUrl, { headers }); - - const contacts = response.data; // Assuming the response directly provides contacts - - - res.render('contacts', { contacts }); - - } catch (error) { - res.status(500).json({ error: error.message }); - } -}); -//INDEX - GET ALL PROPERTIES -app.get('/api/properties', async (req, res) => { - try { const { ASPIRE_API_CLIENT_ID, ASPIRE_API_SECRET_KEY, ASPIRE_TOKEN } = process.env; - - // Implement logic to fetch appointment data using Axios and API keys - const apiUrl = `https://cloud-api.youraspire.com/properties`; // Replace with the actual API endpoint + //Specific api routes with details needed + const apiPropertyUrl = `https://cloud-api.youraspire.com/Properties?%24select=PropertyID%2CSequenceNumber%2CPropertyName%2CPropertyAddressLine1%2CPropertyAddressLine2%2CPropertyAddressCity%2CPropertyAddressStateProvinceCode%2CPropertyAddressZipCode%2CBranchName`; + const apiPropertyContactUrl = `https://cloud-api.youraspire.com/PropertyContacts?%24select=ContactID%2CPropertyID`; + const apiContactUrl = `https://cloud-api.youraspire.com/Contacts?%24select=ContactID%2CEmail%2CMobilePhone%2CNotes%2CFirstName%2CLastName`; const headers = { 'Authorization': `Bearer ${ASPIRE_TOKEN}`, 'Client-ID': ASPIRE_API_CLIENT_ID, 'Content-Type': 'application/json', }; - const response = await axios.get(apiUrl, { headers }); +//VARIABLES to capture needed data + const responseProperty = await axios.get(apiPropertyUrl, { headers }); + const responsePropertyContact = await axios.get(apiPropertyContactUrl, { headers }); + const responseContact = await axios.get(apiContactUrl, { headers }); + const propertyData = responseProperty.data; + const propertyContactData = responsePropertyContact.data; + const contactData = responseContact.data; - const properties = response.data; // Assuming the response directly provides properties - - res.render('properties', { properties }); - } catch (error) { - res.status(500).json({ error: error.message }); - } -}); - - -// DB -GET - WORK TICKET VISIT INDEX -app.get('/db/workticketvisits', async (req, res) => { - const visits = await WorkTicketVisitModel.find({}) - res.render('./workticketvisits/index', { visits }) -}); -//DB - SHOW WORKTICKETVISIT/:ID -app.get('/db/workticketvisit/:id', async (req, res) => { - const visit = await WorkTicketVisitModel.findById(req.params.id) - res.render('./workticketvisits/show', { visit }) -}); - -// DB -GET - WORK TICKET INDEX -app.get('/db/worktickets', async (req, res) => { - const tickets = await WorkTicketModel.find({}) - res.render('worktickets/index', { tickets }) -}); -//DB - SHOW WORKTICKET/:ID -app.get('/db/worktickets/:id', async (req, res) => { - const ticket = await WorkTicketModel.findById(req.params.id) - - res.render('./worktickets/show', { ticket }); -}); - -//DB - INDEX GET ALL contacts -app.get('/db/contacts', async (req, res) => { - const contacts = await ContactModel.find({}) - res.render('./contacts/index', {contacts }); -}); - - - -/**** MESSAGING FEATURE ROUTE ****/ -app.get('/messages', async (req, res)=>{ - try { - const contacts = await ContactModel.find({}); - - const propertyContacts = await PropertyContactModel.find({}); - - const properties = await PropertyModel.find({}); - - const opportunities = await OpportunityModel.find({}); - const worktickets = await WorkTicketModel.find({}); - const workVisits = await WorkTicketVisitModel.find({}); - - const filteredContacts = workVisits.filter(visit => { - return worktickets.some(ticket => ticket.WorkTicketID === visit.WorkTicketID ); - }).filter(opportunity => { - - return opportunities.some(wonOpportunity => wonOpportunity.OpportunityID === ticket.OpportunityID && opportunity.OpportunityStatusName === "won"); - }).filter(propertyContact => { - - return propertyContacts.some(propContact => propContact.PropertyID === wonOpportunity.PropertyID ); - }); - - - - res.render('./messages/index', { - filteredContacts, - // Include other filtered data in the render object - }); - } catch (error) { - res.status(500).json({ error: error.message }); - } -}) - - -//SendGrid TEST - Navigation will need emails to employee contacts in apsire. -app.get('/test', async (req, res) => { - try { - const { ASPIRE_API_CLIENT_ID, ASPIRE_TOKEN, SENDGRID_API_KEY } = process.env; - - - // Implement logic to fetch appointment data using Axios and API keys - const apiUrl = `https://cloud-api.youraspire.com/Contacts?$filter=ContactTypeName eq 'Employee' and LastName ne 'Employee'&$select=FirstName,LastName,Email,CompanyName,Salutation`; // Replace with the actual API endpoint - const headers = { - 'Authorization': `Bearer ${ASPIRE_TOKEN}`, - 'Client-ID': ASPIRE_API_CLIENT_ID, - 'Content-Type': 'application/json', + // Function to connect propertyData to propertyContactData based on PropertyID and connect propertyContactData to contactData based on ContactID + const connectPropertyToContact = property => { + const propertyID = property.PropertyID; + const propertyContacts = propertyContactData.filter(contact => contact.PropertyID === propertyID); + return propertyContacts.map(contact => { + const contactID = contact.ContactID; + const contactDetails = contactData.find(c => c.ContactID === contactID); + return { + ...contact, + contactDetails + }; + }); }; - const response = await axios.get(apiUrl, { headers }); + // Mapping propertyData to connect to contactData + const connectedData = propertyData.map(property => ({ + ...property, + contacts: connectPropertyToContact(property) + })); - const contacts = response.data; - // Assuming the response directly provides contacts + - // Send personalized emails using SendGrid for each contact retrieved -const sgMail = require('@sendgrid/mail'); -sgMail.setApiKey(SENDGRID_API_KEY); - - contacts.forEach(async (contact) => { - const msg = { - to: contact.Email, - from: 'info@sprinklersnorthwest.com', - subject: 'Bulk Email To Employee Contacts', // Set a subject for the email - text: `Hi ${contact.FirstName} ${contact.LastName} of ${contact.CompanyName}, This is an bulk email test to confirm I have pulled contact data from the Aspire API and sent it through sendGrid if this is received please respond to my email landry@shilocode.com when possible thank you Landry-Developer-Shiloh Code`, - html: `Hi ${contact.FirstName} ${contact.LastName} of ${contact.CompanyName}, This is an bulk email test to confirm I have pulled contact data from the Aspire API and sent it through sendGrid if this is received please respond to my email landry@shilocode.com when possible thank you Landry-Developer-Shiloh Code`, - }; - - await sgMail.send(msg); - }); + res.render('./messages/index', { connectedData }); - res.json({ message: 'Emails sent successfully!' }); } catch (error) { res.status(500).json({ error: error.message }); } }); + + +//DONT USE THIS +//SendGrid TEST - Navigation will need emails to employee contacts in apsire. +// app.get('/test', async (req, res) => { +// try { +// const { ASPIRE_API_CLIENT_ID, ASPIRE_TOKEN, SENDGRID_API_KEY } = process.env; + + +// // Implement logic to fetch appointment data using Axios and API keys +// const apiUrl = `https://cloud-api.youraspire.com/Contacts?$filter=ContactTypeName eq 'Employee' and LastName ne 'Employee'&$select=FirstName,LastName,Email,CompanyName,Salutation`; // Replace with the actual API endpoint +// const headers = { +// 'Authorization': `Bearer ${ASPIRE_TOKEN}`, +// 'Client-ID': ASPIRE_API_CLIENT_ID, +// 'Content-Type': 'application/json', +// }; + +// const response = await axios.get(apiUrl, { headers }); + +// const contacts = response.data; +// // Assuming the response directly provides contacts + +// // Send personalized emails using SendGrid for each contact retrieved +// const sgMail = require('@sendgrid/mail'); +// sgMail.setApiKey(SENDGRID_API_KEY); + +// contacts.forEach(async (contact) => { +// const msg = { +// to: contact.Email, +// from: 'info@sprinklersnorthwest.com', +// subject: 'Bulk Email To Employee Contacts', // Set a subject for the email +// text: `Hi ${contact.FirstName} ${contact.LastName} of ${contact.CompanyName}, This is an bulk email test to confirm I have pulled contact data from the Aspire API and sent it through sendGrid if this is received please respond to my email landry@shilocode.com when possible thank you Landry-Developer-Shiloh Code`, +// html: `Hi ${contact.FirstName} ${contact.LastName} of ${contact.CompanyName}, This is an bulk email test to confirm I have pulled contact data from the Aspire API and sent it through sendGrid if this is received please respond to my email landry@shilocode.com when possible thank you Landry-Developer-Shiloh Code`, +// }; + +// await sgMail.send(msg); +// }); + +// res.json({ message: 'Emails sent successfully!' }); +// } catch (error) { +// res.status(500).json({ error: error.message }); +// } +// }); + + app.listen(port, () => { console.log(`Server is running on port ${port}`); }); diff --git a/views/contacts.ejs b/views/contacts.ejs deleted file mode 100644 index 9a8f140..0000000 --- a/views/contacts.ejs +++ /dev/null @@ -1,14 +0,0 @@ -<%- include('partials/head') -%> - - <%- include ('partials/navbar') %> - -

Contacts

- - -<%- include ('partials/footer') %> \ No newline at end of file diff --git a/views/contacts/index.ejs b/views/contacts/index.ejs deleted file mode 100644 index 3623e18..0000000 --- a/views/contacts/index.ejs +++ /dev/null @@ -1,24 +0,0 @@ -<%- include('../partials/head') %> - - <%- include ('../partials/navbar') %> -

Contacts

- - - - - -<%- include ('../partials/footer') %> \ No newline at end of file diff --git a/views/messages/index.ejs b/views/messages/index.ejs index 4e943e1..10f61ab 100644 --- a/views/messages/index.ejs +++ b/views/messages/index.ejs @@ -1,17 +1,60 @@ -<%- include('../partials/head') -%> +<%- include('../partials/head') -%> <%- include ('../partials/navbar') %> - <%- include ('../partials/navbar') %> - - +

Filtered Property and Contact Data

- -

Filtered Contacts

- -<%- include ('../partials/footer') %> \ No newline at end of file +
+ + + + + + + + + + + + + + + + + + + + + <% connectedData.forEach(property => { %> + <% property.contacts.forEach(contact => { %> + + + + + + + + + + + + + + + + + <% }); %> + <% }); %> + +
Property IDProperty NameBranch NameSequence Number - DateProperty AddressContact IDFirst NameLast NameContact EmailMobile Phone
<%= property.PropertyID %><%= property.PropertyName %><%= property.BranchName %><%= property.SequenceNumber %> + <%= property.PropertyAddressLine1 %>
+ <%= property.PropertyAddressLine2 %> + <%= property.PropertyAddressCity%> + <%= property.PropertyAddressStateProvinceCode %> + <%= property.PropertyAddressZipCode %> + + +
<%= contact.ContactID %><%= contact.contactDetails.FirstName %><%= contact.contactDetails.LastName %><%= contact.contactDetails.Email %><%= contact.contactDetails.MobilePhone %>
+
+ +<%- include ('../partials/footer') %> diff --git a/views/opportunities/index.ejs b/views/opportunities/index.ejs deleted file mode 100644 index e69de29..0000000 diff --git a/views/partials/navbar.ejs b/views/partials/navbar.ejs index 9e35774..9a1907e 100644 --- a/views/partials/navbar.ejs +++ b/views/partials/navbar.ejs @@ -1,45 +1,28 @@ \ No newline at end of file + + diff --git a/views/properties.ejs b/views/properties.ejs deleted file mode 100644 index a6eac8f..0000000 --- a/views/properties.ejs +++ /dev/null @@ -1,14 +0,0 @@ -<%- include('partials/head') -%> - - <%- include ('partials/navbar') %> - -

properties

- - -<%- include ('partials/footer') %> \ No newline at end of file diff --git a/views/properties/index.ejs b/views/properties/index.ejs deleted file mode 100644 index e69de29..0000000 diff --git a/views/propertyContacts/index.ejs b/views/propertyContacts/index.ejs deleted file mode 100644 index e69de29..0000000 diff --git a/views/worktickets/index.ejs b/views/worktickets/index.ejs deleted file mode 100644 index 8797206..0000000 --- a/views/worktickets/index.ejs +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - work ticket indes - - -

Work Tickets

- - - - - - - - - - - - \ No newline at end of file diff --git a/views/worktickets/show.ejs b/views/worktickets/show.ejs deleted file mode 100644 index c9aa019..0000000 --- a/views/worktickets/show.ejs +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - work ticket show - - -

Show work ticket details

-

- Ticket ID - <%= ticket.WorkTicketID %> -

-

-status -<%= ticket.WorkTicketStatusName %> -

- -

- <%= ticket.SceduledStartDate %> -

- - - - - - \ No newline at end of file diff --git a/views/workticketvisits/index.ejs b/views/workticketvisits/index.ejs deleted file mode 100644 index 7d0ad29..0000000 --- a/views/workticketvisits/index.ejs +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - work ticket index - - - -

Work Ticket Visits

- - - - - - - \ No newline at end of file diff --git a/views/workticketvisits/show.ejs b/views/workticketvisits/show.ejs deleted file mode 100644 index d49a8e1..0000000 --- a/views/workticketvisits/show.ejs +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - SHOW work ticket visits - - - -

Vistit ID - <%= visit.WorkTicketVisitID %>

- -

<%= visit.RouteName %>

-

<%= visit.WorkTicketID %>

- - - - - \ No newline at end of file diff --git a/views/workticketvisits/workticketvisits.ejs b/views/workticketvisits/workticketvisits.ejs deleted file mode 100644 index 07e7f8e..0000000 --- a/views/workticketvisits/workticketvisits.ejs +++ /dev/null @@ -1,33 +0,0 @@ -<%- include('/partials/head') %> - - <%- include ('partials/navbar') %> -

Work Ticket Visits

- - - - - - - - - - - - - <% for (let i=0; i < workticketvisits.length; i++) { %> - - - - - - <% } %> - -
#Work Ticket IDScheduled Date
- <%= i + 1 %> - - <%= workticketvisits[i].WorkTicketID %> - - <%= workticketvisits[i].ScheduledDate %> -
- - <%- include ('partials/footer') %> \ No newline at end of file