From ca048d4f4b2256283502924a72b8ca544669abbf Mon Sep 17 00:00:00 2001 From: Anson He Date: Mon, 1 Jan 2024 17:18:35 -0500 Subject: [PATCH 1/3] Add READY_FOR_PICKUP UPR status and misc refactors/bugfixes --- backend/emails/emails.js | 28 ++++++- backend/models/constants.js | 4 +- backend/service/uwfinancepurchases.service.js | 8 ++ frontend/src/components/ConfirmationModal.js | 11 +-- .../TicketContent/SFAdminContentTable.js | 76 +++++++++---------- .../TicketContent/UPRAdminContentTable.js | 43 ++++++++++- frontend/src/hooks/hooks.js | 4 +- 7 files changed, 119 insertions(+), 55 deletions(-) diff --git a/backend/emails/emails.js b/backend/emails/emails.js index 0264de0..77acdac 100644 --- a/backend/emails/emails.js +++ b/backend/emails/emails.js @@ -174,7 +174,7 @@ const sendEmailUPRPurchasedToReporter = async (upr) => { `Your UW Finance Purchase Request has been purchased! When the item is ready to be picked up, we will let you know.` ) + (await getUPRTicketInfoHTML(upr)) + - +getTicketLinkHTML(upr.path) + getTicketLinkHTML(upr.path) const To = await getEmailToSection(upr.reporter_id, [ EMAIL_RECIPIENTS.reporter, ]) @@ -205,6 +205,25 @@ const sendEmailUPRPurchasedToCoordinator = async (upr) => { }) } +const sendEmailUPRReadyForPickupToCoordinator = async (upr) => { + const Subject = `[Ready for pickup] ${upr.codename}` + const HTMLPart = + getMainMessageHTML( + 'Your UW Finance Request is ready to be picked up! Please view the ticket below for pickup instructions and confirm when you have picked it up.' + ) + + (await getUPRTicketInfoHTML(upr)) + + getTicketLinkHTML(upr.path) + const To = await getEmailToSection(upr.reporter_id, [ + EMAIL_RECIPIENTS.reporter, + ]) + + await sendEmail({ + Subject, + HTMLPart, + To, + }) +} + const sendEmailPPRApprovedToReporter = async (ppr) => { const Subject = `[Ready to Buy] ${ppr.codename}` const HTMLPart = @@ -287,7 +306,7 @@ const sendEmailSFReimbursementRequestToCoordinator = async (sf) => { const Subject = `[Action Needed] Submit Reimbursement Request ${sf.codename}` const HTMLPart = getMainMessageHTML( - `Claim has been submitted for ${sf.codename}! Please review it and submit a reimbursement request. Visit the ticket link below to confirm you have submitted the reimbursement request.` + `Please review the claim and submit a reimbursement request for ${sf.codename}. Once submitted, please visit the ticket link below to confirm that you have submitted it.` ) + (await getSFTicketInfoHTML(sf)) + getTicketLinkHTML(sf.path) @@ -305,7 +324,7 @@ const sendEmailSFConfirmReimbursementSubmitToCoordinator = async (sf) => { const Subject = `[Action Needed] Confirm Reimbursement Received ${sf.codename}` const HTMLPart = getMainMessageHTML( - `Please visit the ticket link below to confirm you have received the reimbursement for ${sf.codename}.` + `Once the sponsorship fund for ${sf.codename} has reimbursed us, please visit the ticket link below to confirm it.` ) + (await getSFTicketInfoHTML(sf)) + getTicketLinkHTML(sf.path) @@ -322,7 +341,7 @@ const sendEmailSFConfirmReimbursementSubmitToCoordinator = async (sf) => { const sendEmailSFReimbursementReceivedToTeam = async (sf) => { const Subject = `[Reimbursed] ${sf.codename}` const HTMLPart = - getMainMessageHTML(`${sf.codename} has been reimbursed.`) + + getMainMessageHTML(`${sf.codename} has been reimbursed!`) + (await getSFTicketInfoHTML(sf)) + getTicketLinkHTML(sf.path) const To = await getEmailToSection(sf.reporter_id, [ @@ -662,6 +681,7 @@ module.exports = { sendEmailUPRApprovedToCoordinator, sendEmailUPRPurchasedToReporter, sendEmailUPRPurchasedToCoordinator, + sendEmailUPRReadyForPickupToCoordinator, sendEmailPPRApprovedToReporter, sendEmailPPRCreatedToApprovers, sendEmailPPRPurchasedAndReceiptsSubmittedToCoordinator, diff --git a/backend/models/constants.js b/backend/models/constants.js index 9af68f8..6230073 100644 --- a/backend/models/constants.js +++ b/backend/models/constants.js @@ -20,10 +20,10 @@ const UPR_STATUS = [ 'SEEKING_APPROVAL', 'SENT_TO_COORDINATOR', 'ORDERED', + 'READY_FOR_PICKUP', 'PICKED_UP', ] - -const UPR_STATUS_FUNDING_SPENT = ['ORDERED', 'PICKED_UP'] +const UPR_STATUS_FUNDING_SPENT = ['ORDERED', 'READY_FOR_PICKUP', 'PICKED_UP'] const APPROVAL_LEVELS = Object.freeze({ director_approval: 'director_approval', diff --git a/backend/service/uwfinancepurchases.service.js b/backend/service/uwfinancepurchases.service.js index 66e1969..1c7c7ae 100644 --- a/backend/service/uwfinancepurchases.service.js +++ b/backend/service/uwfinancepurchases.service.js @@ -9,6 +9,7 @@ const { sendEmailUPRApprovedToCoordinator, sendEmailUPRPurchasedToCoordinator, sendEmailUPRPurchasedToReporter, + sendEmailUPRReadyForPickupToCoordinator, } = require('../emails/emails') const getAllUWFinancePurchases = () => { @@ -53,6 +54,13 @@ const updateUWFinancePurchase = async (id, body) => { ] await Promise.all(emails) } + if ( + existingPurchaseTicket.status === 'ORDERED' && + body.status === 'READY_FOR_PICKUP' + ) { + const annotatedUPR = await getUWFinancePurchase(id) + await sendEmailUPRReadyForPickupToCoordinator(annotatedUPR) + } return newPurchaseTicket } diff --git a/frontend/src/components/ConfirmationModal.js b/frontend/src/components/ConfirmationModal.js index 7bd7720..7ab4b61 100644 --- a/frontend/src/components/ConfirmationModal.js +++ b/frontend/src/components/ConfirmationModal.js @@ -9,19 +9,14 @@ import { Button, } from '@chakra-ui/react' -const ConfirmationModal = ({ onConfirm, isOpen, onClose }) => { +const ConfirmationModal = ({ title, body, onConfirm, isOpen, onClose }) => { return ( - Submission (Placeholder) + {title} - -
- Are you sure you want to submit this, you cant undo bla - bla bla (PLACEHOLDER) -
-
+ {body} )} {/* can remove getPreserveParamsHref if it does not make sense to preserve params */} diff --git a/frontend/src/components/TicketContent/UPRAdminContentTable.js b/frontend/src/components/TicketContent/UPRAdminContentTable.js index 7068d5f..0fea8df 100644 --- a/frontend/src/components/TicketContent/UPRAdminContentTable.js +++ b/frontend/src/components/TicketContent/UPRAdminContentTable.js @@ -1,5 +1,6 @@ import { Button, Center, Heading, Table, Tbody, VStack } from '@chakra-ui/react' -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' +import { useLocation } from 'react-router-dom' import { useSetRecoilState } from 'recoil' import TicketContentTableRow from './TicketContentTableRow' import { allTicketsState } from '../../state/atoms' @@ -9,6 +10,7 @@ import { getAllTickets } from '../../utils/globalSetters' import { useGetCurrentTicket } from '../../hooks/hooks' const UPRAdminContentTable = () => { + const location = useLocation() const currentTicket = useGetCurrentTicket() const [reqNum, setReqNum] = useState(currentTicket.requisition_number) const [poNum, setPoNum] = useState(currentTicket.po_number) @@ -23,6 +25,23 @@ const UPRAdminContentTable = () => { setChanged(true) } + useEffect(() => { + if (!currentTicket.requisition_number) { + setReqNum('') + } else { + setReqNum(currentTicket.requisition_number) + } + if (!currentTicket.po_number) { + setPoNum('') + } else { + setPoNum(currentTicket.po_number) + } + }, [ + location.pathname, + currentTicket.requisition_number, + currentTicket.po_number, + ]) + const saveFields = async () => { const payload = { requisition_number: reqNum, @@ -50,6 +69,18 @@ const UPRAdminContentTable = () => { setChanged(false) } + const transitionToReadyForPickup = async () => { + const payload = { + status: 'READY_FOR_PICKUP', + } + await axiosPreset.patch( + `${TICKET_ENDPOINTS.UPR}/${currentTicket._id}`, + payload + ) + await getAllTickets(setAllTickets) + setChanged(false) + } + const transitionToPickedUp = async () => { const payload = { status: 'PICKED_UP', @@ -98,6 +129,16 @@ const UPRAdminContentTable = () => { )} {currentTicket.status === 'ORDERED' && ( + + )} + {currentTicket.status === 'READY_FOR_PICKUP' && (