diff --git a/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx b/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx index b2c746fae..544eeacbf 100644 --- a/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx +++ b/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx @@ -4,6 +4,8 @@ import { useTranslation } from "react-i18next"; import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; import ScheduleDayViewContainer from "../schedule-day-view/schedule-day-view.container"; import ScheduleExistingAppointmentsList from "../schedule-existing-appointments-list/schedule-existing-appointments-list.component"; +import axios from "axios"; +import { auth } from "../../firebase/firebase.utils"; export default function ScheduleJobModalComponent({ existingAppointments, @@ -13,18 +15,37 @@ export default function ScheduleJobModalComponent({ setFormData, }) { const { t } = useTranslation(); + + const handleAuto = async () => { + try { + const response = await axios.post( + "/scheduling/job", + { jobId: "661dd1d5-bf06-426f-8bd2-bd9e41de8eb1" }, + { + headers: { + Authorization: `Bearer ${await auth.currentUser.getIdToken(true)}`, + }, + } + ); + console.log("response", response); + } catch (error) { + console.log("error", error, error.message); + } + }; + //TODO Existing appointments list only refreshes sometimes after modal close. May have to do with the container class. return ( - - + + Automatic Job Selection. + - + Manual Job Selection Scheduled Time -
+
{ @@ -45,7 +66,8 @@ export default function ScheduleJobModalComponent({ defaultChecked={formData.notifyCustomer} onChange={(e) => setFormData({ ...formData, notifyCustomer: e.target.checked }) - }> + } + > {t("jobs.labels.appointmentconfirmation")} diff --git a/server.js b/server.js index 43dad4574..ebd32b252 100644 --- a/server.js +++ b/server.js @@ -69,6 +69,10 @@ app.post( smsStatus.status ); +//Scheduling +var scheduling = require("./server/scheduling/scheduling-job"); +app.post("/scheduling/job", scheduling.job); + //Handlebars Paths for Email/Report Rendering var renderHandlebars = require("./server/render/renderHandlebars"); app.post("/render", renderHandlebars.render); diff --git a/server/accounting/qbxml/qbxml-receivables.js b/server/accounting/qbxml/qbxml-receivables.js index 1c16f5da7..ba640572a 100644 --- a/server/accounting/qbxml/qbxml-receivables.js +++ b/server/accounting/qbxml/qbxml-receivables.js @@ -32,6 +32,8 @@ exports.default = async (req, res) => { //Is this a two tier, or 3 tier setup? const isThreeTier = bodyshop.accountingconfig.tiers === 3; + const twoTierPref = bodyshop.accountingconfig.twotierpref; + if (isThreeTier) { QbXmlToExecute.push({ id: jobId, @@ -43,13 +45,25 @@ exports.default = async (req, res) => { QbXmlToExecute.push({ id: jobId, okStatusCodes: ["0", "3100"], - qbxml: generateJobQbxml(jobs_by_pk, bodyshop, isThreeTier, 2), + qbxml: generateJobQbxml( + jobs_by_pk, + bodyshop, + isThreeTier, + 2, + twoTierPref + ), }); QbXmlToExecute.push({ id: jobId, okStatusCodes: ["0", "3100"], - qbxml: generateJobQbxml(jobs_by_pk, bodyshop, isThreeTier, 3), + qbxml: generateJobQbxml( + jobs_by_pk, + bodyshop, + isThreeTier, + 3, + twoTierPref + ), }); //Generate the actual invoice. QbXmlToExecute.push({ @@ -115,7 +129,7 @@ const generateOwnerTier = (jobs_by_pk) => { }`; }; -const generateJobQbxml = (jobs_by_pk, bodyshop, isThreeTier, tierLevel) => { +const generateJobQbxml = (jobs_by_pk, bodyshop, isThreeTier, tierLevel, twoTierPref) => { let Name; let ParentRefName; diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 5216760d0..ccc679f26 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -108,3 +108,23 @@ query QUERY_INVOICES_FOR_PAYABLES_EXPORT($invoices: [uuid!]!) { } `; + +exports.QUERY_UPCOMING_APPOINTMENTS = ` + query QUERY_UPCOMING_APPOINTMENTS($now: timestamptz!) { + appointments(where: {start: {_gt: $now}}) { + start + isintake + id + job { + joblines_aggregate { + aggregate { + sum { + mod_lb_hrs + } + } + } + } + } + } + + `; diff --git a/server/scheduling/scheduling-job.js b/server/scheduling/scheduling-job.js new file mode 100644 index 000000000..a164d2f29 --- /dev/null +++ b/server/scheduling/scheduling-job.js @@ -0,0 +1,47 @@ +const GraphQLClient = require("graphql-request").GraphQLClient; +const path = require("path"); +const queries = require("../graphql-client/queries"); +const Dinero = require("dinero.js"); + +require("dotenv").config({ + path: path.resolve( + process.cwd(), + `.env.${process.env.NODE_ENV || "development"}` + ), +}); + +exports.job = async (req, res) => { + try { + const BearerToken = req.headers.authorization; + const { jobId } = req.body; + console.log("exports.job -> jobId", jobId); + + const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, { + headers: { + Authorization: BearerToken, + }, + }); + + const result = await client + .setHeaders({ Authorization: BearerToken }) + .request(queries.QUERY_UPCOMING_APPOINTMENTS, { + now: new Date(), + }); + + const possibleDates = []; + + //Temp + possibleDates.push(new Date()); + possibleDates.push(new Date()); + possibleDates.push(new Date()); + possibleDates.push(new Date()); + possibleDates.push(new Date()); + //Get a list of upcoming appointments + //Get the config for each day + + res.json(possibleDates); + } catch (error) { + console.log("error", error); + res.status(400).send(error); + } +};