From a57156756e927fade89ac6f04752a7784d84937c Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 28 Oct 2024 11:03:30 -0700 Subject: [PATCH 01/12] feature/IO-2979-DST - Normalize usages of dayjs to dayjs not day, move locale hook Signed-off-by: Dave Richer --- client/src/App/App.container.jsx | 4 ---- client/src/components/eula/eula.component.jsx | 4 ++-- .../job-lifecycle/job-lifecycle.component.jsx | 6 +++--- .../job-line-dispatch-button.component.jsx | 10 +++++++--- .../parts-dispatch-expander.component.jsx | 4 ++-- .../time-tickets-commit-toggle.component.jsx | 4 ++-- .../time-tickets-commit.component.jsx | 6 +++--- .../tt-approve-button/tt-approve-button.component.jsx | 4 ++-- client/src/redux/user/user.sagas.js | 7 +++---- client/src/utils/day.js | 3 +++ 10 files changed, 27 insertions(+), 25 deletions(-) diff --git a/client/src/App/App.container.jsx b/client/src/App/App.container.jsx index e4df37c61..d6f3a53fd 100644 --- a/client/src/App/App.container.jsx +++ b/client/src/App/App.container.jsx @@ -2,8 +2,6 @@ import { ApolloProvider } from "@apollo/client"; import { SplitFactoryProvider, SplitSdk } from "@splitsoftware/splitio-react"; import { ConfigProvider } from "antd"; import enLocale from "antd/es/locale/en_US"; -import dayjs from "../utils/day"; -import "dayjs/locale/en"; import React from "react"; import { useTranslation } from "react-i18next"; import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component"; @@ -19,8 +17,6 @@ if (import.meta.env.DEV) { Userpilot.initialize("NX-69145f08"); } -dayjs.locale("en"); - const config = { core: { authorizationKey: import.meta.env.VITE_APP_SPLIT_API, diff --git a/client/src/components/eula/eula.component.jsx b/client/src/components/eula/eula.component.jsx index 8d2227e02..399a52b40 100644 --- a/client/src/components/eula/eula.component.jsx +++ b/client/src/components/eula/eula.component.jsx @@ -8,7 +8,7 @@ import { INSERT_EULA_ACCEPTANCE } from "../../graphql/user.queries"; import { useMutation } from "@apollo/client"; import { acceptEula } from "../../redux/user/user.actions"; import { useTranslation } from "react-i18next"; -import day from "../../utils/day"; +import dayjs from "../../utils/day"; import "./eula.styles.scss"; import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; @@ -208,7 +208,7 @@ const EulaFormComponent = ({ form, handleChange, onFinish, t }) => ( { required: true, validator: (_, value) => { - if (day(value).isSame(day(), "day")) { + if (dayjs(value).isSame(dayjs(), "day")) { return Promise.resolve(); } return Promise.reject(new Error(t("eula.messages.date_accepted"))); diff --git a/client/src/components/job-lifecycle/job-lifecycle.component.jsx b/client/src/components/job-lifecycle/job-lifecycle.component.jsx index 794524c2a..e648ad4d5 100644 --- a/client/src/components/job-lifecycle/job-lifecycle.component.jsx +++ b/client/src/components/job-lifecycle/job-lifecycle.component.jsx @@ -1,5 +1,5 @@ import React, { useCallback, useEffect, useState } from "react"; -import day from "../../utils/day"; +import dayjs from "../../utils/day"; import axios from "axios"; import { Badge, Card, Space, Table, Tag } from "antd"; import { gql, useQuery } from "@apollo/client"; @@ -72,7 +72,7 @@ export function JobLifecycleComponent({ job, statuses, ...rest }) { dataIndex: "start", key: "start", render: (text) => DateTimeFormatterFunction(text), - sorter: (a, b) => day(a.start).unix() - day(b.start).unix() + sorter: (a, b) => dayjs(a.start).unix() - dayjs(b.start).unix() }, { title: t("job_lifecycle.columns.relative_start"), @@ -90,7 +90,7 @@ export function JobLifecycleComponent({ job, statuses, ...rest }) { } return isEmpty(a.end) ? 1 : -1; } - return day(a.end).unix() - day(b.end).unix(); + return dayjs(a.end).unix() - dayjs(b.end).unix(); }, render: (text) => (isEmpty(text) ? t("job_lifecycle.content.not_available") : DateTimeFormatterFunction(text)) }, diff --git a/client/src/components/job-line-dispatch-button/job-line-dispatch-button.component.jsx b/client/src/components/job-line-dispatch-button/job-line-dispatch-button.component.jsx index 8e570ab2d..ce0b6e4fe 100644 --- a/client/src/components/job-line-dispatch-button/job-line-dispatch-button.component.jsx +++ b/client/src/components/job-line-dispatch-button/job-line-dispatch-button.component.jsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import { useMutation } from "@apollo/client"; import { Button, Form, notification, Popover, Select, Space } from "antd"; -import day from "../../utils/day"; +import dayjs from "../../utils/day"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -48,7 +48,7 @@ export function JobLineDispatchButton({ const result = await dispatchLines({ variables: { partsDispatch: { - dispatched_at: day(), + dispatched_at: dayjs(), employeeid: values.employeeid, jobid: job.id, dispatched_by: currentUser.email, @@ -138,7 +138,11 @@ export function JobLineDispatchButton({ return ( - diff --git a/client/src/components/parts-dispatch-expander/parts-dispatch-expander.component.jsx b/client/src/components/parts-dispatch-expander/parts-dispatch-expander.component.jsx index 477240357..2a84527cc 100644 --- a/client/src/components/parts-dispatch-expander/parts-dispatch-expander.component.jsx +++ b/client/src/components/parts-dispatch-expander/parts-dispatch-expander.component.jsx @@ -1,6 +1,6 @@ import { useMutation } from "@apollo/client"; import { Button, Card, Col, notification, Row, Table } from "antd"; -import day from "../../utils/day"; +import dayjs from "../../utils/day"; import React from "react"; import { useTranslation } from "react-i18next"; import { UPDATE_PARTS_DISPATCH_LINE } from "../../graphql/parts-dispatch.queries"; @@ -11,7 +11,7 @@ export default function PartsDispatchExpander({ dispatch, job }) { const [updateDispatchLine] = useMutation(UPDATE_PARTS_DISPATCH_LINE); const handleAccept = async ({ partsDispatchLineId }) => { - const accepted_at = day(); + const accepted_at = dayjs(); const result = await updateDispatchLine({ variables: { id: partsDispatchLineId, line: { accepted_at } }, optimisticResponse: { diff --git a/client/src/components/time-tickets-commit-toggle/time-tickets-commit-toggle.component.jsx b/client/src/components/time-tickets-commit-toggle/time-tickets-commit-toggle.component.jsx index 3ee60583a..07aa3234d 100644 --- a/client/src/components/time-tickets-commit-toggle/time-tickets-commit-toggle.component.jsx +++ b/client/src/components/time-tickets-commit-toggle/time-tickets-commit-toggle.component.jsx @@ -1,6 +1,6 @@ import { useMutation } from "@apollo/client"; import { Button, notification } from "antd"; -import day from "../../utils/day"; +import dayjs from "../../utils/day"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -29,7 +29,7 @@ export function TimeTicketsCommit({ bodyshop, currentUser, timeticket, disabled, ? { commited_by: null, committed_at: null } : { commited_by: currentUser.email, - committed_at: day() + committed_at: dayjs() }; const result = await updateTimeTicket({ diff --git a/client/src/components/time-tickets-commit/time-tickets-commit.component.jsx b/client/src/components/time-tickets-commit/time-tickets-commit.component.jsx index 52aef7401..c817afd2e 100644 --- a/client/src/components/time-tickets-commit/time-tickets-commit.component.jsx +++ b/client/src/components/time-tickets-commit/time-tickets-commit.component.jsx @@ -1,6 +1,6 @@ import { useMutation } from "@apollo/client"; import { Button, notification } from "antd"; -import day from "../../utils/day"; +import dayjs from "../../utils/day"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -34,7 +34,7 @@ export function TimeTicketsCommit({ timeticketIds: timetickets.map((ticket) => ticket.id), timeticket: { commited_by: currentUser.email, - committed_at: day() + committed_at: dayjs() } }, update(cache) { @@ -47,7 +47,7 @@ export function TimeTicketsCommit({ return { ...ticket, commited_by: currentUser.email, - committed_at: day() + committed_at: dayjs() }; } return ticket; diff --git a/client/src/components/tt-approve-button/tt-approve-button.component.jsx b/client/src/components/tt-approve-button/tt-approve-button.component.jsx index 8a31528d7..48daee263 100644 --- a/client/src/components/tt-approve-button/tt-approve-button.component.jsx +++ b/client/src/components/tt-approve-button/tt-approve-button.component.jsx @@ -1,7 +1,7 @@ import { useApolloClient } from "@apollo/client"; import { Button, notification } from "antd"; import _ from "lodash"; -import day from "../../utils/day"; +import dayjs from "../../utils/day"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -49,7 +49,7 @@ export function TtApproveButton({ })), approvalIds: selectedTickets, approvalUpdate: { - approved_at: day(), + approved_at: dayjs(), approved_by: currentUser.email } } diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js index f565ea544..423b40283 100644 --- a/client/src/redux/user/user.sagas.js +++ b/client/src/redux/user/user.sagas.js @@ -28,7 +28,7 @@ import { } from "../../firebase/firebase.utils"; import { QUERY_EULA } from "../../graphql/bodyshop.queries"; import client from "../../utils/GraphQLClient"; -import day from "../../utils/day"; +import dayjs from "../../utils/day"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; import { checkInstanceId, @@ -96,7 +96,7 @@ export function* isUserAuthenticated() { const eulaQuery = yield client.query({ query: QUERY_EULA, variables: { - now: day() + now: dayjs() } }); @@ -314,8 +314,7 @@ export function* SetAuthLevelFromShopDetails({ payload }) { try { const userEmail = yield select((state) => state.user.currentUser.email); try { - console.log("Setting shop timezone."); - day.tz.setDefault(payload.timezone); + dayjs.tz.setDefault(payload.timezone); } catch (error) { console.log(error); } diff --git a/client/src/utils/day.js b/client/src/utils/day.js index 3fb824b11..3194cfb31 100644 --- a/client/src/utils/day.js +++ b/client/src/utils/day.js @@ -1,5 +1,6 @@ import dayjs from "dayjs"; +import "dayjs/locale/en"; import dayjsBusinessDays from "dayjs-business-days2"; import isSameOrAfter from "dayjs/plugin/isSameOrAfter"; import updateLocale from "dayjs/plugin/updateLocale"; @@ -64,4 +65,6 @@ dayjs.extend(minMax); dayjs.extend(isBetween); dayjs.extend(dayjsBusinessDays); +dayjs.locale("en"); + export default dayjs; From 0b7d469e0e88a2b8ecf0173b948c288e95ca0af3 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 28 Oct 2024 11:55:13 -0700 Subject: [PATCH 02/12] feature/IO-2979-DST - Finish DST Signed-off-by: Dave Richer --- .../components/schedule-calendar-wrapper/localizer.js | 11 ++++++++--- .../scheduler-calendar-wrapper.component.jsx | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/client/src/components/schedule-calendar-wrapper/localizer.js b/client/src/components/schedule-calendar-wrapper/localizer.js index e91016416..871511ce2 100644 --- a/client/src/components/schedule-calendar-wrapper/localizer.js +++ b/client/src/components/schedule-calendar-wrapper/localizer.js @@ -119,7 +119,7 @@ var formats = { agendaTimeRangeFormat: timeRangeFormat }; -const localizer = (dayjsLib) => { +const localizer = (dayjsLib, timezone) => { // load dayjs plugins dayjsLib.extend(isBetween); dayjsLib.extend(isSameOrAfter); @@ -128,6 +128,10 @@ const localizer = (dayjsLib) => { dayjsLib.extend(localizedFormat); dayjsLib.extend(minMax); dayjsLib.extend(utc); + + dayjsLib.locale("en"); + dayjsLib.tz.setDefault(timezone); + var locale = function locale(dj, c) { return c ? dj.locale(c) : dj; }; @@ -136,8 +140,9 @@ const localizer = (dayjsLib) => { // then use the timezone aware version //TODO This was the issue entirely... - // var dayjs = dayjsLib.tz ? dayjsLib.tz : dayjsLib; - var dayjs = dayjsLib; + var dayjs = dayjsLib.tz ? dayjsLib.tz : dayjsLib; + + // var dayjs = dayjsLib; function getTimezoneOffset(date) { // ensures this gets cast to timezone diff --git a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx index fb866d89d..1d9e14eb9 100644 --- a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx +++ b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx @@ -1,7 +1,7 @@ import dayjs from "../../utils/day"; import queryString from "query-string"; import React from "react"; -import { Calendar } from "react-big-calendar"; +import { Calendar, dayjsLocalizer } from "react-big-calendar"; import { connect } from "react-redux"; import { Link, useLocation, useNavigate } from "react-router-dom"; import { createStructuredSelector } from "reselect"; @@ -14,13 +14,13 @@ import { selectProblemJobs } from "../../redux/application/application.selectors import { Alert, Collapse, Space } from "antd"; import { Trans, useTranslation } from "react-i18next"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; -import local from "./localizer"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, problemJobs: selectProblemJobs }); -const localizer = local(dayjs); + +const localizer = dayjsLocalizer(dayjs); export function ScheduleCalendarWrapperComponent({ bodyshop, From 971a81fc272c44f9c43c119eeb4df848c0233edc Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 28 Oct 2024 14:04:14 -0700 Subject: [PATCH 03/12] feature/IO-2979-DST - Finish DST Stuff Signed-off-by: Dave Richer --- .../form-date-time-picker.component.jsx | 26 ++++++++++++++++--- .../schedule-calendar-wrapper/localizer.js | 18 +++---------- .../scheduler-calendar-wrapper.component.jsx | 5 ++-- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx b/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx index e34ae14f7..707dfbdf8 100644 --- a/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx +++ b/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx @@ -4,19 +4,37 @@ import React, { useCallback, useState } from "react"; import { useTranslation } from "react-i18next"; import dayjs from "../../utils/day"; import { fuzzyMatchDate } from "./formats.js"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors.js"; +import { connect } from "react-redux"; -const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, isDateOnly = false, ...restProps }) => { +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); + +const DateTimePicker = ({ + value, + onChange, + onBlur, + id, + onlyFuture, + onlyToday, + isDateOnly = false, + bodyshop, + ...restProps +}) => { const [isManualInput, setIsManualInput] = useState(false); const { t } = useTranslation(); const handleChange = useCallback( (newDate) => { + if (!newDate) return; if (onChange) { - onChange(newDate || null); + onChange(bodyshop?.timezone ? dayjs(newDate).tz(bodyshop.timezone, true) : newDate); } setIsManualInput(false); }, - [onChange] + [onChange, bodyshop?.timezone] ); const handleBlur = useCallback( @@ -102,4 +120,4 @@ DateTimePicker.propTypes = { isDateOnly: PropTypes.bool }; -export default React.memo(DateTimePicker); +export default connect(mapStateToProps, null)(DateTimePicker); diff --git a/client/src/components/schedule-calendar-wrapper/localizer.js b/client/src/components/schedule-calendar-wrapper/localizer.js index 871511ce2..9935252b4 100644 --- a/client/src/components/schedule-calendar-wrapper/localizer.js +++ b/client/src/components/schedule-calendar-wrapper/localizer.js @@ -119,19 +119,7 @@ var formats = { agendaTimeRangeFormat: timeRangeFormat }; -const localizer = (dayjsLib, timezone) => { - // load dayjs plugins - dayjsLib.extend(isBetween); - dayjsLib.extend(isSameOrAfter); - dayjsLib.extend(isSameOrBefore); - dayjsLib.extend(localeData); - dayjsLib.extend(localizedFormat); - dayjsLib.extend(minMax); - dayjsLib.extend(utc); - - dayjsLib.locale("en"); - dayjsLib.tz.setDefault(timezone); - +const localizer = (dayjsLib) => { var locale = function locale(dj, c) { return c ? dj.locale(c) : dj; }; @@ -140,9 +128,9 @@ const localizer = (dayjsLib, timezone) => { // then use the timezone aware version //TODO This was the issue entirely... - var dayjs = dayjsLib.tz ? dayjsLib.tz : dayjsLib; + // var dayjs = dayjsLib.tz ? dayjsLib.tz : dayjsLib; - // var dayjs = dayjsLib; + var dayjs = dayjsLib; function getTimezoneOffset(date) { // ensures this gets cast to timezone diff --git a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx index 1d9e14eb9..4d6f8fe78 100644 --- a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx +++ b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx @@ -1,7 +1,7 @@ import dayjs from "../../utils/day"; import queryString from "query-string"; import React from "react"; -import { Calendar, dayjsLocalizer } from "react-big-calendar"; +import { Calendar } from "react-big-calendar"; import { connect } from "react-redux"; import { Link, useLocation, useNavigate } from "react-router-dom"; import { createStructuredSelector } from "reselect"; @@ -14,13 +14,14 @@ import { selectProblemJobs } from "../../redux/application/application.selectors import { Alert, Collapse, Space } from "antd"; import { Trans, useTranslation } from "react-i18next"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import local from "./localizer"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, problemJobs: selectProblemJobs }); -const localizer = dayjsLocalizer(dayjs); +const localizer = local(dayjs); export function ScheduleCalendarWrapperComponent({ bodyshop, From d75ea2b1a6ffcabe85ef5c5db101a9b4f1ca516a Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 28 Oct 2024 17:38:46 -0700 Subject: [PATCH 04/12] release/2024-11-01 - Misc fixes Signed-off-by: Dave Richer --- .../components/header/header.component.jsx | 21 ++++++++----------- server/accounting/qbo/qbo-payables.js | 2 +- server/web-sockets/redisSocketEvents.js | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index c00aa33e5..341e19ba0 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -116,18 +116,15 @@ function Header({ const { t } = useTranslation(); - const deleteBetaCookie = () => { - const cookieExists = document.cookie.split("; ").some((row) => row.startsWith(`betaSwitchImex=`)); - if (cookieExists) { - const domain = window.location.hostname.split(".").slice(-2).join("."); - document.cookie = `betaSwitchImex=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${domain}`; - console.log(`betaSwitchImex cookie deleted`); - } else { - console.log(`betaSwitchImex cookie does not exist`); - } - }; - - deleteBetaCookie(); + // const deleteBetaCookie = () => { + // const cookieExists = document.cookie.split("; ").some((row) => row.startsWith(`betaSwitchImex=`)); + // if (cookieExists) { + // const domain = window.location.hostname.split(".").slice(-2).join("."); + // document.cookie = `betaSwitchImex=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${domain}`; + // } + // }; + // + // deleteBetaCookie(); const accountingChildren = []; diff --git a/server/accounting/qbo/qbo-payables.js b/server/accounting/qbo/qbo-payables.js index 9b5cf2558..de0c8ad4a 100644 --- a/server/accounting/qbo/qbo-payables.js +++ b/server/accounting/qbo/qbo-payables.js @@ -45,7 +45,7 @@ exports.default = async (req, res) => { const BearerToken = req.BearerToken; const client = req.userGraphQLClient; - logger.log("qbo-payable-create", "DEBUG", req.user.email, billsToQuery); + logger.log("qbo-payable-create", "DEBUG", req.user.email, null, { billsToQuery }); const result = await client .setHeaders({ Authorization: BearerToken }) diff --git a/server/web-sockets/redisSocketEvents.js b/server/web-sockets/redisSocketEvents.js index 0e8a3a449..25e101013 100644 --- a/server/web-sockets/redisSocketEvents.js +++ b/server/web-sockets/redisSocketEvents.js @@ -80,7 +80,7 @@ const redisSocketEvents = ({ try { const room = getBodyshopRoom(bodyshopUUID); socket.join(room); - createLogEvent(socket, "debug", `Client joined bodyshop room: ${room}`); + // createLogEvent(socket, "debug", `Client joined bodyshop room: ${room}`); } catch (error) { createLogEvent(socket, "error", `Error joining room: ${error}`); } From c1331956070c7685a90d2033786ef275bb71fb96 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 28 Oct 2024 17:48:43 -0700 Subject: [PATCH 05/12] release/2024-11-01 - Misc fixes Signed-off-by: Dave Richer --- server/accounting/qbo/qbo-payables.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/accounting/qbo/qbo-payables.js b/server/accounting/qbo/qbo-payables.js index de0c8ad4a..c6e935060 100644 --- a/server/accounting/qbo/qbo-payables.js +++ b/server/accounting/qbo/qbo-payables.js @@ -122,7 +122,7 @@ exports.default = async (req, res) => { res.status(200).json(ret); } catch (error) { //console.log(error); - logger.log("qbo-payable-create-error", "ERROR", req.user.email, { + logger.log("qbo-payable-create-error", "ERROR", req.user.email, null, { error: error.message, stack: error.stack }); From 96e970faf71db79659111445e8c15c3533873d0e Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 28 Oct 2024 18:16:48 -0700 Subject: [PATCH 06/12] release/2024-11-01 - Misc fixes Signed-off-by: Dave Richer --- server/accounting/qbo/qbo-payables.js | 6 ++++++ server/accounting/qbo/qbo-payments.js | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/server/accounting/qbo/qbo-payables.js b/server/accounting/qbo/qbo-payables.js index c6e935060..196520de0 100644 --- a/server/accounting/qbo/qbo-payables.js +++ b/server/accounting/qbo/qbo-payables.js @@ -91,6 +91,12 @@ exports.default = async (req, res) => { ret.push({ billid: bill.id, success: true }); } catch (error) { + logger.log("qbo-paybles-create-error", "ERROR", req.user.email, null, { + error: + (error && error.authResponse && error.authResponse.body) || + error.response?.data?.Fault?.Error.map((e) => e.Detail).join(", ") || + (error && error.message) + }); ret.push({ billid: bill.id, success: false, diff --git a/server/accounting/qbo/qbo-payments.js b/server/accounting/qbo/qbo-payments.js index b5d884f02..6426bfa4f 100644 --- a/server/accounting/qbo/qbo-payments.js +++ b/server/accounting/qbo/qbo-payments.js @@ -49,7 +49,7 @@ exports.default = async (req, res) => { const BearerToken = req.BearerToken; const client = req.userGraphQLClient; - logger.log("qbo-payment-create", "DEBUG", req.user.email, paymentsToQuery); + logger.log("qbo-payment-create", "DEBUG", req.user.email, null, { paymentsToQuery }); const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_PAYMENTS_FOR_EXPORT, { payments: paymentsToQuery @@ -152,7 +152,7 @@ exports.default = async (req, res) => { ret.push({ paymentid: payment.id, success: true }); } catch (error) { - logger.log("qbo-payment-create-error", "ERROR", req.user.email, { + logger.log("qbo-payment-create-error", "ERROR", req.user.email, null, { error: (error && error.authResponse && error.authResponse.body) || (error && error.message) }); //Add the export log error. @@ -183,7 +183,7 @@ exports.default = async (req, res) => { res.status(200).json(ret); } catch (error) { //console.log(error); - logger.log("qbo-payment-create-error", "ERROR", req.user.email, { + logger.log("qbo-payment-create-error", "ERROR", req.user.email, null, { error: error.message, stack: error.stack }); From fc3ea2bdf8c97d80645ded1c9ec6dcd0ce007f25 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 29 Oct 2024 07:37:40 -0700 Subject: [PATCH 07/12] release/2024-11-01 - Misc fixes Signed-off-by: Dave Richer --- server/accounting/qb-receivables-lines.js | 2 +- server/accounting/qbxml/qbxml-payables.js | 7 ++++--- server/accounting/qbxml/qbxml-payments.js | 7 +++++-- server/accounting/qbxml/qbxml-receivables.js | 7 +++++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/server/accounting/qb-receivables-lines.js b/server/accounting/qb-receivables-lines.js index 8476ce6d4..043dc8e89 100644 --- a/server/accounting/qb-receivables-lines.js +++ b/server/accounting/qb-receivables-lines.js @@ -63,7 +63,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes ); if (!account) { - logger.log("qbxml-receivables-no-account", "warn", null, jobline.id, null); + logger.log("qbxml-receivables-no-account", "warn", null, jobline.id); throw new Error( `A matching account does not exist for the part allocation. Center: ${jobline.profitcenter_part}` ); diff --git a/server/accounting/qbxml/qbxml-payables.js b/server/accounting/qbxml/qbxml-payables.js index 9ffe4513f..ef588e0fb 100644 --- a/server/accounting/qbxml/qbxml-payables.js +++ b/server/accounting/qbxml/qbxml-payables.js @@ -42,9 +42,10 @@ exports.default = async (req, res) => { //For each invoice. res.status(200).json(QbXmlToExecute); } catch (error) { - logger.log("qbxml-payable-error", "ERROR", req.user.email, req.body.billsToQuery, { - error: error.message, - stack: error.stack + logger.log("qbxml-payable-error", "ERROR", req?.user?.email, null, { + billsToQuery: req?.body?.billsToQuery, + error: error?.message, + stack: error?.stack }); res.status(400).send(JSON.stringify(error)); } diff --git a/server/accounting/qbxml/qbxml-payments.js b/server/accounting/qbxml/qbxml-payments.js index cdc08d2e4..68e7b8778 100644 --- a/server/accounting/qbxml/qbxml-payments.js +++ b/server/accounting/qbxml/qbxml-payments.js @@ -21,7 +21,9 @@ exports.default = async (req, res) => { const client = req.userGraphQLClient; try { - logger.log("qbxml-payments-create", "DEBUG", req.user.email, req.body.paymentsToQuery, null); + logger.log("qbxml-payments-create", "DEBUG", req?.user?.email, null, { + paymentsToQuery: req.body?.paymentsToQuery + }); const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_PAYMENTS_FOR_EXPORT, { payments: paymentsToQuery @@ -62,7 +64,8 @@ exports.default = async (req, res) => { res.status(200).json(QbXmlToExecute); } catch (error) { - logger.log("qbxml-payments-error", "error", req.user.email, req.body.paymentsToQuery, { + logger.log("qbxml-payments-error", "error", req?.user?.email, null, { + paymentsToQuery: req.body?.paymentsToQuery, error: error.message, stack: error.stack }); diff --git a/server/accounting/qbxml/qbxml-receivables.js b/server/accounting/qbxml/qbxml-receivables.js index 0e8a4f20d..c4353704e 100644 --- a/server/accounting/qbxml/qbxml-receivables.js +++ b/server/accounting/qbxml/qbxml-receivables.js @@ -23,7 +23,9 @@ exports.default = async (req, res) => { const client = req.userGraphQLClient; try { - logger.log("qbxml-receivables-create", "DEBUG", req.user.email, req.body.jobIds, null); + logger.log("qbxml-receivables-create", "DEBUG", req?.user?.email, null, { + jobIds: req?.body?.jobIds + }); const result = await client .setHeaders({ Authorization: BearerToken }) @@ -74,7 +76,8 @@ exports.default = async (req, res) => { res.status(200).json(QbXmlToExecute); } catch (error) { - logger.log("qbxml-receivables-error", "error", req.user.email, req.body.jobIds, { + logger.log("qbxml-receivables-error", "error", req?.user?.email, null, { + jobIds: req.body?.jobIds, error: error.message, stack: error.stack }); From 23f8f69bbeb38111951b8ee87e3e6ac7835e2c18 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 29 Oct 2024 08:19:58 -0700 Subject: [PATCH 08/12] release/2024-11-01 - Misc fixes Signed-off-by: Dave Richer --- server/email/mailer.js | 3 ++- server/utils/logger.js | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/server/email/mailer.js b/server/email/mailer.js index 6503e1f8c..654f56cb3 100644 --- a/server/email/mailer.js +++ b/server/email/mailer.js @@ -3,6 +3,7 @@ const { defaultProvider } = require("@aws-sdk/credential-provider-node"); const { default: InstanceManager } = require("../utils/instanceMgr"); const aws = require("@aws-sdk/client-ses"); const nodemailer = require("nodemailer"); +const logger = require("../utils/logger"); const isLocal = isString(process.env?.LOCALSTACK_HOSTNAME) && !isEmpty(process.env?.LOCALSTACK_HOSTNAME); @@ -19,7 +20,7 @@ const sesConfig = { if (isLocal) { sesConfig.endpoint = `http://${process.env.LOCALSTACK_HOSTNAME}:4566`; - console.log(`SES Mailer set to LocalStack end point: ${sesConfig.endpoint}`); + logger.logger.debug(`SES Mailer set to LocalStack end point: ${sesConfig.endpoint}`); } const ses = new aws.SES(sesConfig); diff --git a/server/utils/logger.js b/server/utils/logger.js index 75d282fa2..b1e96e02d 100644 --- a/server/utils/logger.js +++ b/server/utils/logger.js @@ -8,7 +8,7 @@ const InstanceManager = require("../utils/instanceMgr").default; const winston = require("winston"); const WinstonCloudWatch = require("winston-cloudwatch"); const { isString, isEmpty } = require("lodash"); -const { networkInterfaces } = require("node:os"); +const { networkInterfaces, hostname } = require("node:os"); const createLogger = () => { try { @@ -28,9 +28,6 @@ const createLogger = () => { if (isLocal) { winstonCloudwatchTransportDefaults.awsOptions.endpoint = `http://${process.env.LOCALSTACK_HOSTNAME}:4566`; - console.log( - `Winston Transports set to LocalStack end point: ${winstonCloudwatchTransportDefaults.awsOptions.endpoint}` - ); } const levelFilter = (levels) => { @@ -43,19 +40,22 @@ const createLogger = () => { })(); }; - const getPrivateIP = () => { + const getHostNameOrIP = () => { + // Try to get the hostname first + const hostName = hostname(); + if (hostName) return hostName; + const interfaces = networkInterfaces(); for (const name of Object.keys(interfaces)) { for (const iface of interfaces[name]) { - // Find an IPv4 address that's not internal (like localhost) if (iface.family === "IPv4" && !iface.internal) { return iface.address; } } } + return "127.0.0.1"; }; - const createProductionTransport = (level, logStreamName, filters) => { return new WinstonCloudWatch({ level, @@ -65,7 +65,7 @@ const createLogger = () => { }); }; - const hostname = process.env.HOSTNAME || getPrivateIP(); + const hostname = process.env.HOSTNAME || getHostNameOrIP(); const getDevelopmentTransports = () => [ new winston.transports.Console({ @@ -106,6 +106,12 @@ const createLogger = () => { : [...getDevelopmentTransports(), ...getProductionTransports()] }); + if (isLocal) { + winstonLogger.debug( + `CloudWatch set to LocalStack end point: ${winstonCloudwatchTransportDefaults.awsOptions.endpoint}` + ); + } + const log = (message, type, user, record, meta) => { winstonLogger.log({ level: type.toLowerCase(), From 63b914731b781e07d86bd7598715d17dc02d2e39 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 29 Oct 2024 08:25:54 -0700 Subject: [PATCH 09/12] release/2024-11-01 - Misc fixes Signed-off-by: Dave Richer --- server/utils/logger.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/utils/logger.js b/server/utils/logger.js index b1e96e02d..26dd72150 100644 --- a/server/utils/logger.js +++ b/server/utils/logger.js @@ -65,7 +65,7 @@ const createLogger = () => { }); }; - const hostname = process.env.HOSTNAME || getHostNameOrIP(); + const internalHostname = process.env.HOSTNAME || getHostNameOrIP(); const getDevelopmentTransports = () => [ new winston.transports.Console({ @@ -74,7 +74,7 @@ const createLogger = () => { winston.format.colorize(), winston.format.timestamp(), winston.format.printf(({ level, message, timestamp, user, record, meta }) => { - const hostnameColor = `\x1b[34m${hostname}\x1b[0m`; // Blue + const hostnameColor = `\x1b[34m${internalHostname}\x1b[0m`; // Blue const timestampColor = `\x1b[36m${timestamp}\x1b[0m`; // Cyan const labelColor = "\x1b[33m"; // Yellow const separatorColor = "\x1b[35m|\x1b[0m"; // Magenta for separators @@ -118,7 +118,7 @@ const createLogger = () => { message, user, record, - hostname, + hostname: internalHostname, meta }); }; From 3f247a9227ecdfedbae4cf53a69413dcdd8fc5f4 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 29 Oct 2024 09:54:45 -0700 Subject: [PATCH 10/12] release/2024-11-01 - Misc fixes Signed-off-by: Dave Richer --- server/job/job-updated.js | 2 +- server/mixdata/mixdata.js | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/server/job/job-updated.js b/server/job/job-updated.js index f218f83bc..606e6682c 100644 --- a/server/job/job-updated.js +++ b/server/job/job-updated.js @@ -15,7 +15,7 @@ const jobUpdated = async (req, res) => { }); } - logger.log("job-update", "INFO", req.user?.email, null, { + logger.log("job-update", "DEBUG", req.user?.email, null, { message: `Job updated event received from Hasura`, jobid: req?.body?.event?.data?.new?.id }); diff --git a/server/mixdata/mixdata.js b/server/mixdata/mixdata.js index 0dca3705b..d61989103 100644 --- a/server/mixdata/mixdata.js +++ b/server/mixdata/mixdata.js @@ -9,11 +9,9 @@ require("dotenv").config({ }); exports.mixdataUpload = async (req, res) => { - const { bodyshopid } = req.body; - const client = req.userGraphQLClient; - logger.log("job-mixdata-upload", "DEBUG", req.user.email, null, null); + logger.log("job-mixdata-upload", "DEBUG", req?.user?.email, null, null); try { for (const element of req.files) { @@ -23,7 +21,7 @@ exports.mixdataUpload = async (req, res) => { explicitArray: false }); - logger.log("job-mixdata-parse", "DEBUG", req.user.email, inboundRequest); + logger.log("job-mixdata-parse", "DEBUG", req?.user?.email, null, { inboundRequest }); const ScaleType = DetermineScaleType(inboundRequest); const RoNumbersFromInboundRequest = GetListOfRos(inboundRequest, ScaleType); @@ -70,7 +68,7 @@ function DetermineScaleType(inboundRequest) { const ret = { type: "", verson: 0 }; //PPG Mix Data - if (inboundRequest.PPG && inboundRequest.PPG.Header.Protocol.Name === "PPG") { + if (inboundRequest?.PPG?.Header?.Protocol?.Name === "PPG") { return { type: inboundRequest.PPG.Header.Protocol.Name, company: "PPG", @@ -80,13 +78,13 @@ function DetermineScaleType(inboundRequest) { } function GetListOfRos(inboundRequest, ScaleType) { - if (ScaleType.company === "PPG" && ScaleType.version === "1.3.0") { + if (ScaleType?.company === "PPG" && ScaleType?.version === "1.3.0") { return inboundRequest.PPG.MixDataInterface.ROData.RepairOrders.RO.map((r) => r.RONumber); } } function GenerateMixDataArray(inboundRequest, ScaleType, jobHash) { - if (ScaleType.company === "PPG" && ScaleType.version === "1.3.0") { + if (ScaleType?.company === "PPG" && ScaleType?.version === "1.3.0") { return inboundRequest.PPG.MixDataInterface.ROData.RepairOrders.RO.map((r) => { return { jobid: jobHash[r.RONumber]?.jobid, From 42f1d6fa1370880e520d3351bd3a5496dcf728e5 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 29 Oct 2024 10:53:09 -0700 Subject: [PATCH 11/12] release/2024-11-01 - Misc fixes Signed-off-by: Dave Richer --- server/cdk/cdk-get-makes.js | 3 +- server/email/sendemail.js | 35 ++++++------ server/email/tasksEmails.js | 4 +- server/email/tasksEmailsQueue.js | 5 +- server/firebase/firebase-handler.js | 8 ++- server/job/job-costing.js | 55 +++++++++++++++---- server/job/job-totals-USA.js | 16 +++--- .../validateFirebaseIdTokenMiddleware.js | 18 +++--- server/payroll/pay-all.js | 6 +- server/scheduling/scheduling-job.js | 8 +-- server/stripe/payment.js | 2 +- server/tasks/tasks.js | 9 ++- 12 files changed, 108 insertions(+), 61 deletions(-) diff --git a/server/cdk/cdk-get-makes.js b/server/cdk/cdk-get-makes.js index 06ccc53e2..90accf64e 100644 --- a/server/cdk/cdk-get-makes.js +++ b/server/cdk/cdk-get-makes.js @@ -39,8 +39,8 @@ exports.default = async function ReloadCdkMakes(req, res) { const deleteResult = await client .setHeaders({ Authorization: BearerToken }) .request(queries.DELETE_ALL_DMS_VEHICLES, {}); - console.log("🚀 ~ file: cdk-get-makes.js ~ line 53 ~ deleteResult", deleteResult); + // logger.logger.debug("🚀 ~ file: cdk-get-makes.js ~ line 53 ~ deleteResult", { deleteResult }); //Insert the new ones. const insertResult = await client.setHeaders({ Authorization: BearerToken }).request(queries.INSERT_DMS_VEHICLES, { @@ -59,6 +59,7 @@ exports.default = async function ReloadCdkMakes(req, res) { cdk_dealerid, count: newList.length }); + res.sendStatus(200); } catch (error) { logger.log("cdk-replace-makes-models-error", "ERROR", req.user.email, null, { diff --git a/server/email/sendemail.js b/server/email/sendemail.js index 97e8f74ad..9d103ef81 100644 --- a/server/email/sendemail.js +++ b/server/email/sendemail.js @@ -21,7 +21,7 @@ const getImage = async (imageUrl) => { // Log the email in the database const logEmail = async (req, email) => { try { - const insertresult = await client.request(queries.INSERT_EMAIL_AUDIT, { + await client.request(queries.INSERT_EMAIL_AUDIT, { email: { to: email.to, cc: email.cc, @@ -34,13 +34,13 @@ const logEmail = async (req, email) => { status: "Sent" } }); - console.log(insertresult); } catch (error) { - logger.log("email-log-error", "error", req.user.email, null, { + logger.log("email-log-error", "error", req?.user?.email, null, { from: `${req.body.from.name} <${req.body.from.address}>`, - to: req.body.to, - cc: req.body.cc, - subject: req.body.subject + to: req?.body?.to, + cc: req?.body?.cc, + subject: req?.body?.subject, + email // info, }); } @@ -70,12 +70,11 @@ const sendServerEmail = async ({ subject, text }) => { } }, (err, info) => { - console.log(err || info); + logger.log("server-email-failure", err ? "error" : "debug", null, null, { message: err || info }); } ); } catch (error) { - console.log(error); - logger.log("server-email-failure", "error", null, null, error); + logger.log("server-email-failure", "error", null, null, { error }); } }; @@ -88,8 +87,7 @@ const sendProManagerWelcomeEmail = async ({ to, subject, html }) => { html }); } catch (error) { - console.log(error); - logger.log("server-email-failure", "error", null, null, error); + logger.log("server-email-failure", "error", null, null, { error }); } }; @@ -108,12 +106,12 @@ const sendTaskEmail = async ({ to, subject, type = "text", html, text, attachmen attachments: attachments || null }, (err, info) => { - console.log(err || info); + // (message, type, user, record, meta + logger.log("server-email", err ? "error" : "debug", null, null, { message: err || info }); } ); } catch (error) { - console.log(error); - logger.log("server-email-failure", "error", null, null, error); + logger.log("server-email-failure", "error", null, null, { error }); } }; @@ -184,9 +182,8 @@ const sendEmail = async (req, res) => { } }, (err, info) => { - console.log(err || info); if (info) { - logger.log("send-email-success", "DEBUG", req.user.email, null, { + logger.log("send-email-success", "DEBUG", req?.user?.email, null, { from: `${req.body.from.name} <${req.body.from.address}>`, replyTo: req.body.ReplyTo.Email, to: req.body.to, @@ -205,7 +202,7 @@ const sendEmail = async (req, res) => { success: true //response: info }); } else { - logger.log("send-email-failure", "ERROR", req.user.email, null, { + logger.log("send-email-failure", "ERROR", req?.user?.email, null, { from: `${req.body.from.name} <${req.body.from.address}>`, replyTo: req.body.ReplyTo.Email, to: req.body.to, @@ -290,7 +287,9 @@ ${body.bounce?.bouncedRecipients.map( ` }, (err, info) => { - console.log("***", err || info); + logger.log("sns-error", err ? "error" : "debug", "api", null, { + message: err ? JSON.stringify(error) : info + }); } ); } diff --git a/server/email/tasksEmails.js b/server/email/tasksEmails.js index ab25343e0..c05185b6b 100644 --- a/server/email/tasksEmails.js +++ b/server/email/tasksEmails.js @@ -18,10 +18,10 @@ const tasksEmailQueue = taskEmailQueue(); const tasksEmailQueueCleanup = async () => { try { // Example async operation - console.log("Performing Tasks Email Reminder process cleanup..."); + // console.log("Performing Tasks Email Reminder process cleanup..."); await new Promise((resolve) => tasksEmailQueue.destroy(() => resolve())); } catch (err) { - console.error("Tasks Email Reminder process cleanup failed:", err); + // console.error("Tasks Email Reminder process cleanup failed:", err); } }; diff --git a/server/email/tasksEmailsQueue.js b/server/email/tasksEmailsQueue.js index dc004abc1..c1828b858 100644 --- a/server/email/tasksEmailsQueue.js +++ b/server/email/tasksEmailsQueue.js @@ -10,8 +10,9 @@ const logger = require("../utils/logger"); const taskEmailQueue = () => new Queue( (taskIds, cb) => { - console.log("Processing reminds for taskIds: ", taskIds.join(", ")); - + logger.log("Processing reminds for taskIds: ", "silly", null, null, { + taskIds: taskIds?.join(", ") + }); // Set the remind_at_sent to the current time. const now = moment().toISOString(); diff --git a/server/firebase/firebase-handler.js b/server/firebase/firebase-handler.js index ec20114f9..e24c86174 100644 --- a/server/firebase/firebase-handler.js +++ b/server/firebase/firebase-handler.js @@ -269,10 +269,14 @@ const sendNotification = async (req, res) => { }) .then((response) => { // Response is a message ID string. - console.log("Successfully sent message:", response); + logger.log("Successfully sent message:", "debug", req?.user?.email, null, { + response + }); }) .catch((error) => { - console.log("Error sending message:", error); + logger.log("Successfully sent message:", "error", req?.user?.email, null, { + error + }); }); res.sendStatus(200); diff --git a/server/job/job-costing.js b/server/job/job-costing.js index 9ce65f71d..c0a3ee149 100644 --- a/server/job/job-costing.js +++ b/server/job/job-costing.js @@ -46,7 +46,9 @@ async function JobCostingMulti(req, res) { const BearerToken = req.BearerToken; const client = req.userGraphQLClient; - logger.log("job-costing-multi-start", "DEBUG", req.user.email, jobids, null); + logger.log("job-costing-multi-start", "DEBUG", req?.user?.email, null, { + jobids + }); try { const resp = await client @@ -244,7 +246,8 @@ async function JobCostingMulti(req, res) { data: ret }); } catch (error) { - logger.log("job-costing-multi-error", "ERROR", req.user.email, [jobids], { + logger.log("job-costing-multi-error", "ERROR", req?.user?.email, null, { + jobids, message: error.message, stack: error.stack }); @@ -282,7 +285,12 @@ function GenerateCostingData(job) { if (val.mod_lbr_ty) { const laborProfitCenter = val.profitcenter_labor || defaultProfits[val.mod_lbr_ty] || "Unknown"; - if (laborProfitCenter === "Unknown") console.log("Unknown type", val.line_desc, val.mod_lbr_ty); + if (laborProfitCenter === "Unknown") { + logger.log("job-costing unknown type", "debug", null, null, { + line_desc: val.line_desc, + mod_lbr_ty: val.mod_lbr_ty + }); + } const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`; @@ -349,10 +357,21 @@ function GenerateCostingData(job) { if (val.part_type && val.part_type !== "PAE" && val.part_type !== "PAS" && val.part_type !== "PASL") { const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown"; - if (partsProfitCenter === "Unknown") console.log("Unknown type", val.line_desc, val.part_type); + if (partsProfitCenter === "Unknown" || !partsProfitCenter) { + logger.log( + partsProfitCenter === "Unknown" + ? "job-costing unknown type" + : "Unknown cost/profit center mapping for parts.", + "debug", + null, + null, + { + line_desc: val.line_desc, + part_type: val.part_type + } + ); + } - if (!partsProfitCenter) - console.log("Unknown cost/profit center mapping for parts.", val.line_desc, val.part_type); let partsAmount = Dinero({ amount: val.act_price_before_ppc ? Math.round(val.act_price_before_ppc * 100) @@ -409,10 +428,21 @@ function GenerateCostingData(job) { if (val.part_type && val.part_type !== "PAE" && (val.part_type === "PAS" || val.part_type === "PASL")) { const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown"; - if (partsProfitCenter === "Unknown") console.log("Unknown type", val.line_desc, val.part_type); + if (partsProfitCenter === "Unknown" || !partsProfitCenter) { + logger.log( + partsProfitCenter === "Unknown" + ? "job-costing unknown type" + : "job-costing Unknown cost/profit center mapping for sublet", + "debug", + null, + null, + { + line_desc: val.line_desc, + part_type: val.part_type + } + ); + } - if (!partsProfitCenter) - console.log("Unknown cost/profit center mapping for sublet.", val.line_desc, val.part_type); const partsAmount = Dinero({ amount: Math.round((val.act_price || 0) * 100) }) @@ -444,7 +474,10 @@ function GenerateCostingData(job) { const partsProfitCenter = val.profitcenter_part || getAdditionalCostCenter(val, defaultProfits) || "Unknown"; if (partsProfitCenter === "Unknown") { - console.log("Unknown type", val.line_desc, val.part_type); + logger.log("job-costing unknown type", "debug", null, null, { + line_desc: val.line_desc, + part_type: val.part_type + }); } const partsAmount = Dinero({ amount: Math.round((val.act_price || 0) * 100) @@ -476,7 +509,7 @@ function GenerateCostingData(job) { if (!hasMapaLine) { if (!jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]]) jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = Dinero(); - + jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = jobLineTotalsByProfitCenter.additional[ defaultProfits["MAPA"] ].add( diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index 4e123850e..c23a64068 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -26,7 +26,7 @@ exports.totalsSsu = async function (req, res) { const BearerToken = req.BearerToken; const client = req.userGraphQLClient; - logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, id, null); + logger.log("job-totals-ssu-USA", "DEBUG", req?.user?.email, id); try { const job = await client.setHeaders({ Authorization: BearerToken }).request(queries.GET_JOB_BY_PK, { @@ -47,7 +47,7 @@ exports.totalsSsu = async function (req, res) { res.status(200).send(); } catch (error) { - logger.log("job-totals-ssu-USA-error", "ERROR", req.user.email, id, { + logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, { jobid: id, error }); @@ -84,12 +84,10 @@ async function Totals(req, res) { const logger = req.logger; const client = req.userGraphQLClient; - logger.log("job-totals-USA", "DEBUG", req.user.email, job.id, { + logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, job.id, { jobid: job.id }); - logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, id, null); - await AutoAddAtsIfRequired({ job, client }); try { @@ -961,7 +959,9 @@ function CalculateTaxesTotals(job, otherTotals) { } } } catch (error) { - console.error("Key with issue", key); + logger.log("job-totals-USA Key with issue", "error", null, null, { + key + }); } }); @@ -1026,7 +1026,9 @@ function CalculateTaxesTotals(job, otherTotals) { totalTaxByTier[taxTierKey] = totalTaxByTier[taxTierKey].add(taxAmountToAdd); } } catch (error) { - console.error("PFP Calculation error", error); + logger.log("job-totals-USA - PFP Calculation Error", "error", null, null, { + error + }); } }); diff --git a/server/middleware/validateFirebaseIdTokenMiddleware.js b/server/middleware/validateFirebaseIdTokenMiddleware.js index d76cc8019..83ab38eaf 100644 --- a/server/middleware/validateFirebaseIdTokenMiddleware.js +++ b/server/middleware/validateFirebaseIdTokenMiddleware.js @@ -16,7 +16,11 @@ const validateFirebaseIdTokenMiddleware = async (req, res, next) => { (!req.headers.authorization || !req.headers.authorization.startsWith("Bearer ")) && !(req.cookies && req.cookies.__session) ) { - console.error("Unauthorized attempt. No authorization provided."); + logger.log("api-authorization-call", "warn", req?.user?.email, null, { + type: "unauthorized", + path: req.path, + body: req.body + }); return res.status(403).send("Unauthorized"); } @@ -32,10 +36,10 @@ const validateFirebaseIdTokenMiddleware = async (req, res, next) => { idToken = req.cookies.__session; } else { // No cookie - console.error("Unauthorized attempt. No cookie provided."); - logger.log("api-unauthorized-call", "WARN", null, null, { - req, - type: "no-cookie" + logger.log("api-unauthorized-call", "warn", null, null, { + type: "unauthorized", + path: req.path, + body: req.body }); return res.status(403).send("Unauthorized"); @@ -47,11 +51,11 @@ const validateFirebaseIdTokenMiddleware = async (req, res, next) => { req.user = decodedIdToken; next(); } catch (error) { - logger.log("api-unauthorized-call", "WARN", null, null, { + logger.log("api-unauthorized-call", "warn", null, null, { path: req.path, body: req.body, - type: "unauthroized", + type: "unauthorized", ...error }); diff --git a/server/payroll/pay-all.js b/server/payroll/pay-all.js index 9288e256a..03c6fbee8 100644 --- a/server/payroll/pay-all.js +++ b/server/payroll/pay-all.js @@ -45,12 +45,12 @@ exports.payall = async function (req, res) { const path = diffParser(diff); if (diff.op === "add") { - console.log(Object.keys(diff.val)); + // console.log(Object.keys(diff.val)); if (typeof diff.val === "object" && Object.keys(diff.val).length > 1) { //Multiple values to add. Object.keys(diff.val).forEach((key) => { - console.log("Hours", diff.val[key][Object.keys(diff.val[key])[0]]); - console.log("Rate", Object.keys(diff.val[key])[0]); + // console.log("Hours", diff.val[key][Object.keys(diff.val[key])[0]]); + // console.log("Rate", Object.keys(diff.val[key])[0]); ticketsToInsert.push({ task_name: "Pay All", jobid: job.id, diff --git a/server/scheduling/scheduling-job.js b/server/scheduling/scheduling-job.js index a005a8d72..11b881f70 100644 --- a/server/scheduling/scheduling-job.js +++ b/server/scheduling/scheduling-job.js @@ -49,7 +49,7 @@ exports.job = async (req, res) => { if (bucketId) { load.productionTotal[bucketId].count = load.productionTotal[bucketId].count + 1; } else { - console.log("Uh oh, this job doesn't fit in a bucket!", item); + // console.log("Uh oh, this job doesn't fit in a bucket!", item); } }); @@ -254,7 +254,7 @@ const CalculateLoad = (currentLoad, buckets, jobsIn, jobsOut) => { if (bucketId) { newLoad[bucketId].count = newLoad[bucketId].count + 1; } else { - console.log("[Util Arr Job]Uh oh, this job doesn't fit in a bucket!", job); + // console.log("[Util Arr Job]Uh oh, this job doesn't fit in a bucket!", job); } }); @@ -263,10 +263,10 @@ const CalculateLoad = (currentLoad, buckets, jobsIn, jobsOut) => { if (bucketId) { newLoad[bucketId].count = newLoad[bucketId].count - 1; if (newLoad[bucketId].count < 0) { - console.log("***ERROR: NEGATIVE LOAD Bucket =>", bucketId, job); + // console.log("***ERROR: NEGATIVE LOAD Bucket =>", bucketId, job); } } else { - console.log("[Util Out Job]Uh oh, this job doesn't fit in a bucket!", job); + // console.log("[Util Out Job]Uh oh, this job doesn't fit in a bucket!", job); } }); diff --git a/server/stripe/payment.js b/server/stripe/payment.js index 3f79c78d0..7b7bc1dc8 100644 --- a/server/stripe/payment.js +++ b/server/stripe/payment.js @@ -39,7 +39,7 @@ const processor = async (req, res) => { } }); } catch (error) { - console.log("error", error); + // console.log("error", error); res.status(400).send(error); } }; diff --git a/server/tasks/tasks.js b/server/tasks/tasks.js index d59d834eb..2ae944e60 100644 --- a/server/tasks/tasks.js +++ b/server/tasks/tasks.js @@ -6,10 +6,11 @@ const client = require("../graphql-client/graphql-client").client; const emailer = require("../email/sendemail"); const moment = require("moment-timezone"); const converter = require("json-2-csv"); +const logger = require("../utils/logger"); exports.taskHandler = async (req, res) => { try { - const { bodyshopid, query, variables, text, to, subject, timezone } = req.body; + const { query, variables, text, to, subject, timezone } = req.body; //Check the variables to see if they are an object. Object.keys(variables).forEach((key) => { @@ -32,8 +33,10 @@ exports.taskHandler = async (req, res) => { text, attachments: [{ filename: "query.csv", content: csv }] }) - .catch((err) => { - console.error("Errors sending CSV Email."); + .catch((error) => { + logger.log("Tasks - Error sending CSV EMAIL", "error", req?.user?.email, null, { + error + }); }); return res.status(200).send(csv); From 6b501e4619ddebf2c7ba960cb48272d515363999 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 29 Oct 2024 11:02:08 -0700 Subject: [PATCH 12/12] release/2024-11-01 - Misc fixes Signed-off-by: Dave Richer --- server/job/job-costing.js | 95 +++++++++++++------------ server/web-sockets/redisSocketEvents.js | 12 ++-- 2 files changed, 59 insertions(+), 48 deletions(-) diff --git a/server/job/job-costing.js b/server/job/job-costing.js index c0a3ee149..668a35673 100644 --- a/server/job/job-costing.js +++ b/server/job/job-costing.js @@ -19,7 +19,8 @@ async function JobCosting(req, res) { const BearerToken = req.BearerToken; const client = req.userGraphQLClient; - logger.log("job-costing-start", "DEBUG", req.user.email, jobid, null); + //Uncomment for further testing + // logger.log("job-costing-start", "DEBUG", req.user.email, jobid, null); try { const resp = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_JOB_COSTING_DETAILS, { @@ -46,9 +47,10 @@ async function JobCostingMulti(req, res) { const BearerToken = req.BearerToken; const client = req.userGraphQLClient; - logger.log("job-costing-multi-start", "DEBUG", req?.user?.email, null, { - jobids - }); + //Uncomment for further testing + // logger.log("job-costing-multi-start", "DEBUG", req?.user?.email, null, { + // jobids + // }); try { const resp = await client @@ -285,12 +287,13 @@ function GenerateCostingData(job) { if (val.mod_lbr_ty) { const laborProfitCenter = val.profitcenter_labor || defaultProfits[val.mod_lbr_ty] || "Unknown"; - if (laborProfitCenter === "Unknown") { - logger.log("job-costing unknown type", "debug", null, null, { - line_desc: val.line_desc, - mod_lbr_ty: val.mod_lbr_ty - }); - } + //Uncomment for further testing + // if (laborProfitCenter === "Unknown") { + // logger.log("job-costing unknown type", "debug", null, null, { + // line_desc: val.line_desc, + // mod_lbr_ty: val.mod_lbr_ty + // }); + // } const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`; @@ -357,20 +360,21 @@ function GenerateCostingData(job) { if (val.part_type && val.part_type !== "PAE" && val.part_type !== "PAS" && val.part_type !== "PASL") { const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown"; - if (partsProfitCenter === "Unknown" || !partsProfitCenter) { - logger.log( - partsProfitCenter === "Unknown" - ? "job-costing unknown type" - : "Unknown cost/profit center mapping for parts.", - "debug", - null, - null, - { - line_desc: val.line_desc, - part_type: val.part_type - } - ); - } + //Uncomment for further testing + // if (partsProfitCenter === "Unknown" || !partsProfitCenter) { + // logger.log( + // partsProfitCenter === "Unknown" + // ? "job-costing unknown type" + // : "Unknown cost/profit center mapping for parts.", + // "debug", + // null, + // null, + // { + // line_desc: val.line_desc, + // part_type: val.part_type + // } + // ); + // } let partsAmount = Dinero({ amount: val.act_price_before_ppc @@ -428,20 +432,21 @@ function GenerateCostingData(job) { if (val.part_type && val.part_type !== "PAE" && (val.part_type === "PAS" || val.part_type === "PASL")) { const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown"; - if (partsProfitCenter === "Unknown" || !partsProfitCenter) { - logger.log( - partsProfitCenter === "Unknown" - ? "job-costing unknown type" - : "job-costing Unknown cost/profit center mapping for sublet", - "debug", - null, - null, - { - line_desc: val.line_desc, - part_type: val.part_type - } - ); - } + //Uncomment for further testing + // if (partsProfitCenter === "Unknown" || !partsProfitCenter) { + // logger.log( + // partsProfitCenter === "Unknown" + // ? "job-costing unknown type" + // : "job-costing Unknown cost/profit center mapping for sublet", + // "debug", + // null, + // null, + // { + // line_desc: val.line_desc, + // part_type: val.part_type + // } + // ); + // } const partsAmount = Dinero({ amount: Math.round((val.act_price || 0) * 100) @@ -473,12 +478,14 @@ function GenerateCostingData(job) { //If so, use it, otherwise try to use the same from the auto-allocate logic in IO app jobs-close-auto-allocate. const partsProfitCenter = val.profitcenter_part || getAdditionalCostCenter(val, defaultProfits) || "Unknown"; - if (partsProfitCenter === "Unknown") { - logger.log("job-costing unknown type", "debug", null, null, { - line_desc: val.line_desc, - part_type: val.part_type - }); - } + //Uncomment for further testing + // if (partsProfitCenter === "Unknown") { + // logger.log("job-costing unknown type", "debug", null, null, { + // line_desc: val.line_desc, + // part_type: val.part_type + // }); + // } + const partsAmount = Dinero({ amount: Math.round((val.act_price || 0) * 100) }) diff --git a/server/web-sockets/redisSocketEvents.js b/server/web-sockets/redisSocketEvents.js index 25e101013..7ae8cd8c4 100644 --- a/server/web-sockets/redisSocketEvents.js +++ b/server/web-sockets/redisSocketEvents.js @@ -41,7 +41,8 @@ const redisSocketEvents = ({ // Register Socket Events const registerSocketEvents = (socket) => { - createLogEvent(socket, "debug", `Registering RedisIO Socket Events.`); + // Uncomment for further testing + // createLogEvent(socket, "debug", `Registering RedisIO Socket Events.`); // Token Update Events const registerUpdateEvents = (socket) => { @@ -54,12 +55,13 @@ const redisSocketEvents = ({ // If We ever want to persist user Data across workers // await setSessionData(socket.id, "user", user); - createLogEvent(socket, "debug", "Token updated successfully"); + // Uncomment for further testing + // createLogEvent(socket, "debug", "Token updated successfully"); socket.emit("token-updated", { success: true }); } catch (error) { if (error.code === "auth/id-token-expired") { - createLogEvent(socket, "WARNING", "Stale token received, waiting for new token"); + createLogEvent(socket, "warn", "Stale token received, waiting for new token"); socket.emit("token-updated", { success: false, error: "Stale token." @@ -114,7 +116,9 @@ const redisSocketEvents = ({ // Disconnect Events const registerDisconnectEvents = (socket) => { const disconnect = () => { - createLogEvent(socket, "debug", `User disconnected.`); + // Uncomment for further testing + // createLogEvent(socket, "debug", `User disconnected.`); + const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id); for (const room of rooms) { socket.leave(room);